Finished (Kinda... Im juste f tired of this)

This commit is contained in:
2024-12-27 10:30:33 +01:00
parent c8215f7adb
commit feb7609ed6
3 changed files with 876 additions and 2 deletions

413
ctris_changes.patch Normal file
View File

@@ -0,0 +1,413 @@
diff --git a/Makefile b/Makefile
index 9831a3a..482f39c 100644
--- a/Makefile
+++ b/Makefile
@@ -2,12 +2,12 @@
MANDIR=$(DESTDIR)/usr/share/man/man6/
BINDIR=$(DESTDIR)/usr/games/
-CC=gcc
+CC=arm-buildroot-linux-musleabi-gcc
MKDIR=mkdir -p
INSTALL=install
-CFLAGS=-Wall -fomit-frame-pointer -O3
-LIBS=-lm -lncurses
+CFLAGS=-Wall -fomit-frame-pointer -O3 -I/home/moi/tp/lib/ncurses/buildNcurse/usr/include
+LIBS=-L/home/moi/tp/lib/ncurses/buildNcurse/usr/lib -lm -lncursesw
OBJS=ctris.o game.o screen.o brick.o highscore.o
OUTPUT=ctris
diff --git a/brick.o b/brick.o
new file mode 100644
index 0000000..8a0e376
Binary files /dev/null and b/brick.o differ
diff --git a/config.h b/config.h
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/config.h
@@ -0,0 +1 @@
+
diff --git a/ctris b/ctris
new file mode 100755
index 0000000..9ed491c
Binary files /dev/null and b/ctris differ
diff --git a/ctris.o b/ctris.o
new file mode 100644
index 0000000..5972bc7
Binary files /dev/null and b/ctris.o differ
diff --git a/game.c b/game.c
index 7a2bea0..b3d4a45 100644
--- a/game.c
+++ b/game.c
@@ -16,6 +16,20 @@ void init_board(char board[BOARD_HEIGHT][BOARD_WIDTH])
}
}
+// NEW CODE
+#define PATH_MODULE "/dev/mylab1_joystick"
+int fd;
+int buffer[5] = {1,1,1,1,1};
+int read_err;
+int init_mylab(){
+ fd = open(PATH_MODULE,O_RDONLY,S_IRUSR);
+ if(fd < 0){
+ printf("Could not retrieve mylab driver\n");
+ return fd;
+ }
+}
+//
+
void remove_this_row(WINDOW *win, char board[BOARD_HEIGHT][BOARD_WIDTH], unsigned char y)
{
unsigned char x;
@@ -88,6 +102,12 @@ unsigned int game_engine(bool resize)
static bool engine_stop = false;
show_headline();
+
+ // NEW CODE
+
+ init_mylab();
+
+ //
if (resize) {
if (game_state != PAUSED_STATE) {
@@ -147,7 +167,28 @@ unsigned int game_engine(bool resize)
while(game_state == RUNNING_STATE)
{
show_board_win(board_win, board, cur_brick, brick_type, x, y);
- switch(get_key(board_win))
+
+ int keyValue = get_key(board_win);
+
+ // NEW CODE
+ // Update KEY_STATE
+ read_err = read(fd,buffer,5 * sizeof(int));
+ if(read_err < 0)
+ printf("Could not read module\n");
+
+ if(!buffer[0])
+ keyValue = KEY_UP;
+ if(!buffer[1])
+ keyValue = KEY_DOWN;
+ if(!buffer[2])
+ keyValue = KEY_LEFT;
+ if(!buffer[3])
+ keyValue = KEY_RIGHT;
+ if(!buffer[4])
+ keyValue = 'p';
+ //
+
+ switch(keyValue)
{
case 's':
case KEY_DOWN:
@@ -278,5 +319,3 @@ unsigned int game_engine(bool resize)
engine_stop = true;
return score;
}
-
-
diff --git a/game.o b/game.o
new file mode 100644
index 0000000..1da7f4d
Binary files /dev/null and b/game.o differ
diff --git a/highscore.o b/highscore.o
new file mode 100644
index 0000000..44a44c1
Binary files /dev/null and b/highscore.o differ
diff --git a/oldgame.c b/oldgame.c
new file mode 100644
index 0000000..7a2bea0
--- /dev/null
+++ b/oldgame.c
@@ -0,0 +1,282 @@
+#include "ctris.h"
+#include "game.h"
+#include "brick.h"
+#include "screen.h"
+#include "highscore.h"
+
+void init_board(char board[BOARD_HEIGHT][BOARD_WIDTH])
+{
+ unsigned char i, n;
+ for(i = 0; i < BOARD_HEIGHT; i++)
+ {
+ for(n = 0; n < BOARD_WIDTH; n++)
+ {
+ board[i][n] = 0;
+ }
+ }
+}
+
+void remove_this_row(WINDOW *win, char board[BOARD_HEIGHT][BOARD_WIDTH], unsigned char y)
+{
+ unsigned char x;
+ show_remove_row(win, board, y);
+ for(; y > 0; y--)
+ {
+ for(x = 0; x < BOARD_WIDTH; x++)
+ {
+ board[y][x] = board[y - 1][x];
+ }
+ }
+}
+
+void remove_rows(WINDOW *win, char board[BOARD_HEIGHT][BOARD_WIDTH], unsigned int *score, const char level)
+{
+ char removed_rows = 0;
+ unsigned char x, y;
+ unsigned int sub_score = 0;
+ for(y = 0; y < BOARD_HEIGHT; y++)
+ {
+ for(x = 0; x < BOARD_WIDTH; x++)
+ {
+ if(board[y][x] == 0)
+ {
+ break;
+ }
+ }
+ if(x >= BOARD_WIDTH)
+ {
+ remove_this_row(win, board, y);
+ removed_rows++;
+ sub_score += BONUS_CONST * level * removed_rows;
+ }
+ }
+ *score += sub_score;
+ if(removed_rows > 0)
+ {
+ refresh_win(win);
+ usleep(REMOVE_SPLASH_TIME);
+ }
+}
+
+void calc_level(const unsigned int score, char *level)
+{
+ while(SPEED_CONST_2 - (*level + 1) * SPEED_CONST_1 >= 0 && score / (LEVEL_CONST * (unsigned int)pow((double)*level, 2)) > 0)
+ {
+ *level += 1;
+ }
+}
+
+void pause_game()
+{
+ game_engine(true);
+}
+
+unsigned int start_game()
+{
+ return game_engine(false);
+}
+
+unsigned int game_engine(bool resize)
+{
+ static char brick_type, next_brick_type, name[40], cur_brick[4][4], board[BOARD_HEIGHT][BOARD_WIDTH], level = 1;
+ char run;
+ unsigned int score = 0;
+ static unsigned long time = 0L;
+ unsigned int tick = 0;
+ static unsigned char x, y;
+ static WINDOW *board_win, *preview_win, *score_win;
+ static bool engine_stop = false;
+
+ show_headline();
+
+ if (resize) {
+ if (game_state != PAUSED_STATE) {
+ // if the game engine is in the RUNING_STATE then
+ // the resize call below will switch the engine to PAUSED_STATE
+
+ // if the game is in the QUIT_STATE then
+ // the call below will simulate a key being pressed
+ // and that will force the highscore screen or play_again dialog to be refreshed
+ put_key('p');
+ }
+
+ if (game_state == QUIT_STATE)
+ {
+ // if the game is in the highscore screen then refresh it upon resize
+ if (!engine_stop) {
+ show_highscore(name);
+ }
+ }
+ else
+ {
+ // here we will only have RUNNING_STATE, PAUSED_STATE or GAME_OVER_STATE
+ // both states coresponds to the main screen so
+ // the main screen will be refreshed upon resize
+ show_score(score_win, score, level, time);
+ show_brick_preview(preview_win, next_brick_type);
+ show_board_win(board_win, board, cur_brick, brick_type, x, y);
+ if (game_state == PAUSED_STATE) {
+ show_pause(board_win);
+ }
+ else if (game_state == GAME_OVER_STATE) {
+ show_game_over(board_win);
+ }
+ }
+ return score;
+ }
+
+ engine_stop = false;
+ board_win = (WINDOW *)create_board_win();
+ preview_win = (WINDOW *)create_preview_win();
+ score_win = (WINDOW *)create_score_win();
+ init_board(board);
+ show_score(score_win, score, level, time);
+ next_brick_type = get_rand(7) + 1;
+ game_state = PAUSED_STATE;
+ wait_for_start(board_win);
+ game_state = RUNNING_STATE;
+ while(game_state == RUNNING_STATE)
+ {
+ brick_type = next_brick_type;
+ next_brick_type = get_rand(7) + 1;
+ show_brick_preview(preview_win, next_brick_type);
+ memcpy(cur_brick, brick_digit[brick_type - 1], sizeof(char) * 4 * 4);
+ x = BOARD_WIDTH / 2;
+ y = 0;
+ run = 1;
+ while(game_state == RUNNING_STATE)
+ {
+ show_board_win(board_win, board, cur_brick, brick_type, x, y);
+ switch(get_key(board_win))
+ {
+ case 's':
+ case KEY_DOWN:
+ if(old_style_keys != 0)
+ {
+ if(counterclockwise_rotation == 1)
+ {
+ change_direction(board, cur_brick, x, y, -1);
+ }
+ else
+ {
+ change_direction(board, cur_brick, x, y, 1);
+ }
+ }
+ else
+ {
+ if(check_brick(board, cur_brick, x, y + 1) == 0)
+ {
+ y++;
+ }
+ }
+ break;
+ case 'w':
+ case 'k':
+ case KEY_UP:
+ if(counterclockwise_rotation == 1)
+ {
+ change_direction(board, cur_brick, x, y, 1);
+ }
+ else
+ {
+ change_direction(board, cur_brick, x, y, -1);
+ }
+ break;
+ case 'd':
+ case 'l':
+ case KEY_RIGHT:
+ if(check_brick(board, cur_brick, x + 1, y) == 0)
+ {
+ x++;
+ }
+ break;
+ case 'a':
+ case 'j':
+ case KEY_LEFT:
+ if(x > 0 && check_brick(board, cur_brick, x - 1, y) == 0)
+ {
+ x--;
+ }
+ break;
+ case ' ':
+ if(old_style_keys != 0)
+ {
+ if(check_brick(board, cur_brick, x, y + 1) == 0)
+ {
+ y++;
+ }
+ }
+ else
+ {
+ while(check_brick(board, cur_brick, x, y + 1) == 0)
+ {
+ y++;
+ }
+ }
+ break;
+ case 'p':
+ game_state = PAUSED_STATE;
+ show_pause(board_win);
+ while(old_get_key(board_win) != 'p');
+ game_state = RUNNING_STATE;
+ break;
+ case 'q':
+ game_state = QUIT_STATE;
+ break;
+ }
+ tick = SPEED_CONST_2 - level * SPEED_CONST_1;
+ time += tick;
+ show_score(score_win, score, level, time);
+ usleep(tick);
+ if(run > 15)
+ {
+ if(check_brick(board, cur_brick, x, y + 1) == 0)
+ {
+ y++;
+ run = 0;
+ }
+ else
+ {
+ if(y <= 1)
+ {
+ game_state = GAME_OVER_STATE;
+ show_game_over(board_win);
+ while(old_get_key(board_win) != ' ');
+ game_state = QUIT_STATE;
+ }
+ draw_to_board(board, cur_brick, brick_type, x, y);
+ show_board_win(board_win, board, cur_brick, brick_type, x, y);
+ remove_rows(board_win, board, &score, level);
+#ifdef EXTRA_BONUS
+ score += level;
+#endif
+ calc_level(score, &level);
+ show_score(score_win, score, level, time);
+ break;
+ }
+ }
+ run++;
+ }
+
+ }
+ destroy_score_win(score_win);
+ destroy_preview_win(preview_win);
+ destroy_board_win(board_win);
+ if(game_state == QUIT_STATE)
+ {
+ if(in_highscore(score) == 0)
+ {
+ add_user_to_highscore(name, score);
+ }
+ else
+ {
+ strncpy(name, "-no-name-", 40);
+ }
+ show_highscore(name);
+ getch();
+ }
+ engine_stop = true;
+ return score;
+}
+
+
diff --git a/screen.o b/screen.o
new file mode 100644
index 0000000..3ea2576
Binary files /dev/null and b/screen.o differ

321
game.c Normal file
View File

@@ -0,0 +1,321 @@
#include "ctris.h"
#include "game.h"
#include "brick.h"
#include "screen.h"
#include "highscore.h"
void init_board(char board[BOARD_HEIGHT][BOARD_WIDTH])
{
unsigned char i, n;
for(i = 0; i < BOARD_HEIGHT; i++)
{
for(n = 0; n < BOARD_WIDTH; n++)
{
board[i][n] = 0;
}
}
}
// NEW CODE
#define PATH_MODULE "/dev/mylab1_joystick"
int fd;
int buffer[5] = {1,1,1,1,1};
int read_err;
int init_mylab(){
fd = open(PATH_MODULE,O_RDONLY,S_IRUSR);
if(fd < 0){
printf("Could not retrieve mylab driver\n");
return fd;
}
}
//
void remove_this_row(WINDOW *win, char board[BOARD_HEIGHT][BOARD_WIDTH], unsigned char y)
{
unsigned char x;
show_remove_row(win, board, y);
for(; y > 0; y--)
{
for(x = 0; x < BOARD_WIDTH; x++)
{
board[y][x] = board[y - 1][x];
}
}
}
void remove_rows(WINDOW *win, char board[BOARD_HEIGHT][BOARD_WIDTH], unsigned int *score, const char level)
{
char removed_rows = 0;
unsigned char x, y;
unsigned int sub_score = 0;
for(y = 0; y < BOARD_HEIGHT; y++)
{
for(x = 0; x < BOARD_WIDTH; x++)
{
if(board[y][x] == 0)
{
break;
}
}
if(x >= BOARD_WIDTH)
{
remove_this_row(win, board, y);
removed_rows++;
sub_score += BONUS_CONST * level * removed_rows;
}
}
*score += sub_score;
if(removed_rows > 0)
{
refresh_win(win);
usleep(REMOVE_SPLASH_TIME);
}
}
void calc_level(const unsigned int score, char *level)
{
while(SPEED_CONST_2 - (*level + 1) * SPEED_CONST_1 >= 0 && score / (LEVEL_CONST * (unsigned int)pow((double)*level, 2)) > 0)
{
*level += 1;
}
}
void pause_game()
{
game_engine(true);
}
unsigned int start_game()
{
return game_engine(false);
}
unsigned int game_engine(bool resize)
{
static char brick_type, next_brick_type, name[40], cur_brick[4][4], board[BOARD_HEIGHT][BOARD_WIDTH], level = 1;
char run;
unsigned int score = 0;
static unsigned long time = 0L;
unsigned int tick = 0;
static unsigned char x, y;
static WINDOW *board_win, *preview_win, *score_win;
static bool engine_stop = false;
show_headline();
// NEW CODE
init_mylab();
//
if (resize) {
if (game_state != PAUSED_STATE) {
// if the game engine is in the RUNING_STATE then
// the resize call below will switch the engine to PAUSED_STATE
// if the game is in the QUIT_STATE then
// the call below will simulate a key being pressed
// and that will force the highscore screen or play_again dialog to be refreshed
put_key('p');
}
if (game_state == QUIT_STATE)
{
// if the game is in the highscore screen then refresh it upon resize
if (!engine_stop) {
show_highscore(name);
}
}
else
{
// here we will only have RUNNING_STATE, PAUSED_STATE or GAME_OVER_STATE
// both states coresponds to the main screen so
// the main screen will be refreshed upon resize
show_score(score_win, score, level, time);
show_brick_preview(preview_win, next_brick_type);
show_board_win(board_win, board, cur_brick, brick_type, x, y);
if (game_state == PAUSED_STATE) {
show_pause(board_win);
}
else if (game_state == GAME_OVER_STATE) {
show_game_over(board_win);
}
}
return score;
}
engine_stop = false;
board_win = (WINDOW *)create_board_win();
preview_win = (WINDOW *)create_preview_win();
score_win = (WINDOW *)create_score_win();
init_board(board);
show_score(score_win, score, level, time);
next_brick_type = get_rand(7) + 1;
game_state = PAUSED_STATE;
wait_for_start(board_win);
game_state = RUNNING_STATE;
while(game_state == RUNNING_STATE)
{
brick_type = next_brick_type;
next_brick_type = get_rand(7) + 1;
show_brick_preview(preview_win, next_brick_type);
memcpy(cur_brick, brick_digit[brick_type - 1], sizeof(char) * 4 * 4);
x = BOARD_WIDTH / 2;
y = 0;
run = 1;
while(game_state == RUNNING_STATE)
{
show_board_win(board_win, board, cur_brick, brick_type, x, y);
int keyValue = get_key(board_win);
// NEW CODE
// Update KEY_STATE
read_err = read(fd,buffer,5 * sizeof(int));
if(read_err < 0)
printf("Could not read module\n");
if(!buffer[0])
keyValue = KEY_UP;
if(!buffer[1])
keyValue = KEY_DOWN;
if(!buffer[2])
keyValue = KEY_LEFT;
if(!buffer[3])
keyValue = KEY_RIGHT;
if(!buffer[4])
keyValue = 'p';
//
switch(keyValue)
{
case 's':
case KEY_DOWN:
if(old_style_keys != 0)
{
if(counterclockwise_rotation == 1)
{
change_direction(board, cur_brick, x, y, -1);
}
else
{
change_direction(board, cur_brick, x, y, 1);
}
}
else
{
if(check_brick(board, cur_brick, x, y + 1) == 0)
{
y++;
}
}
break;
case 'w':
case 'k':
case KEY_UP:
if(counterclockwise_rotation == 1)
{
change_direction(board, cur_brick, x, y, 1);
}
else
{
change_direction(board, cur_brick, x, y, -1);
}
break;
case 'd':
case 'l':
case KEY_RIGHT:
if(check_brick(board, cur_brick, x + 1, y) == 0)
{
x++;
}
break;
case 'a':
case 'j':
case KEY_LEFT:
if(x > 0 && check_brick(board, cur_brick, x - 1, y) == 0)
{
x--;
}
break;
case ' ':
if(old_style_keys != 0)
{
if(check_brick(board, cur_brick, x, y + 1) == 0)
{
y++;
}
}
else
{
while(check_brick(board, cur_brick, x, y + 1) == 0)
{
y++;
}
}
break;
case 'p':
game_state = PAUSED_STATE;
show_pause(board_win);
while(old_get_key(board_win) != 'p');
game_state = RUNNING_STATE;
break;
case 'q':
game_state = QUIT_STATE;
break;
}
tick = SPEED_CONST_2 - level * SPEED_CONST_1;
time += tick;
show_score(score_win, score, level, time);
usleep(tick);
if(run > 15)
{
if(check_brick(board, cur_brick, x, y + 1) == 0)
{
y++;
run = 0;
}
else
{
if(y <= 1)
{
game_state = GAME_OVER_STATE;
show_game_over(board_win);
while(old_get_key(board_win) != ' ');
game_state = QUIT_STATE;
}
draw_to_board(board, cur_brick, brick_type, x, y);
show_board_win(board_win, board, cur_brick, brick_type, x, y);
remove_rows(board_win, board, &score, level);
#ifdef EXTRA_BONUS
score += level;
#endif
calc_level(score, &level);
show_score(score_win, score, level, time);
break;
}
}
run++;
}
}
destroy_score_win(score_win);
destroy_preview_win(preview_win);
destroy_board_win(board_win);
if(game_state == QUIT_STATE)
{
if(in_highscore(score) == 0)
{
add_user_to_highscore(name, score);
}
else
{
strncpy(name, "-no-name-", 40);
}
show_highscore(name);
getch();
}
engine_stop = true;
return score;
}

144
tp6.md
View File

@@ -492,7 +492,7 @@ Quand le kernel a fini d'être compilé on peut faire un `make` pour compiler no
On va avoir besoin du .ko pour tester notre module.
`sudo insmod mymodule.ko`
`insmod mymodule.ko`
Le resultat de la commande est :
@@ -944,6 +944,37 @@ en
A defaut d'avoir un fichier .profile dans /etc
EDIT:
Cette methode avait l'air de marcher en serie mais avec Telnet plus tard il faut utiliser une autre methode :
Il faut ajouter `export TERM=linux`
dans `/etc/init.d/rcS`
```bash
#!/bin/sh
# sets the terminal
export TERM=linux
# Start all init scripts in /etc/init.d
# executing them in numeric order.
for i in /etc/init.d/S??*; do
case "$i" in
*.sh)
# Source shell script for speed.
. "$i"
;;
*)
# No .sh extension, so fork subprocess.
"$i" start
;;
esac
done
```
## [Q7] Quelle en est la raison à votre avis ?
Bon honnêtement je n'ai pas spécialement vu de ralentissement et je trouvais pas le jeu peu fluide mais la raison pour laquelle ca n'est pas aussi fluide que sur un vrai écran natif c'est que tout est envoyé caractère par caractère en série et donc forcément ca pue un peu pour des applications qui utilisent ncurses qui demande beaucoup de caractères par seconde pour mettre à jour tout l'écran.
@@ -992,7 +1023,7 @@ Pour faire en sorte que le serveur telnetd soit lancé au démarrage on peut cr
`vi Stelnetd.sh`
```
```bash
#!/bin/sh
mkdir /dev/pts
mount -t devpts devpts /dev/pts
@@ -1005,6 +1036,115 @@ Et avec ca, après chaque reboot ce script est lancé et je peut accèder au sys
## Modification de CTRIS pour utiliser le joystick de la carte MyLab1
Bon on est pas la pour faire du super beau code ou quoi que ce soit donc j'ai juste été dans le fichier game.c et j'ai ajouté cette methode :
```c
#define PATH_MODULE "/dev/mylab1_joystick"
int fd;
int buffer[5] = {1,1,1,1,1};
int read_err;
int init_mylab(){
fd = open(PATH_MODULE,O_RDONLY,S_IRUSR);
if(fd < 0){
printf("Could not retrieve mylab driver\n");
return fd;
}
}
```
Ensuite dans la fonction game_engine() j'ai ajouté cette ligne
`init_mylab();` au début pour que le driver soit load au début du game engine.
Ensuite le switch case avant se trouvait comme cela :
`switch(get_key(board_win))`
Je l'ai courcircuité de cette facon
```c
int keyValue = get_key(board_win);
switch(keyValue){}
```
Ce qui me permet ensuite de venir me plugger comme un petit parasite et interferer avec les touches detectées :
```c
int keyValue = get_key(board_win);
read_err = read(fd,buffer,5 * sizeof(int));
if(read_err < 0)
printf("Could not read module\n");
if(!buffer[0])
keyValue = KEY_UP;
if(!buffer[1])
keyValue = KEY_DOWN;
if(!buffer[2])
keyValue = KEY_LEFT;
if(!buffer[3])
keyValue = KEY_RIGHT;
if(!buffer[4])
keyValue = 'p';
switch(keyValue){}
```
Seule différence avec l'énoncé c'est que j'ai mis le bouton du milieu comme pause je trouve que c'est mieux mais pour remettre sur espace c'est vraiment une ligne à changer.
De cette manière si le user utilise des touches sur son clavier, on ne change rien au comportement, mais si on utilise le joystick ca override les valeurs.
C'est un peu degeu mais bon.
Ensuite quand on compile et que on lance le jeu on peut voir que ca ne marche pas evidemment car j'ai redémarré la board et le driver n'est plus chargé.
Je crée donc un un fichier Smylab1DriverLoad.sh dans /etc/init.d/ qui ressemble à ca :
```bash
#!/bin/sh
insmod /lib/modules/6.6.56/kernel/drivers/gpio/mymodule.ko
```
Et la quand on redemarre le systeme embarqué, le module est chargé par défaut.
Bon avec tout ca j'ai essayé de jouer a CTRIS et en vrai ca passe. C'est pas le plus facile car le joystick est très sensible sans sleep mais c'est jouable juste pas facile.
Après désolé mais faire un joli petit truc modulaire avec des jolies fonctions faites exprès la GROSSE FLEMME. Ce tp est déja beaucoup trop long j'en ai d'autres sur lesquels ruiner le reste de mes vacances ainsi que mes revisions.
pour crééer un patch :
`git add -A`
`git diff > ctris_changes.patch`
## [Q9] Expliquez comment vous avez modifié le code de CTRIS afin que celui-ci utilise le joystick de votre carte MyLab1 et que le jeu reste jouable. Créez un patch avec le code complet de vos changements (en incluant le Makefile) et indiquez où il se trouve sur votre git.
Les modifications sont expliquées plus haut
Le fichier game.c dans la racine du git contient le fichier game.c modifié avec mon code.
Ensuite le fichier ctris_changes.patch aussi à la racine est le fichier qui contient le patch de toutes mes modifications sur le repo du jeu ctris
## Integration sécurisée
On va créer un user qui s'occupera de lancer notre module
`adduser -D -H -G nogroup -s /bin/false gpio_mylab`
On change ensuite le Stelnetd.sh en
```bash
#!/bin/sh
mkdir /dev/pts
mount -t devpts devpts /dev/pts
telnetd -u gpio_mylab
```