diff -urN linux-2.6.12-rc4-mm2-panel-0.9.3/drivers/char/panel.c linux-2.6.12-rc4-mm2-panel-0.9.4/drivers/char/panel.c --- linux-2.6.12-rc4-mm2-panel-0.9.3/drivers/char/panel.c 2005-05-20 11:55:08.000000000 +0200 +++ linux-2.6.12-rc4-mm2-panel-0.9.4/drivers/char/panel.c 2005-05-20 11:55:01.000000000 +0200 @@ -64,6 +64,13 @@ * - added a system notifier callback to print the system state on the LCD * during reboots or halts. * + * 2005/05/20 : 0.9.4 + * - first working port on kernel 2.6 + * + * FIXME: + * - the initialization/deinitialization process is very dirty and should + * be rewritten. It may even be buggy. + * * TODO: * - document 24 keys keyboard (3 rows of 8 cols, 32 diodes + 2 inputs) * - make the LCD a part of a virtual screen of Vx*Vy @@ -1407,16 +1414,20 @@ if (file->f_flags & O_NONBLOCK) return -EAGAIN; + //printk(KERN_ERR "keypad_read():1 len=%d", keypad_buflen); interruptible_sleep_on(&keypad_read_wait); + //printk(KERN_ERR "keypad_read():2 len=%d", keypad_buflen); if (signal_pending(current)) return -EINTR; } + //printk(KERN_ERR "keypad_read():3 len=%d", keypad_buflen); for( ; count-- > 0 && (keypad_buflen > 0); ++i, ++tmp, --keypad_buflen ) { put_user( keypad_buffer[keypad_start], tmp ); keypad_start = (keypad_start + 1) % KEYPAD_BUFFER; } *ppos = i; + //printk(KERN_ERR "keypad_read():4 len=%d", keypad_buflen); return( tmp - buf ); } @@ -1453,16 +1464,21 @@ }; static void keypad_send_key(char *string, int max_len) { + //printk(KERN_ERR "keypad_send_key(%c,%d):1\n", *string,max_len); if (init_in_progress) return; + //printk(KERN_ERR "keypad_send_key(%c,%d):2\n", *string,max_len); /* send the key to the device only if a process is attached to it. */ if (keypad_open_cnt > 0) { + //printk(KERN_ERR "keypad_send_key(%c,%d):3\n", *string,max_len); while (max_len-- && keypad_buflen < KEYPAD_BUFFER && *string) { keypad_buffer[(keypad_start + keypad_buflen++) % KEYPAD_BUFFER] = *string++; } + //printk(KERN_ERR "keypad_send_key(%d):4\n", *string,max_len); wake_up_interruptible(&keypad_read_wait); } + //printk(KERN_ERR "keypad_send_key(%d):5\n", *string,max_len); } @@ -1945,7 +1961,10 @@ /* device initialization */ /**************************************************/ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#define INIT_FUNC static int __init panel_init_module +#define CLEANUP_FUNC static void __exit panel_cleanup_module +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #define INIT_FUNC static int __init panel_init_module #define CLEANUP_FUNC static void panel_cleanup_module #else @@ -2077,17 +2096,72 @@ if (port->number != parport) return; + if (pprt) { + printk(KERN_ERR "panel_attach(): port->number=%d parport=%d, already registered !\n", port->number, parport); + return; + } + pprt = parport_register_device(port, "panel", NULL, NULL, /* pf, kf */ NULL, /*PARPORT_DEV_EXCL*/ 0, (void *)&pprt); + + if (parport_claim(pprt)) { + printk(KERN_ERR "Panel: could not claim access to parport%d. Aborting.\n", parport); + //parport_unregister_device(pprt); + //parport_unregister_driver(&panel_driver); + //return -EIO; + return; + } + + /* turns IRQ off */ + // port->ops->disable_irq(port); + + /* must init LCD first, just in case an IRQ from the keypad is generated at keypad init */ + if (lcd_enabled) { + lcd_init(); + misc_register( &lcd_dev ); + } + + if (keypad_enabled) { + keypad_init(); + misc_register( &keypad_dev ); + } + + if (smartcard_enabled) { + smartcard_init(); + misc_register( &smartcard_dev ); + } } static void panel_detach (struct parport *port) { - /* nothing yet */ + if (port->number != parport) + return; + + if (!pprt) { + printk(KERN_ERR "panel_detach(): port->number=%d parport=%d, nothing to unregister.\n", + port->number, parport); + return; + } + + if (smartcard_enabled) { + misc_deregister( &smartcard_dev ); + } + + if (keypad_enabled) { + misc_deregister( &keypad_dev ); + } + + if (lcd_enabled) { + misc_deregister( &lcd_dev ); + } + + parport_release(pprt); + parport_unregister_device(pprt); + pprt = NULL; } static struct parport_driver panel_driver = { @@ -2170,42 +2244,19 @@ return -EIO; } - if (pprt == NULL) { - printk(KERN_ERR "Panel: could not register parport%d. Aborting.\n", parport); - parport_unregister_driver(&panel_driver); - return -ENODEV; /* port not found */ - } - - - if (parport_claim(pprt)) { - printk(KERN_ERR "Panel: could not claim access to parport%d. Aborting.\n", parport); - parport_unregister_device(pprt); - parport_unregister_driver(&panel_driver); - return -EIO; - } - - /* turns IRQ off */ - // port->ops->disable_irq(port); - - /* must init LCD first, just in case an IRQ from the keypad is generated at keypad init */ - if (lcd_enabled) { - lcd_init(); - misc_register( &lcd_dev ); - } - - if (keypad_enabled) { - keypad_init(); - misc_register( &keypad_dev ); - } + // The parport can be asynchronously registered later. + //if (pprt == NULL) { + // printk(KERN_ERR "Panel: could not register parport%d. Aborting.\n", parport); + // parport_unregister_driver(&panel_driver); + // return -ENODEV; /* port not found */ + //} - if (smartcard_enabled) { - smartcard_init(); - misc_register( &smartcard_dev ); - } if (!lcd_enabled && !keypad_enabled && !smartcard_enabled) { /* no device enabled, let's release the parport */ - parport_release(pprt); - parport_unregister_device(pprt); + if (pprt) { + parport_release(pprt); + parport_unregister_device(pprt); + } parport_unregister_driver(&panel_driver); printk(KERN_ERR "Panel driver version " PANEL_VERSION " disabled.\n"); return -ENODEV; @@ -2213,8 +2264,11 @@ register_reboot_notifier(&panel_notifier); - printk(KERN_INFO "Panel driver version " PANEL_VERSION " registered on parport%d (io=0x%lx).\n", - parport, pprt->port->base); + if (pprt) + printk(KERN_INFO "Panel driver version " PANEL_VERSION " registered on parport%d (io=0x%lx).\n", + parport, pprt->port->base); + else + printk(KERN_INFO "Panel driver version " PANEL_VERSION " not yet registered\n"); /* tells various subsystems about the fact that initialization is finished */ init_in_progress = 0; return 0;