LINUX.ORG.RU

И все таки, почему не работает?


0

0

И все таки, почему не работает этот модуль так как надо на 2.4.28...
Он запускаетя пишет скан коды в лог, но клава не работает как положено.Сканкоды пишет, а в самой системе ниче не нажимается - ПОЧЕМУ?Пусть не выгружается, только заработает.Помогите плиз!!!
 
#include <linux/kernel.h>               /* We're doing kernel work */
#include <linux/module.h>               /* Specifically, a module */
#include <linux/sched.h>
#include <linux/tqueue.h>
#include <linux/interrupt.h>
#include <asm/io.h>
static void got_char(void *scancode)
{
   printk("Scan Code %x %s.\n",
          (int) *((char *) scancode) & 0x7F,
          *((char *) scancode) & 0x80 ? "Released" : "Pressed");
}
irqreturn_t irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
    static unsigned char scancode;
    static struct tq_struct task ={
        .routine=got_char,
        .data=&scancode
    };
   unsigned char status;
   status = inb(0x64);
  scancode = inb(0x60);
queue_task(&task, &tq_immediate);
   mark_bh(IMMEDIATE_BH);
  return IRQ_HANDLED;
}

int init_module()
{
free_irq(1, NULL);
return request_irq(1,   /* The number of the keyboard IRQ on PCs */
              irq_handler, /* our handler */
              SA_SHIRQ,
              "test_keyboard_irq_handler", NULL);
}

void cleanup_module()
{
   free_irq(1, NULL);
}
MODULE_LICENSE("GPL");




 

уффф, я вам отвечаю в последний раз :)

как я уже говорил, это происходит потому, что вы
"убиваете" обработчик прерывания драйвера клавиатуры:

        free_irq(1, NULL);

а в нем и происходит (происходила) вся работа по
"пересылке" события в tty.

idle ★★★★★
()
Ответ на: комментарий от idle

Почему тогда в ядре 2.6 все работает если только реализовать очередь по другому.Тоесть захват и освобождение оставить таким же(почти), а изменить реализацию запуска нижних половинок.

Valentin_vv
() автор топика
Ответ на: комментарий от Valentin_vv

> Тоесть захват и освобождение оставить таким же(почти), а изменить реализацию

покажите код.

idle ★★★★★
()
Ответ на: комментарий от idle

Вот ссылка
(http://www.linuxcenter.ru/lib/books/lkmpg.phtml#KEYBOARDSONTHEINTELARCHITECTURE
) и код для 2.6:



/*
 *  intrpt.c - Обработчик прерываний.
 *
 *  Copyright (C) 2001 by Peter Jay Salzman
 */


/* 
 * Standard in kernel modules 
 */
#include <linux/kernel.h>    /* Все-таки мы работаем с ядром! */
#include <linux/module.h>    /* Необходимо для любого модуля */
#include <linux/workqueue.h> /* очереди задач */
#include <linux/sched.h>     /* Взаимодействие с планировщиком */
#include <linux/interrupt.h> /* определение irqreturn_t */
#include <asm/io.h>

#define MY_WORK_QUEUE_NAME "WQsched.c"

static struct workqueue_struct *my_workqueue;

/* 
 * Эта функция вызывается ядром, поэтому в ней будут безопасны все действия
 * которые допустимы в модулях ядра.
 */
static void got_char(void *scancode)
{
  printk("Scan Code %x %s.\n",
        (int)*((char *)scancode) & 0x7F,
        *((char *)scancode) & 0x80 ? "Released" : "Pressed");
}

/* 
 * Обработчик прерываний от клавиатуры.
 * Он считывает информацию с клавиатуры
 * и передает ее менее критичной по
 * времени исполнения части,
 * которая будет запущена сразу же,
 * как только ядро сочтет это возможным.
 */
irqreturn_t irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
  /* 
   * Эти переменные объявлены статическими, чтобы имелась возможность
   * доступа к ним (посредством указателей) из "нижней половины".
   */
  static int initialised = 0;
  static unsigned char scancode;
  static struct work_struct task;
  unsigned char status;

  /* 
   * Прочитать состояние клавиатуры
   */
  status = inb(0x64);
  scancode = inb(0x60);

  if (initialised == 0) {
    INIT_WORK(&task, got_char, &scancode);
    initialised = 1;
  } else {
    PREPARE_WORK(&task, got_char, &scancode);
  }

  queue_work(my_workqueue, &task);

  return IRQ_HANDLED;
}

int init_module()
{
  my_workqueue = create_workqueue(MY_WORK_QUEUE_NAME);

  /* 
   * Поскольку стандартный обработчик прерываний от клавиатуры не может
   * сосуществовать с таким как наш, то придется запретить его
   * (освободить IRQ) прежде, чем что либо сделать.
   * Но поскольку мы не знаем где он находится в ядре, то мы лишены
   * возможности переустановить его - поэтому
   * компьютер придется перезагрузить
   * после опробования этого примера.
   */
        free_irq(1, NULL);

  /* 
   * Подставить свой обработчик (irq_handler) на IRQ 1.
   * SA_SHIRQ означает, что мы допускаем возможность совместного
   * обслуживания этого IRQ другими обработчиками.
   */
  return request_irq(1,    /* Номер IRQ */
         irq_handler,      /* наш обработчик */
         SA_SHIRQ,
         "test_keyboard_irq_handler",
         (void *)(irq_handler));
}

/* 
 * Завершение работы
 */
void cleanup_module()
{
  /* 
   * Эта функция добавлена лишь для полноты изложения. 
   * Она вообще бессмысленна, поскольку я не вижу способа
   * восстановить стандартный обработчик прерываний от клавиатуры 
   * поэтому необходимо выполнить перезагрузку системы.
   */
  free_irq(1, NULL);
}

/* 
 * некоторые функции, относящиеся к work_queue 
 * доступны только если модуль лицензирован под GPL
 */
MODULE_LICENSE("GPL");

Valentin_vv
() автор топика
Ответ на: комментарий от Valentin_vv

работает это вот почему.

в 2.6 обработчик прерывания вызывается не только
в случае собственно прерывания, но и по таймеру,
20 раз в сек.

см drivers/input/serio/i8042.c:i8042_interrupt()

обратите внимание, что эта функция вызывается из
i8042_timer.function == i8042_timer_func.

idle ★★★★★
()
Ответ на: комментарий от idle

А можно узнать адрес этого обработчика? Чтобы не перегрудать комп?

ProtecT
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.