Messages in this thread Patch in this message | | | From | rubini@pop ... | Subject | /proc/mice and dynamic mouse minors | Date | Wed, 27 Mar 1996 14:50:13 +0100 (MET) |
| |
Hello Linus and Linuxers.
This patch adds support for dynamic assignment of minor numbers to mouse devices (misc char devices), and the file /proc/mice, which lists the currently defined minor numbers.
There is people out there who's writing drivers for pointing devices, be them pens or touchscreens, and they need to be assigned minor numbers, in order to have the driver tested out. Besides, /proc/mice is the linux way to answer to the question "have I got the such and such driver?"
Dynamic minors start from 63 and grow downwards, just like dynamic majors.
The patch is taken against 1.3.79 and I tried it with both the builtin and modular setup (but /proc/mice is only there with the builtin setup).
The way I implemented /proc/mice required a minor change to fs/proc/array.c in order to use the get_info pointer, which wasn't used but for /proc/net. The file system node being a stupid one, I didn't want to clubber the kernel with two more fops structures. This change to array.c also allows ease motion of device-specific functionality out of array.c itself to the device code.
Finally, mouse.c exports set_selection and paste_selection, in order to be able to implement gpm as a kernel module without further changes to the kernel.
Feel free to call me back about this stuff. /alessandro
--- ./fs/proc/array.c.orig79 Tue Mar 26 10:29:53 1996 +++ ./fs/proc/array.c Wed Mar 27 08:36:13 1996 @@ -1074,6 +1074,7 @@ int length; int end; unsigned int type, pid; + struct proc_dir_entry *dp; if (count < 0) return -EINVAL; @@ -1085,8 +1086,13 @@ pid = type >> 16; type &= 0x0000ffff; start = NULL; - length = fill_array((char *) page, pid, type, - &start, file->f_pos, count); + dp = (struct proc_dir_entry *) inode->u.generic_ip; + if (dp->get_info) + length = dp->get_info((char *)page, &start, file->f_pos, + count, 0); + else + length = fill_array((char *) page, pid, type, + &start, file->f_pos, count); if (length < 0) { free_page(page); return length; --- ./drivers/char/mem.c.orig79 Sat Mar 23 10:05:19 1996 +++ ./drivers/char/mem.c Wed Mar 27 08:36:13 1996 @@ -387,7 +387,7 @@ #ifdef CONFIG_PRINTER lp_init(); #endif -#if defined (CONFIG_BUSMOUSE) || \ +#if defined (CONFIG_BUSMOUSE) || defined(CONFIG_UMOUSE) || \ defined (CONFIG_PSMOUSE) || defined (CONFIG_MS_BUSMOUSE) || \ defined (CONFIG_ATIXL_BUSMOUSE) || defined(CONFIG_SOFT_WATCHDOG) mouse_init(); --- ./drivers/char/tty_io.c.orig79 Sat Mar 23 10:06:07 1996 +++ ./drivers/char/tty_io.c Wed Mar 27 08:36:13 1996 @@ -1543,7 +1543,7 @@ return do_get_ps_info(arg); #endif case 2: - return set_selection(arg, tty); + return set_selection(arg, tty, 1); case 3: return paste_selection(tty); case 4: --- ./drivers/char/Config.in.orig79 Sat Mar 23 10:06:30 1996 +++ ./drivers/char/Config.in Wed Mar 27 08:36:13 1996 @@ -19,6 +19,7 @@ fi tristate 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE tristate 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE +bool 'Support for user mouse modules' CONFIG_UMOUSE bool 'QIC-02 tape support' CONFIG_QIC02_TAPE if [ "$CONFIG_QIC02_TAPE" = "y" ]; then --- ./drivers/char/mouse.c.orig79 Sat Mar 23 10:05:36 1996 +++ ./drivers/char/mouse.c Wed Mar 27 09:30:56 1996 @@ -17,6 +17,8 @@ * * Fixed a failing symbol register to free the device registration * Alan Cox <alan@lxorguk.ukuu.org.uk> 21-Jan-96 + * + * Dynamic minors and /proc/mice by Alessandro Rubini. 26-Mar-96 */ #include <linux/module.h> @@ -28,18 +30,43 @@ #include <linux/kernel.h> #include <linux/major.h> #include <linux/malloc.h> +#include <linux/proc_fs.h> +#include <linux/stat.h> + +#include <linux/tty.h> /* needed by selection.h */ +#include "selection.h" /* export its symbols */ /* * Head entry for the doubly linked mouse list */ static struct mouse mouse_list = { 0, "head", NULL, &mouse_list, &mouse_list }; +/* + * Assigned numbers, used for dynamic minors + */ +#define DYNAMIC_MINORS 64 /* like dynamic majors */ +static unsigned char mouse_minors[DYNAMIC_MINORS / 8]; + #ifndef MODULE extern int bus_mouse_init(void); extern int psaux_init(void); extern int ms_bus_mouse_init(void); extern int atixl_busmouse_init(void); -#endif +extern void watchdog_init(void); + +#ifdef CONFIG_PROC_FS +static int proc_mouse_read(char *buf, char **start, off_t offset, int len, int unused) +{ + struct mouse *p; + + len=0; + for (p = mouse_list.next; p != &mouse_list; p = p->next) + len += sprintf(buf+len, "%3i %s\n",p->minor, p->name ?: ""); + return len; +} + +#endif /* PROC_FS */ +#endif /* !MODULE */ static int mouse_open(struct inode * inode, struct file * file) { @@ -76,6 +103,16 @@ { if (mouse->next || mouse->prev) return -EBUSY; + if (mouse->minor == MOUSE_DYNAMIC_MINOR) { + int i = DYNAMIC_MINORS; + while (--i >= 0) + if ( (mouse_minors[i>>3] & (1 << (i&7))) == 0) + break; + if (i<0) return -EBUSY; + mouse->minor = i; + } + if (mouse->minor < DYNAMIC_MINORS) + mouse_minors[mouse->minor >> 3] |= 1 << (mouse->minor & 7); MOD_INC_USE_COUNT; mouse->next = &mouse_list; mouse->prev = mouse_list.prev; @@ -86,6 +123,7 @@ int mouse_deregister(struct mouse * mouse) { + int i = mouse->minor; if (!mouse->next || !mouse->prev) return -EINVAL; MOD_DEC_USE_COUNT; @@ -93,6 +131,9 @@ mouse->next->prev = mouse->prev; mouse->next = NULL; mouse->prev = NULL; + if (i < DYNAMIC_MINORS && i>0) { + mouse_minors[i>>3] &= ~(1 << (mouse->minor & 7)); + } return 0; } @@ -112,12 +153,24 @@ #include <linux/symtab_begin.h> X(mouse_register), X(mouse_deregister), +#ifndef MODULE + X(set_selection), /* used by the kmouse module, can only */ + X(clear_selection), /* be exported if mouse.c is in linked in */ +#endif #include <linux/symtab_end.h> }; int mouse_init(void) { #ifndef MODULE +#ifdef CONFIG_PROC_FS + proc_register_dynamic(&proc_root, &(struct proc_dir_entry) { + 0, 4, "mice", + S_IRUGO, 1, 0, 0, + 0, NULL /* ops -- default to array */, + &proc_mouse_read /* get_info */, + }); +#endif /* PROC_FS */ #ifdef CONFIG_BUSMOUSE bus_mouse_init(); #endif --- ./drivers/char/Makefile.orig79 Sat Mar 23 10:06:43 1996 +++ ./drivers/char/Makefile Wed Mar 27 08:36:13 1996 @@ -100,6 +100,11 @@ endif endif +ifeq ($(CONFIG_UMOUSE),y) +# To support third-party modules, mouse.c must reside in the kernel +M = y +endif + ifdef CONFIG_SOFT_WATCHDOG L_OBJS += softdog.o M = y --- ./drivers/char/selection.c.orig79 Sat Mar 23 10:07:14 1996 +++ ./drivers/char/selection.c Wed Mar 27 08:36:13 1996 @@ -110,8 +110,8 @@ return v; } -/* set the current selection. Invoked by ioctl(). */ -int set_selection(const unsigned long arg, struct tty_struct *tty) +/* set the current selection. Invoked by ioctl() or by kernel code. */ +int set_selection(const unsigned long arg, struct tty_struct *tty, int user) { int sel_mode, new_sel_start, new_sel_end, spc; char *bp, *obp; @@ -122,12 +122,19 @@ { unsigned short *args, xs, ys, xe, ye; args = (unsigned short *)(arg + 1); - xs = get_user(args++) - 1; - ys = get_user(args++) - 1; - xe = get_user(args++) - 1; - ye = get_user(args++) - 1; - sel_mode = get_user(args); - + if (user) { + xs = get_user(args++) - 1; + ys = get_user(args++) - 1; + xe = get_user(args++) - 1; + ye = get_user(args++) - 1; + sel_mode = get_user(args); + } else { + xs = *(args++) - 1; /* set selection from kernel */ + ys = *(args++) - 1; + xe = *(args++) - 1; + ye = *(args++) - 1; + sel_mode = *args; + } xs = limit(xs, video_num_columns - 1); ys = limit(ys, video_num_lines - 1); xe = limit(xe, video_num_columns - 1); --- ./drivers/char/selection.h.orig79 Sat Mar 23 10:07:34 1996 +++ ./drivers/char/selection.h Wed Mar 27 10:09:01 1996 @@ -6,7 +6,7 @@ extern int sel_cons; extern void clear_selection(void); -extern int set_selection(const unsigned long arg, struct tty_struct *tty); +extern int set_selection(const unsigned long arg, struct tty_struct *tty, int user); extern int paste_selection(struct tty_struct *tty); extern int sel_loadlut(const unsigned long arg); extern int mouse_reporting(void); --- ./Documentation/Configure.help.orig79 Wed Mar 27 08:30:55 1996 +++ ./Documentation/Configure.help Wed Mar 27 08:36:14 1996 @@ -2815,6 +2815,13 @@ plugging in a COM port (9 or 25 pins) which is supported automatically. +Support for user mouse modules +CONFIG_UMOUSE + This option forces generic mouse support in the kernel, and allows + later loading of user mouse modules, such as drivers for optic pens + and touchscreens. Unless you have peculiar custom modules, or are + willing to write/test one, just say N. + QIC-02 tape support CONFIG_QIC02_TAPE If you have a non-SCSI tape drive like that, say Y.
-- __ o alessandro rubini - rubini@ipvvis.unipv.it _`\<, __( )/( )____ Italy: the country of fine arts and bad politics :)
| |