Linken chrdev met /dev/

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • k0ewl
  • Registratie: December 2003
  • Laatst online: 18-08-2023
Hoi mede-techneuten,

ik ben vanochtend maar eens begonnen met het schrijven van mijn eerste device driver onder linux. Ik gebruik Ubuntu op het moment, maar het idee is dat deze driver straks op een embedded linux versie gaat draaien.

De driver zou een Analog Devices ADV7180 aan moeten gaan sturen. Deze chip is een simpele videodecoder welke aanstuurbaar is via I2C. Hij stuurt zijn beelden over een aparte databus en werkt met een externe klok en geeft deze klok door aan mijn ARM11. Maar dat gaat al veel te ver, want ik krijg de simpele functionaliteit al niet aan de praat.

Het scenario:
Mijn driver zal een character-device aan gaan sturen en gebruik gaan maken van de file-operaties. Aangezien de ADV7180 via I2C bestuurbaar is, wil ik een shadowmap gaan maken van zijn registers. Dit zijn maximaal 256 registers van elk 8 bits. Enkele registers zijn alleen writeable, anderen alleen readable.
Wat ik wilde doen is met seek de offset voor de I2C actie te bepalen en dan daar de read of write op uitvoeren als de gebruiker read of write naar de file descriptor.

Mijn driver code op dit moment om te testen of ik vanuit userspace mijn driver kan benaderen:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/fcntl.h>
#include <linux/cdev.h>

/* Defines */
#define DRIVER_DESC "ADV7180 Driver"

#define ADV7180_MAJOR   0
#define ADV7180_MINOR   0
#define ADV7180_DEVS    1

/* Declaration of adv7180 functions */
static int     adv7180_open   ( struct inode *inode, struct file *filp );
static int     adv7180_release( struct inode *inode, struct file *filp );
static loff_t  adv7180_seek   ( struct file *filp, loff_t off, int whence );
static ssize_t adv7180_read   ( struct file *filp, char *buf, size_t count, loff_t *f_pos );
static ssize_t adv7180_write  ( struct file *filp, const char *buf, size_t count, loff_t *f_pos );

/* Struct which declares which of the file operations are applicable to this driver */
struct file_operations adv7180_fops = {
    .owner   = THIS_MODULE,
    .open    = adv7180_open,
    .llseek  = adv7180_seek,
    .read    = adv7180_read,
    .write   = adv7180_write,
    .release = adv7180_release
};

struct adv7180_cdev {
    unsigned char mutex;
    struct cdev cdev;
} adv7180_dev;

static int adv7180_major = 0;
static int adv7180_minor = 0;

static int __init adv7180_init( void )
{
    int ret;
    int dev;

    printk(KERN_INFO "Init " DRIVER_DESC "\n");

    if (ADV7180_MAJOR) {
        dev = MKDEV( ADV7180_MAJOR, ADV7180_MINOR );
        ret = register_chrdev_region( dev, ADV7180_DEVS, DRIVER_DESC );
    } else {
        ret = alloc_chrdev_region( &dev, ADV7180_MINOR, ADV7180_DEVS, DRIVER_DESC );
    }

    adv7180_major = MAJOR( dev );
    adv7180_minor = MINOR( dev );

    if (ret < 0) {
        printk( KERN_ERR "ADV7180: Can't get major %d (err %d)\n", adv7180_major, ret );

       return ret;
    }
    else
    {
        printk( KERN_INFO "ADV7180 located at %d %d\n", adv7180_major, adv7180_minor );
    }

    cdev_init( &(adv7180_dev.cdev), &adv7180_fops );
    adv7180_dev.cdev.owner = THIS_MODULE;
    adv7180_dev.cdev.ops   = &adv7180_fops;
    ret = cdev_add( &(adv7180_dev.cdev), adv7180_major, ADV7180_DEVS );
    if (ret < 0) {
        printk( KERN_ERR "ADV7180: Can't add device (err %d)\n", ret );

       return ret;
    }

    return 0;
}

static void __exit adv7180_exit( void )
{
    printk(KERN_INFO "Exit " DRIVER_DESC "\n");

    unregister_chrdev_region( adv7180_major, ADV7180_DEVS );
}

static int adv7180_open( struct inode *inode, struct file *filp )
{
    printk(KERN_INFO "OPEN\n");

    return 0;
}

static int adv7180_release( struct inode *inode, struct file *filp )
{
    printk(KERN_INFO "RELEASE\n");

    return 0;
}

static loff_t adv7180_seek( struct file *filp, loff_t off, int whence )
{
    printk(KERN_INFO "SEEK\n");

    return 0;
}

static ssize_t adv7180_read( struct file *filp, char *buf, size_t count, loff_t *f_pos )
{
    printk(KERN_INFO "READ\n");

    return 0;
}

static ssize_t adv7180_write( struct file *filp, const char *buf, size_t count, loff_t *f_pos )
{
    printk(KERN_INFO "WRITE\n");

    return 0;
}

MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR("Jaap Koekkoek");
MODULE_LICENSE("GPL");

module_init(adv7180_init);
module_exit(adv7180_exit);


Nu compileert dit gewoon zonder errors en krijg ik netjes een kernel module.
Dan insmod ik de kernel module zodat deze geinitialiseerd wordt.
Kijk in de dmseg om te bepalen wat zijn major en minor nummers zijn.
Deze nummers gebruik ik dan om te mknod-en.

code:
1
2
3
4
5
6
7
sudo insmod adv7180.ko

dmesg | tail
[177865.245290] Init ADV7180 Driver
[177865.245294] ADV7180 located at 244 0

mknod /dev/adv7180 c 244 0


Dan om te testen of ik de open, write, read en release functies aan kan roepen doe ik simpel weg een echo naar de /dev/adv7180 en een cat van de /dev/adv7180.

Dan krijg ik als error:
code:
1
bash: /dev/adv7180: No such device or address


Dit is zover ik gekomen ben, en nu ben ik even de kluts kwijt.

[ Voor 0% gewijzigd door moto-moi op 07-02-2010 11:32 . Reden: even highlighting aangezet voor je code :) ]

A byte walks into a bar and orders a pint. Bartender asks him "What's wrong?" Byte says "Parity error." Bartender nods and says "Yeah, I thought you looked a bit off."


Acties:
  • 0 Henk 'm!

  • FireDrunk
  • Registratie: November 2002
  • Laatst online: 12:59
cat /dev/adv*

misschien een verkeerde versie detectie? Device wel gemapped? Weet dat je in windows niet plug-and-pray devices hardhandig aan moet geven, misschien moet jij dat ook op de een of andere manier?

het lijkt mij dat /dev/adv7180 alleen bestaat als dat device ook herkend word. Als het COM/RS232 is, zul je /dev/com1 (ofzoiets) moeten gebruiken....

Even niets...


Acties:
  • 0 Henk 'm!

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Ik wil je toch even wijzen op dit:
http://git.kernel.org/?p=...0f931ac2b0b05463a;hb=HEAD

Die driver is al geimplementeerd. Mocht je een oudere kernel versie hebben, kun je deze beter backporten.

Daarnaast wil ik ook even wijzen op het i2c framework dat reeds bestaat. Als je er gebruik van maakt dan komt je device automatisch in /sys en zal udev er ook een device node voor maken.

[ Voor 24% gewijzigd door H!GHGuY op 06-02-2010 18:21 ]

ASSUME makes an ASS out of U and ME


Acties:
  • 0 Henk 'm!

  • k0ewl
  • Registratie: December 2003
  • Laatst online: 18-08-2023
H!GHGuY schreef op zaterdag 06 februari 2010 @ 18:20:
Ik wil je toch even wijzen op dit:
http://git.kernel.org/?p=...0f931ac2b0b05463a;hb=HEAD

Die driver is al geimplementeerd. Mocht je een oudere kernel versie hebben, kun je deze beter backporten.

Daarnaast wil ik ook even wijzen op het i2c framework dat reeds bestaat. Als je er gebruik van maakt dan komt je device automatisch in /sys en zal udev er ook een device node voor maken.
Dank je wel, maar ik wilde nog steeds weten waarom ik de error melding krijg. Ik moet namelijk nog wel meer drivers maken die niet bestaan en dit leek me een makkelijke om mee te beginnen omdat ik de werking er van snap.

A byte walks into a bar and orders a pint. Bartender asks him "What's wrong?" Byte says "Parity error." Bartender nods and says "Yeah, I thought you looked a bit off."


Acties:
  • 0 Henk 'm!

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

k0ewl schreef op maandag 08 februari 2010 @ 08:54:
[...]

Dank je wel, maar ik wilde nog steeds weten waarom ik de error melding krijg. Ik moet namelijk nog wel meer drivers maken die niet bestaan en dit leek me een makkelijke om mee te beginnen omdat ik de werking er van snap.
Kijk eens in /proc of je driver wel degelijk gelist staat met die major/minor. Ik zou even naar linux moeten rebooten om te zien welke file het juist is, maar ik vermoed dat /proc/devices of /proc/modules wel meer moet vertellen.

Ik vermoed dat je nog een call mist naar device_create.
Zie http://git.kernel.org/?p=...293deda919866d4e6;hb=HEAD

Daarnaast register je ook best een class.

ASSUME makes an ASS out of U and ME


Acties:
  • 0 Henk 'm!

  • k0ewl
  • Registratie: December 2003
  • Laatst online: 18-08-2023
H!GHGuY schreef op maandag 08 februari 2010 @ 20:04:
[...]


Kijk eens in /proc of je driver wel degelijk gelist staat met die major/minor. Ik zou even naar linux moeten rebooten om te zien welke file het juist is, maar ik vermoed dat /proc/devices of /proc/modules wel meer moet vertellen.

Ik vermoed dat je nog een call mist naar device_create.
Zie http://git.kernel.org/?p=...293deda919866d4e6;hb=HEAD

Daarnaast register je ook best een class.
Yup, hij staat gelist. Gewoon ook met dezelfde major/minor. Wat ik denk is dat hij in de proc lijst voor moet komen als /dev/adv7180 dan ofniet? Dan klopt de naamgeving gewoon niet helemaal. Zo eens proberen.

A byte walks into a bar and orders a pint. Bartender asks him "What's wrong?" Byte says "Parity error." Bartender nods and says "Yeah, I thought you looked a bit off."


Acties:
  • 0 Henk 'm!

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

k0ewl schreef op dinsdag 09 februari 2010 @ 16:58:
[...]

Yup, hij staat gelist. Gewoon ook met dezelfde major/minor. Wat ik denk is dat hij in de proc lijst voor moet komen als /dev/adv7180 dan ofniet? Dan klopt de naamgeving gewoon niet helemaal. Zo eens proberen.
Nee, de kernel weet helemaal niets af van device nodes en trekt het zich ook helemaal niet aan. Daarvoor dient udev. Zoals gezegd, doe eerst even een device_create.

ASSUME makes an ASS out of U and ME


Acties:
  • 0 Henk 'm!

  • igmar
  • Registratie: April 2000
  • Laatst online: 03-09 22:58

igmar

ISO20022

k0ewl schreef op vrijdag 05 februari 2010 @ 16:11:
Dan krijg ik als error:
code:
1
bash: /dev/adv7180: No such device or address
Die device nodes worden niet door de kernel aangemaakt, maar of door een mknod commando, of door udevd. udevd weet dat een device een node nodig heeft doordat je class_create() doet gevolgt door een device_create()

(eigenlijk : device_create() maaktt entries in sysfs, udevd haalt zijn info dan ook daar uit)

Acties:
  • 0 Henk 'm!

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

igmar schreef op woensdag 10 februari 2010 @ 12:35:
[...]
Die device nodes worden niet door de kernel aangemaakt, maar of door een mknod commando, of door udevd. udevd weet dat een device een node nodig heeft doordat je class_create() doet gevolgt door een device_create()

(eigenlijk : device_create() maaktt entries in sysfs, udevd haalt zijn info dan ook daar uit)
De TS gaf aan zelf mknod aangeroepen te hebben...

[ Voor 4% gewijzigd door H!GHGuY op 10-02-2010 12:58 ]

ASSUME makes an ASS out of U and ME

Pagina: 1