lkml.org 
[lkml]   [1996]   [Mar]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject/proc/mice and dynamic mouse minors
Date

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 :)

\
 
 \ /
  Last update: 2005-03-22 13:36    [W:0.022 / U:0.204 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site