|
|
## 2.2 sevenseg.c
|
|
|
### 2.2.1 Header-Files und Definition von Makros
|
|
|
Damit alle Funktionen der im Code verwendeten Funktionen funktionieren müssen einige Header-Files eingebunden werden:
|
|
|
Damit alle der im Code verwendeten Funktionen funktionieren müssen einige Header-Files eingebunden werden:
|
|
|
```
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/module.h>
|
... | ... | @@ -19,21 +19,21 @@ Damit alle Funktionen der im Code verwendeten Funktionen funktionieren müssen e |
|
|
- linux/kernel.h : Headerfile für die KERN_INFO Ausgabe
|
|
|
|
|
|
```
|
|
|
#define A1 17 // Pin 17 wird durch A1 ersetzt (7SEG a)
|
|
|
#define A2 27 // Pin 27 wird durch A2 ersetzt (7SEG b)
|
|
|
#define A3 22 // Pin 12 wird durch A3 ersetzt (7SEG c)
|
|
|
#define A4 5 // Pin 5 wird durch A4 ersetzt (7SEG d)
|
|
|
#define A5 6 // Pin 6 wird durch A5 ersetzt (7SEG e)
|
|
|
#define A6 13 // Pin 13 wird durch A6 ersetzt (7SEG f)
|
|
|
#define A7 19 // Pin 19 wird durch A7 ersetzt (7SEG g)
|
|
|
#define A8 26 // Pin 26 wird durch A8 ersetzt (7SEG dot)
|
|
|
#define Sa 17 // Pin 17 wird durch Sa ersetzt (7SEG a)
|
|
|
#define Sb 27 // Pin 27 wird durch Sb ersetzt (7SEG b)
|
|
|
#define Sc 22 // Pin 12 wird durch Sc ersetzt (7SEG c)
|
|
|
#define Sd 5 // Pin 5 wird durch Sd ersetzt (7SEG d)
|
|
|
#define Se 6 // Pin 6 wird durch Se ersetzt (7SEG e)
|
|
|
#define Sf 13 // Pin 13 wird durch Sf ersetzt (7SEG f)
|
|
|
#define Sg 19 // Pin 19 wird durch Sg ersetzt (7SEG g)
|
|
|
#define Sp 26 // Pin 26 wird durch Sp ersetzt (7SEG dot)
|
|
|
|
|
|
#define SUCCESS 0
|
|
|
#define DEVICE_NAME "sevenseg" // Device-Name
|
|
|
#define BUF_LEN 1 /* Maximale Länge der Nachricht vom Treiber */
|
|
|
#define BUF_LEN 1 // Maximale Länge einer Nachricht
|
|
|
```
|
|
|
|
|
|
### 2.2.2 Lizensierung und Modul Dokumentation
|
|
|
### 2.2.2 Lizensierung und Modul-Dokumentation
|
|
|
|
|
|
```c
|
|
|
MODULE_LICENSE("GPL");
|
... | ... | @@ -61,46 +61,46 @@ vermagic: 4.9.62-v7+ SMP mod_unload modversions ARMv7 p2v8 |
|
|
```
|
|
|
|
|
|
### 2.2.3 GPIO-Implementierung
|
|
|
Um die 7-Segemntanzeige an einem Raspberry Pi zu betreiben müssen die GPIO-Pins (engl. GPIO – general purpose input/output) über den Treiber angesprochen und verwaltet werden die sgeschieht im folgenden Abschnitt.
|
|
|
Um die 7-Segemntanzeige an einem Raspberry Pi zu betreiben müssen die GPIO-Pins (engl. GPIO – general purpose input/output) über den Treiber angesprochen und verwaltet werden dies geschieht im folgenden Abschnitt.
|
|
|
Als erstes müssen die Pins initialisiert werden:
|
|
|
```c
|
|
|
void seven_gpio_init(void) {
|
|
|
void seven_gpio_init(void) { //Initialisiert die GPIO-Pins (gpio_request)
|
|
|
printk(KERN_INFO "SEVENSEG: starting gpio...");
|
|
|
gpio_request(A1, "A1");
|
|
|
gpio_request(A2, "A2");
|
|
|
gpio_request(A3, "A3");
|
|
|
gpio_request(A4, "A4");
|
|
|
gpio_request(A5, "A5");
|
|
|
gpio_request(A6, "A6");
|
|
|
gpio_request(A7, "A7");
|
|
|
gpio_request(A8, "A8");
|
|
|
|
|
|
gpio_direction_output(A1, 0);
|
|
|
gpio_direction_output(A2, 0);
|
|
|
gpio_direction_output(A3, 0);
|
|
|
gpio_direction_output(A4, 0);
|
|
|
gpio_direction_output(A5, 0);
|
|
|
gpio_direction_output(A6, 0);
|
|
|
gpio_direction_output(A7, 0);
|
|
|
gpio_direction_output(A8, 0);
|
|
|
gpio_request(Sa, "Sa");
|
|
|
gpio_request(Sb, "Sb");
|
|
|
gpio_request(Sc, "Sc");
|
|
|
gpio_request(Sd, "Sd");
|
|
|
gpio_request(Se, "Se");
|
|
|
gpio_request(Sf, "Sf");
|
|
|
gpio_request(Sg, "Sg");
|
|
|
gpio_request(Sp, "Sp");
|
|
|
|
|
|
gpio_direction_output(Sa, 0); //Legt fest das der Pin als Output-Pin ansprechbar ist (gpio_direction_output)
|
|
|
gpio_direction_output(Sb, 0);
|
|
|
gpio_direction_output(Sc, 0);
|
|
|
gpio_direction_output(Sd, 0);
|
|
|
gpio_direction_output(Se, 0);
|
|
|
gpio_direction_output(Sf, 0);
|
|
|
gpio_direction_output(Sg, 0);
|
|
|
gpio_direction_output(Sp, 0);
|
|
|
printk(KERN_INFO "SEVENSEG: starting gpio done.");
|
|
|
}
|
|
|
```
|
|
|
Die GPIO-Pins müssen zuerst für das Modul reserviert werden, dies wird mit `gpio_request(unsigned int gpio, const char *label)` erreicht.
|
|
|
Um mit den Pins arbeiten zu können muss noch festgelegt werden, dass es Output-Pins sind was, mit `gpio_direction_output(unsigned int gpio, int value)` bewerkstelligt wird.
|
|
|
Um mit den Pins arbeiten zu können muss noch festgelegt werden, dass es Output-Pins sind, was mit `gpio_direction_output(unsigned int gpio, int value)` bewerkstelligt wird.
|
|
|
|
|
|
Wenn man das Modul entladen will müssen die GPIO-Pins wieder freigegeben werden was im folgenden Codeabschnitt durch `gpio_free(const int gpio)` realisiert wurde:
|
|
|
```c
|
|
|
void seven_gpio_exit(void) { //Beim Rausladen des LKM werden die Pins wieder freigegeben (gpio_free)
|
|
|
printk(KERN_INFO "SEVENSEG: stopping gpio...");
|
|
|
gpio_free(A1);
|
|
|
gpio_free(A2);
|
|
|
gpio_free(A3);
|
|
|
gpio_free(A4);
|
|
|
gpio_free(A5);
|
|
|
gpio_free(A6);
|
|
|
gpio_free(A7);
|
|
|
gpio_free(A8);
|
|
|
gpio_free(Sa);
|
|
|
gpio_free(Sb);
|
|
|
gpio_free(Sc);
|
|
|
gpio_free(Sd);
|
|
|
gpio_free(Se);
|
|
|
gpio_free(Sf);
|
|
|
gpio_free(Sg);
|
|
|
gpio_free(Sp);
|
|
|
printk(KERN_INFO "SEVENSEG: stopping gpio done.");
|
|
|
}
|
|
|
```
|
... | ... | @@ -112,117 +112,185 @@ void seven_status(int display) { //Switch-case fuer die Anzeigemoeg |
|
|
|
|
|
switch (display) {
|
|
|
case 0 :
|
|
|
gpio_set_value(A1, 0);
|
|
|
gpio_set_value(A2, 0);
|
|
|
gpio_set_value(A3, 0);
|
|
|
gpio_set_value(A4, 0);
|
|
|
gpio_set_value(A5, 0); // 7-Segment zeigt 0 an
|
|
|
gpio_set_value(A6, 0);
|
|
|
gpio_set_value(A7, 0);
|
|
|
gpio_set_value(A8, 0);
|
|
|
gpio_set_value(Sa, 0);
|
|
|
gpio_set_value(Sb, 0);
|
|
|
gpio_set_value(Sc, 0);
|
|
|
gpio_set_value(Sd, 0);
|
|
|
gpio_set_value(Se, 0); // 7-Segment zeigt 0 an
|
|
|
gpio_set_value(Sf, 0);
|
|
|
gpio_set_value(Sg, 1);
|
|
|
gpio_set_value(Sp, 1);
|
|
|
break;
|
|
|
case 1:
|
|
|
gpio_set_value(A1, 1);
|
|
|
gpio_set_value(A2, 1);
|
|
|
gpio_set_value(A3, 1);
|
|
|
gpio_set_value(A4, 1);
|
|
|
gpio_set_value(A5, 1); // 7-Segment zeigt 1 an
|
|
|
gpio_set_value(A6, 1);
|
|
|
gpio_set_value(A7, 1);
|
|
|
gpio_set_value(A8, 1);
|
|
|
gpio_set_value(Sa, 1);
|
|
|
gpio_set_value(Sb, 0);
|
|
|
gpio_set_value(Sc, 0);
|
|
|
gpio_set_value(Sd, 1);
|
|
|
gpio_set_value(Se, 1); // 7-Segment zeigt 1 an
|
|
|
gpio_set_value(Sf, 1);
|
|
|
gpio_set_value(Sg, 1);
|
|
|
gpio_set_value(Sp, 1);
|
|
|
break;
|
|
|
case 2:
|
|
|
gpio_set_value(A1, 0);
|
|
|
gpio_set_value(A2, 0);
|
|
|
gpio_set_value(A3, 0);
|
|
|
gpio_set_value(A4, 0);
|
|
|
gpio_set_value(A5, 0); // 7-Segment zeigt 2 an
|
|
|
gpio_set_value(A6, 0);
|
|
|
gpio_set_value(A7, 0);
|
|
|
gpio_set_value(A8, 0);
|
|
|
gpio_set_value(Sa, 0);
|
|
|
gpio_set_value(Sb, 0);
|
|
|
gpio_set_value(Sc, 1);
|
|
|
gpio_set_value(Sd, 0);
|
|
|
gpio_set_value(Se, 0); // 7-Segment zeigt 2 an
|
|
|
gpio_set_value(Sf, 1);
|
|
|
gpio_set_value(Sg, 0);
|
|
|
gpio_set_value(Sp, 1);
|
|
|
break;
|
|
|
case 3:
|
|
|
gpio_set_value(A1, 0);
|
|
|
gpio_set_value(A2, 0);
|
|
|
gpio_set_value(A3, 0);
|
|
|
gpio_set_value(A4, 0);
|
|
|
gpio_set_value(A5, 0); // 7-Segment zeigt 3 an
|
|
|
gpio_set_value(A6, 0);
|
|
|
gpio_set_value(A7, 0);
|
|
|
gpio_set_value(A8, 0);
|
|
|
gpio_set_value(Sa, 0);
|
|
|
gpio_set_value(Sb, 0);
|
|
|
gpio_set_value(Sc, 0);
|
|
|
gpio_set_value(Sd, 0);
|
|
|
gpio_set_value(Se, 1); // 7-Segment zeigt 3 an
|
|
|
gpio_set_value(Sf, 1);
|
|
|
gpio_set_value(Sg, 0);
|
|
|
gpio_set_value(Sp, 1);
|
|
|
break;
|
|
|
case 4:
|
|
|
gpio_set_value(A1, 0);
|
|
|
gpio_set_value(A2, 0);
|
|
|
gpio_set_value(A3, 0);
|
|
|
gpio_set_value(A4, 0);
|
|
|
gpio_set_value(A5, 0); // 7-Segment zeigt 4 an
|
|
|
gpio_set_value(A6, 0);
|
|
|
gpio_set_value(A7, 0);
|
|
|
gpio_set_value(A8, 0);
|
|
|
gpio_set_value(Sa, 1);
|
|
|
gpio_set_value(Sb, 0);
|
|
|
gpio_set_value(Sc, 0);
|
|
|
gpio_set_value(Sd, 1);
|
|
|
gpio_set_value(Se, 1); // 7-Segment zeigt 4 an
|
|
|
gpio_set_value(Sf, 0);
|
|
|
gpio_set_value(Sg, 0);
|
|
|
gpio_set_value(Sp, 1);
|
|
|
break;
|
|
|
case 5:
|
|
|
gpio_set_value(A1, 0);
|
|
|
gpio_set_value(A2, 0);
|
|
|
gpio_set_value(A3, 0);
|
|
|
gpio_set_value(A4, 0);
|
|
|
gpio_set_value(A5, 0); // 7-Segment zeigt 5 an
|
|
|
gpio_set_value(A6, 0);
|
|
|
gpio_set_value(A7, 0);
|
|
|
gpio_set_value(A8, 0);
|
|
|
gpio_set_value(Sa, 0);
|
|
|
gpio_set_value(Sb, 1);
|
|
|
gpio_set_value(Sc, 0);
|
|
|
gpio_set_value(Sd, 0);
|
|
|
gpio_set_value(Se, 1); // 7-Segment zeigt 5 an
|
|
|
gpio_set_value(Sf, 0);
|
|
|
gpio_set_value(Sg, 0);
|
|
|
gpio_set_value(Sp, 1);
|
|
|
break;
|
|
|
case 6:
|
|
|
gpio_set_value(A1, 0);
|
|
|
gpio_set_value(A2, 0);
|
|
|
gpio_set_value(A3, 0);
|
|
|
gpio_set_value(A4, 0);
|
|
|
gpio_set_value(A5, 0); // 7-Segment zeigt 6 an
|
|
|
gpio_set_value(A6, 0);
|
|
|
gpio_set_value(A7, 0);
|
|
|
gpio_set_value(A8, 0);
|
|
|
gpio_set_value(Sa, 0);
|
|
|
gpio_set_value(Sb, 1);
|
|
|
gpio_set_value(Sc, 0);
|
|
|
gpio_set_value(Sd, 0);
|
|
|
gpio_set_value(Se, 0); // 7-Segment zeigt 6 an
|
|
|
gpio_set_value(Sf, 0);
|
|
|
gpio_set_value(Sg, 0);
|
|
|
gpio_set_value(Sp, 0);
|
|
|
break;
|
|
|
case 7:
|
|
|
gpio_set_value(A1, 0);
|
|
|
gpio_set_value(A2, 0);
|
|
|
gpio_set_value(A3, 0);
|
|
|
gpio_set_value(A4, 0);
|
|
|
gpio_set_value(A5, 0); // 7-Segment zeigt 7 an
|
|
|
gpio_set_value(A6, 0);
|
|
|
gpio_set_value(A7, 0);
|
|
|
gpio_set_value(A8, 0);
|
|
|
gpio_set_value(Sa, 0);
|
|
|
gpio_set_value(Sb, 0);
|
|
|
gpio_set_value(Sc, 0);
|
|
|
gpio_set_value(Sd, 1);
|
|
|
gpio_set_value(Se, 1); // 7-Segment zeigt 7 an
|
|
|
gpio_set_value(Sf, 1);
|
|
|
gpio_set_value(Sg, 1);
|
|
|
gpio_set_value(Sp, 1);
|
|
|
break;
|
|
|
case 8:
|
|
|
gpio_set_value(A1, 0);
|
|
|
gpio_set_value(A2, 0);
|
|
|
gpio_set_value(A3, 0);
|
|
|
gpio_set_value(A4, 0);
|
|
|
gpio_set_value(A5, 0); // 7-Segment zeigt 8 an
|
|
|
gpio_set_value(A6, 0);
|
|
|
gpio_set_value(A7, 0);
|
|
|
gpio_set_value(A8, 0);
|
|
|
gpio_set_value(Sa, 0);
|
|
|
gpio_set_value(Sb, 0);
|
|
|
gpio_set_value(Sc, 0);
|
|
|
gpio_set_value(Sd, 0);
|
|
|
gpio_set_value(Se, 0); // 7-Segment zeigt 8 an
|
|
|
gpio_set_value(Sf, 0);
|
|
|
gpio_set_value(Sg, 0);
|
|
|
gpio_set_value(Sp, 1);
|
|
|
break;
|
|
|
case 9:
|
|
|
gpio_set_value(A1, 0);
|
|
|
gpio_set_value(A2, 0);
|
|
|
gpio_set_value(A3, 0);
|
|
|
gpio_set_value(A4, 0);
|
|
|
gpio_set_value(A5, 0); // 7-Segment zeigt 9 an
|
|
|
gpio_set_value(A6, 0);
|
|
|
gpio_set_value(A7, 0);
|
|
|
gpio_set_value(A8, 0);
|
|
|
gpio_set_value(Sa, 0);
|
|
|
gpio_set_value(Sb, 0);
|
|
|
gpio_set_value(Sc, 0);
|
|
|
gpio_set_value(Sd, 0);
|
|
|
gpio_set_value(Se, 1); // 7-Segment zeigt 9 an
|
|
|
gpio_set_value(Sf, 0);
|
|
|
gpio_set_value(Sg, 0);
|
|
|
gpio_set_value(Sp, 1);
|
|
|
break;
|
|
|
|
|
|
case 'a':
|
|
|
gpio_set_value(Sa, 1);
|
|
|
gpio_set_value(Sb, 1);
|
|
|
gpio_set_value(Sc, 0);
|
|
|
gpio_set_value(Sd, 0);
|
|
|
gpio_set_value(Se, 0); // 7-Segment zeigt a an
|
|
|
gpio_set_value(Sf, 1);
|
|
|
gpio_set_value(Sg, 0);
|
|
|
gpio_set_value(Sp, 1);
|
|
|
break;
|
|
|
case 'b':
|
|
|
gpio_set_value(Sa, 1);
|
|
|
gpio_set_value(Sb, 1);
|
|
|
gpio_set_value(Sc, 0);
|
|
|
gpio_set_value(Sd, 0);
|
|
|
gpio_set_value(Se, 0); // 7-Segment zeigt b an
|
|
|
gpio_set_value(Sf, 0);
|
|
|
gpio_set_value(Sg, 0);
|
|
|
gpio_set_value(Sp, 1);
|
|
|
break;
|
|
|
case 'c':
|
|
|
gpio_set_value(Sa, 1);
|
|
|
gpio_set_value(Sb, 1);
|
|
|
gpio_set_value(Sc, 1);
|
|
|
gpio_set_value(Sd, 0);
|
|
|
gpio_set_value(Se, 0); // 7-Segment zeigt c an
|
|
|
gpio_set_value(Sf, 1);
|
|
|
gpio_set_value(Sg, 0);
|
|
|
gpio_set_value(Sp, 1);
|
|
|
break;
|
|
|
case 'd':
|
|
|
gpio_set_value(Sa, 1);
|
|
|
gpio_set_value(Sb, 0);
|
|
|
gpio_set_value(Sc, 0);
|
|
|
gpio_set_value(Sd, 0);
|
|
|
gpio_set_value(Se, 0); // 7-Segment zeigt d an
|
|
|
gpio_set_value(Sf, 1);
|
|
|
gpio_set_value(Sg, 0);
|
|
|
gpio_set_value(Sp, 1);
|
|
|
break;
|
|
|
case 'e':
|
|
|
gpio_set_value(Sa, 0);
|
|
|
gpio_set_value(Sb, 1);
|
|
|
gpio_set_value(Sc, 1);
|
|
|
gpio_set_value(Sd, 0);
|
|
|
gpio_set_value(Se, 0); // 7-Segment zeigt e an
|
|
|
gpio_set_value(Sf, 0);
|
|
|
gpio_set_value(Sg, 0);
|
|
|
gpio_set_value(Sp, 1);
|
|
|
break;
|
|
|
case 'f':
|
|
|
gpio_set_value(Sa, 0);
|
|
|
gpio_set_value(Sb, 1);
|
|
|
gpio_set_value(Sc, 1);
|
|
|
gpio_set_value(Sd, 1);
|
|
|
gpio_set_value(Se, 0); // 7-Segment zeigt f an
|
|
|
gpio_set_value(Sf, 0);
|
|
|
gpio_set_value(Sg, 0);
|
|
|
gpio_set_value(Sp, 1);
|
|
|
break;
|
|
|
|
|
|
|
|
|
default:
|
|
|
gpio_set_value(A1, 1);
|
|
|
gpio_set_value(A2, 1);
|
|
|
gpio_set_value(A3, 1);
|
|
|
gpio_set_value(A4, 1);
|
|
|
gpio_set_value(A5, 1); //default alle Pins auf LOW gesetzt
|
|
|
gpio_set_value(A6, 1);
|
|
|
gpio_set_value(A7, 1);
|
|
|
gpio_set_value(A8, 1);
|
|
|
gpio_set_value(Sa, 1);
|
|
|
gpio_set_value(Sb, 1);
|
|
|
gpio_set_value(Sc, 1);
|
|
|
gpio_set_value(Sd, 1);
|
|
|
gpio_set_value(Se, 1); //default alle Pins auf LOW gesetzt
|
|
|
gpio_set_value(Sf, 1);
|
|
|
gpio_set_value(Sg, 1);
|
|
|
gpio_set_value(Sp, 1);
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
Nachdem die Funktion mit der gewünschten Ausgabe `seven_status(int display)` aufgerufen wurde, werden in der switch-case-Funktion die GPIO-Pins angesprochen
|
... | ... | @@ -234,7 +302,7 @@ Quelle: [GPIO in the kernel] (https://lwn.net/Articles/532714/) |
|
|
Um später mit dem Treiber im Kernel-Space kommunizieren zu können, wird ein Character Device Driver benötigt, der im Kernel-Space eine Node-Datei erstellt, auf die der User
|
|
|
mit `& echo "display" >> /dev/sevenseg` schreiben kann und das Modul die Eingabe verarbeitet.
|
|
|
|
|
|
Als erstes wird hierzu folgende globale Variablen und Strukturfunktionen:
|
|
|
Als erstes werden hierzu folgende globale Variablen und Strukturfunktionen erstellt:
|
|
|
```c
|
|
|
/* Globale Variablen für die Chracter-Device-Schnittstelle */
|
|
|
static ssize_t seven_write(struct file *, const char *, size_t, loff_t *);
|
... | ... | @@ -256,16 +324,16 @@ Man kann seine eigene Major Nummer bestimmen muss aber darauf achten das sie noc |
|
|
`register_chrdev(unsigned int major, const char *name, struct file_operations *fops)` bei `unsigned int major` 0 ein und lässt sich dann durch die Rückgabe eine freie Major Nummer zuteilen
|
|
|
wie im folgenden Code-Abschnitt:
|
|
|
```c
|
|
|
int seven_dev_init(void)
|
|
|
int seven_dev_init(void) //Wird aufgerufen wenn das Modul geladen wird
|
|
|
{
|
|
|
Major = register_chrdev(0, DEVICE_NAME, &seven_fops);
|
|
|
Major = register_chrdev(0, DEVICE_NAME, &seven_fops); //Registrierung eines Chardevice
|
|
|
|
|
|
if (Major < 0) {
|
|
|
printk(KERN_ALERT "SEVENSEG: Registering char device failed with %d\n", Major);
|
|
|
return Major;
|
|
|
}
|
|
|
printk(KERN_INFO "SEVENSEG: sevenseg driver loaded with major %d\n", Major);
|
|
|
printk(KERN_INFO "SEVENSEG: >> $ mknod /dev/%s c %d 0\n", DEVICE_NAME, Major); //Info welche Nodedatei mit welchen Parametern erstellt werden soll
|
|
|
printk(KERN_INFO "SEVENSEG: >> $ mknod /dev/%s c %d 0\n", DEVICE_NAME, Major); //Info welche Nodedatei mit welchen parametern erstellt werden soll
|
|
|
|
|
|
msg = (char *)kmalloc(32, GFP_KERNEL); //Speicherreservierung fuer die Uebertragung von Kernelspace zu Userspace
|
|
|
if (msg != NULL)
|
... | ... | @@ -275,11 +343,11 @@ int seven_dev_init(void) |
|
|
```
|
|
|
Mit der KERN_INFO lassen wir uns hier den genauen Pfad ausgeben in der die Node Datei erstellt werden soll in unserem Fall wird mit
|
|
|
|
|
|
> $ mknod /dev/sevenseg 257 0
|
|
|
> $ mknod /dev/sevenseg 243 0
|
|
|
|
|
|
eine Datei mit Majornummer 257 und Minor-Nummer 0 angelegt. Die Minor Nummer wird nur verwendet wenn ein Treiber mehrere Geräte ansprechen soll.
|
|
|
eine Datei mit Major Nummer 243 und Minor-Nummer 0 angelegt. Die Minor Nummer wird nur verwendet wenn ein Treiber mehrere Geräte ansprechen soll.
|
|
|
|
|
|
Zu guter letzt muss noch Speicher für die Übertragung des Puffers reserviert werden da die Eingaben in die Nodedatei nur indirekt ausgelesen werden können.
|
|
|
Zu guter Letzt muss noch Speicher für die Übertragung des Puffers reserviert werden da die Eingaben in die Node Datei nur indirekt ausgelesen werden können.
|
|
|
|
|
|
In der folgenden Funktion verwenden wir die bereits erstellte Struktur der write-Funktion:
|
|
|
```c
|
... | ... | @@ -290,7 +358,7 @@ static ssize_t seven_write(struct file *filep, const char *buffer, size_t len, l |
|
|
memset(msg, 0, 32);
|
|
|
|
|
|
|
|
|
count = copy_from_user(msg, buffer, len); // Kopieren des Strings aus dem User-Space which open and write this device
|
|
|
count = copy_from_user(msg, buffer, len); // Kopieren des Strings aus dem User-Space
|
|
|
|
|
|
if (msg[0] == '1') {
|
|
|
seven_status(1);
|
... | ... | @@ -316,9 +384,30 @@ static ssize_t seven_write(struct file *filep, const char *buffer, size_t len, l |
|
|
else if (msg[0] == '8') {
|
|
|
seven_status(8);
|
|
|
}
|
|
|
else if (msg[0] == '9') {
|
|
|
seven_status(9);
|
|
|
}
|
|
|
else if (msg[0] == 'a') {
|
|
|
seven_status('a');
|
|
|
}
|
|
|
else if (msg[0] == 'b') {
|
|
|
seven_status('b');
|
|
|
}
|
|
|
else if (msg[0] == 'c') {
|
|
|
seven_status('c');
|
|
|
}
|
|
|
else if (msg[0] == 'd') {
|
|
|
seven_status('d');
|
|
|
}
|
|
|
else if (msg[0] == 'e') {
|
|
|
seven_status('e');
|
|
|
}
|
|
|
else if (msg[0] == 'f') {
|
|
|
seven_status('f');
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
seven_status(0);
|
|
|
seven_status('default');
|
|
|
}
|
|
|
return len;
|
|
|
|
... | ... | @@ -344,13 +433,13 @@ void seven_dev_exit(void) |
|
|
|
|
|
}
|
|
|
```
|
|
|
Hier wird durch die Funktion `unregister_chrdev(unsigned int major, const char *name)` der Treiber abgemeldet in den Parametern wird die Majornummer und der DEVICE_NAME angegeben.
|
|
|
Hier wird durch die Funktion `unregister_chrdev(unsigned int major, const char *name)` der Treiber abgemeldet, in den Parametern wird die Major Nummer und der DEVICE_NAME angegeben.
|
|
|
|
|
|
Quelle: [Linux Loadable Kernel Module HOWTO] (http://tldp.org/LDP/lkmpg/2.6/html/lkmpg.html#AEN569)
|
|
|
|
|
|
### 2.2.5 Die Modulfunktionen
|
|
|
|
|
|
Zu guter letzt müssen alle Initialisierungsfunktionen über die Modulinitialiesierung aufgerufen werden damit beim Laden des Treibers alle Funktionen garantiert sind:
|
|
|
Zu guter Letzt müssen alle Initialisierungsfunktionen über die Modulinitialisierung aufgerufen werden damit beim Laden des Treibers alle Funktionen garantiert sind:
|
|
|
```c
|
|
|
static int __init seven_init(void) {
|
|
|
printk(KERN_INFO "SEVENSEG: starting...");
|
... | ... | @@ -369,4 +458,12 @@ static void __exit seven_exit(void) { |
|
|
|
|
|
module_init(seven_init); //Alle Funktionen in led_init werden im Modul geladen
|
|
|
module_exit(seven_exit); //Alle Funktionen in led_init werden entladen
|
|
|
``` |
|
|
\ No newline at end of file |
|
|
```
|
|
|
Die Makros `module_init(seven_init)` und `module_exit(seven_exit)` ermöglichen es die Initialisierungs-Funktionen seperat in eigene Funktionen zu schreiben. Man muss beachten,
|
|
|
dass die Funktionen `seven_init()` und `seven_exit()` ein __init und __exit in der Deklaration haben und vor den Modulmakros aufgerufen werden müssen, da sonst Probleme beim Kompilieren entstehen.
|
|
|
|
|
|
Quelle: [Linux Loadable Kernel Module HOWTO] (http://tldp.org/HOWTO/Module-HOWTO/index.html)
|
|
|
|
|
|
Die ganze sevenseg.c Datei:
|
|
|
|
|
|
[Gesamter Code](https://mygit.th-deg.de/ce12213/Kernelmodul_Sevenseg/blob/master/Sevenseg/sevenseg.c) |