> чтобы драйвер компилировался, как модуль ядра1. Есть 2 способа скомпилировать драйвер как модуль ядра: in-tree и out-of-tree. Т.е. внутри дерева исходников ядра или снаружи. Вам сначала нужно решить, какой способ вы хотите использовать (уточнить у препода?). В зависимости от этого будут разные Makefile. Моё предположение -- вам нужно использовать out-of-tree способ, т.к. он проще.
a) in-tree
* Создаете в drivers/ (в исходниках ядра) свой каталог, например "masha".
- Туда кладете свой .c файл драйвера; назовём его "masha.c".
Для начала можете забить туда этот код (для проверки), потом добавите код драйвера клавиатуры:
#include <linux/init.h>
#include <linux/module.h>static int masha_init(void)
{
pr_alert("Hello there\n");
return 0;
}
static void masha_exit(void)
{
}
MODULE_LICENSE("GPL");
module_init(masha_init);
module_exit(masha_exit);
- Там же создаете Kconfig файл примерно следующего содержания:
menuconfig MASHA
tristate "Masha keyboard support"
default m
help
Masha keyboard support
this long line is just to trick kernel git hook system
this long line is just to trick kernel git hook system
this long line is just to trick kernel git hook system
this long line is just to trick kernel git hook system
this long line is just to trick kernel git hook system
this long line is just to trick kernel git hook systemconfig MASHA_KEYBOARD
tristate "Masha keyboard"
depends on MASHA != n
default m
help
bla bla
- И еще там же создаете Makefile такого содержания:
obj-$(CONFIG_MASHA_KEYBOARD) += masha.o
* в drivers/Kconfig добавляете:
source "drivers/masha/Kconfig"
* в drivers/Makefile добавляете:
obj-$(CONFIG_MASHA) += masha/
* Собираете свой модуль таким образом (выполняете эти команды из корня дерева исходников ядра)
$ make Image -j4
$ make M=drivers/masha
- после этого увидите .ko файл в drivers/masha -- это и будет ваш собранный модуль.
b) out-of-tree
* Тут всё проще. создаете в произвольном месте (не в каталоге исходников ядра) свой каталог (например /home/masha/projects/masha-kernel-module/), и в нем будет всего 2 файла: masha.c и Makefile. Исходник будет такой же, как и в случае in-the-tree, но Makefile будет примерно следующего содержания:
ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /lib/modules/$(shell uname -r)/buildmodule:
$(MAKE) -C $(KERNELDIR) M=$(PWD) C=1 modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) C=1 clean
.PHONY: module clean
else
obj-m := masha.o
endif
где KERNELDIR -- путь к корню дерева исходников ядра; если у вас своё дерево -- эту переменную надо изменить соответствующим образом.
* дальше выполняете из этого каталога:
$ make module
и получаете .ko файл -- это и есть ваш модуль. Как работает этот Makefile не буду объяснять, это долго.
2. Когда у вас получиться собрать "Hello world" модуль (код его я привел выше, см. "masha.c") -- вам нужно будет попросту вставить вместо того кода свой код, который вам дал преподаватель. Насколько я вижу, вам останется только дописать туда соответствующие макросы module_init() и module_exit() для уже готовых там функций init_module() и cleanup_module(). Да, еще наверное сигнатуру этих функций придется изменить так, как это в моем примере показано.
> и работал правильно на новых версиях (3.2, например).
Когда сделаете всё что написано выше -- попробуйте собрать на новом ядре ваш старый код и посмотреть, какие ошибки/предупреждения покажет компилятор. Починив эти ошибки, скорее всего получите работающий код
> Даже не знаю,с чего начать
Я сторонник мнения, что любую сложную проблему можно решить, разбив её на небольшие, решаемые части. Это называется планирование.
1. Для старого ядра сделайте проект "Hello world" модуля (код я привел выше), наверное это будет out-of-tree проект. Добейтесь, чтобы он собирался и на выходе получался .ko файл.
2. Вместо кода "Hello world" модуля вставьте код, который вам дал преподаватель. Добавьте module_init() и module_exit() макросы, как это было сделано у меня в "Hello world" модуле, изменив сигнатуры соответствующих функций должным образом. Добейтесь чтобы собиралось всё.
3. Протестируйте работу вашего модуля (команда insmod загружает модуль, команда dmesg показывает вывод ядра). Для этого надо разобраться, как модуль работает и как увидеть результат его работ.
Я не особо разбирался, но вроде как этот недо-драйвер просто вешается на шаренное прерывание клавиатуры и выводит в журнал ядра скан-код нажатой клавиши, и нажата она или отжата; кстати, убедитесь что в оригинальном драйвере клавиатуры это прерывание сделано шаренным, иначе ничего работать не будет. И да, я бы переделал workqueue на threaded_irq, так проще было бы.
Убедитесь, что всё работает.
4. Теперь попробуйте собрать модуль с новым ядром. Разберитесь с ошибками/предупреждениями компилятора и почините их.
5. Когда сможете собрать модуль для нового ядра -- проверьте его работу на новом ядре.
Если совсем ничего не понятно, советую к прочтению:
[1] http://rus-linux.net/MyLDP/BOOKS/drivers/linux-device-driver...
[2] http://lwn.net/Kernel/LDD3/