Программное обеспечение параллельного порта

Нижеследующее обсуждение посвящено соответствующей функции для этого проекта. Полный листинг программы для parll. с вместе с файлом parll. л приведен в конце этой книги.
1) Настройка файловых операций (fops)
Как говорилось ранее, этот модуль использует open (), close () и ioctl (), как и описанные ранее init и cleanup.
Первым шагом является настройка структуры файловых операций. Эта структура определена в /linux/f s .h, перечисляющем все функции, которые можно реализовать в нашем модуле. Нам не нужно использовать все операции, достаточно только самых необходимых. Поиск в сети по запросу С99 или linux module даст вам больше информации об этих методах. Используя эту структуру, мы сообщаем ядру о местонахождении наших реализаций (или точках вхождения) open, release и iotcl.

parll.с
struct file_operations parlport_fops = { .open = parlport_open, .ioctl = parlport_ioctl, .release = parlport_close };

Далее мы создаем функции open () и close (). Данные функции-пустышки используются для сигнализации об открытии и закрытии:

parll.с
static int parlport_open(struct inode ino, struct file filp) {
printk("\n parlport open function"); return 0;
}
static int parlport_close(struct inode ino, struct file filp) { printk("\n parlport close function"); return 0;
}

Создадим функцию ioctl (). Обратите внимание, что определение функции делается в начале parll. с:

#define MODULE_NAME "parll" static int base = 0x378; parll.с
static int parlport_ioctl(struct inode *ino, struct file *filp, unsigned int ioctl_cmd, unsigned long parm)
{
printk("\n parlport ioctl function"); if(_IOC_TYPE(ioctl_cmd) != IOCTL_TYPE)
{
printk("\n%s wrong ioctl type",MODULE_NAME); return -1;
}
switch(ioctl_cmd) {
case DATA_OUT:
printk("\n%s ioctl data out=%x",MODULE_NAME,(unsigned int)parm); outbfparm & Oxff, base+0); return (parm & Oxff); case GET_STATUS: parm = inb(base+l);
printk("\n%s ioctl get status=%x",MODULE_NAME,(unsigned int)parm); return parm; case CTRL_OUT:
printk("\n%s ioctl Ctrl out=%x",MODULE_NAME,(unsigned int)parm); outbfparm && Oxff, base+2); return 0; } //end switch return 0; } //end ioctl

Функция ioctl () делает возможной обработку любых определенных пользователем команд. В нашем модуле мы используем три регистра, связанные с параллельным портом пользователя. Команда DATA_OUT посылает значение из регистра data, команда GET_STATUS читает из регистра status, и, наконец, команда CTRL_OUT позволяет установить сигнал для порта. Несмотря на то что лучше было бы скрыть специфические для устройства операции внутри функций read () и write (), этот модуль, работоспособен, так как служит только для экспериментов с вводом-выводом, а не для реального применения.
Эти три команды определены в заголовочном файле parll. h. Они создаются с применением вспомогательных функций IOCTL для проверки типов. Вместо использования целого для представления функции IOCTL мы используем IOCTL-макрос проверки типов 10 (type, number), где параметр type определен как р (для параллельного порта), a number как текущий номер IOCTL, используемый в выражении. В начале parlport_ ioctl () мы проверяем тип, которым должен быть р. Так как код приложения использует тот же заголовочный файл, что и драйвер, интерфейс будет согласованным.