Blind-access patch for Linux 1.3.x

Kenneth Albanowski (kjahds@kjahds.com)
Tue, 5 Mar 1996 17:23:06 -0500 (EST)


This patch is intended to make Linux easier for the blind to use. It was
based was produced and tested on 1.3.67, but should work on all 1.3.x
kernels. The following changes have been made:

1. A new global kernel variable "blind_flag" is made, which defaults to
zero.

2. A new kernel command-line parameter is availble, "blind=", which
currently is used to directly set the blind_flag, as in "blind=1", or
"blind=0".

3. The i386 bootup and setup code has been modified to pass a flag at
position 0x1F0 to communicate the blind_flag from the bootup code to the
setup code.

4. During i386 bootup, the blind_flag is normally set to zero. If a default
vga mode of -4 is selected (through any mechanism, including rdev, LILO,
loadlin, etc.), then the default 80x25 mode will be chosen, and the
blind_flag will be set to 1. If a video mode of -2 (ASK) is selected and the
Backspace key is hit at any prompt, then 80x25 will be chosen, and the
blind_flag will be set to 1. Otherwise, the blind_flag is left at 0.

5. A function has been added to the console driver, to enable or disable
scrollback. This can be performed at any time. In addition, a new "setterm"
parameter has been added, so that "\033[15;0]" will disable scrollback, and
"\033[15;1]" will enable it. It is not expected that this behaviour will be
of great utility, but it seems sensible to add it. (One change not made, but
quite simple to accomplish, is adding a keyboard function mapping so that a
key combination could toggle scrollback. This was viewed as being worth the
effort, as loadkeys would have to be patched along with the kernel to support
the new binding.)

6. If the blind_flag is nonzero at console init, the console driver will
report "Blind-friendly mode enabled", and scrollback will be disabled. This
is currently the only effect of setting the blind_flag.

7. Disabling scrollback is only known to be of use to the Braillex
ib80-piezo Braille reader made by F.H. Papenmeier (Germany). However, it is
assumed that the blind_flag (and the corresponding "blind=" setup parameter)
can be the target for any future chances needed to make Linux more accessible
to the visually impaired.

Note that no changes have been made to the kernel configuration process. The
goal is to have the behaviour produced by this patch available (but normally
dormant) in _all_ future kernels. Obviously scrollback can normally be
disabled through a very simple patch, but if someone does not have access to
Linux in the first place to recompile the kernel, this can be difficult. If
this patch is part of the distribution, then a simple "rdev -v /dev/fd0 -4"
or "vga=-4" or "vga=ask" (or equivalent for other software) will be all that
is needed to allow the ib80 Braille reader to be used.

I would appreciate hearing any objections to putting this in the 1.3.x series
kernel.

*** arch/i386/boot/setup.S.orig Sun Mar 3 17:36:07 1996
--- arch/i386/boot/setup.S Mon Mar 4 16:51:18 1996
***************
*** 165,168 ****
--- 165,169 ----
mov ax,#0x5019
movb [15],#0 ! by default, no VGA
+ mov dx,#0 ! default blind-flag to 0
cmp bl,#0x1a ! 1a means VGA, anything else EGA or lower
jne novga
***************
*** 170,173 ****
--- 171,175 ----
call chsvga
novga: mov [14],al
+ mov [0x1f0],dx ! tuck away blind-flag
mov ah,#0x03 ! read cursor pos
xor bh,bh ! clear bh
***************
*** 490,493 ****
--- 492,497 ----
cmp ax,#EXTENDED_VGA
je vga50
+ cmp ax,#BLIND_VGA
+ je blindvga
cmp ax,#ASK_VGA
jne svga
***************
*** 498,506 ****
--- 502,518 ----
cmp al,#0x0d ! enter ?
je svga ! yes - svga selection
+ cmp al,#0x08 ! backspace ?
+ je blindvga ! yes - blind_vga selection
cmp al,#0x20 ! space ?
je defvga ! no - repeat
call beep
jmp nokey
+ blindvga:
+ mov dx,#1 ! set blind_flag
+ mov ax,#0x5019 ! same mode as defvga
+ pop ds
+ ret
defvga: mov ax,#0x5019
+ mov dx,#0 ! leave blind_flag unset
pop ds
ret
***************
*** 521,524 ****
--- 533,537 ----
pop ds
mov ax,#0x5032 ! return 80x50
+ mov dx,#0 ! leave blind_flag unset
ret
/* extended vga mode: 80x28 */
***************
*** 533,536 ****
--- 546,550 ----
pop ds
mov ax,#0x501c ! return 80x28
+ mov dx,#0 ! leave blind_flag unset
ret
/* svga modes */
***************
*** 875,878 ****
--- 889,894 ----
nonumb: call beep
nonum: call getkey
+ cmp al,#0x08 ! backspace = choose blindvga
+ je blindvga2
cmp al,#0x30 ! ascii `0'
jb nonumb
***************
*** 905,909 ****
--- 921,932 ----
lodsw
pop ds
+ mov dx,#0 ! leave blind-flag unset
ret
+ blindvga2: ! Identical to blindvga which is out of range
+ mov dx,#1 ! set blind_flag
+ mov ax,#0x5019 ! same mode as defvga
+ pop ds
+ ret
+

! Routine to write al into a VGA-register that is
*** arch/i386/kernel/setup.c.orig Sun Mar 3 17:44:50 1996
--- arch/i386/kernel/setup.c Sun Mar 3 17:46:34 1996
***************
*** 71,74 ****
--- 71,75 ----

extern int root_mountflags;
+ extern int blind_flag;
extern int _etext, _edata, _end;

***************
*** 85,88 ****
--- 86,90 ----
#define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
#define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
+ #define BLIND_FLAG (*(unsigned short *) (PARAM+0x1F0))
#define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
#define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
***************
*** 120,123 ****
--- 122,126 ----
#endif
aux_device_present = AUX_DEVICE_INFO;
+ blind_flag = BLIND_FLAG;
memory_end = (1<<20) + (EXT_MEM_K<<10);
memory_end &= PAGE_MASK;
*** drivers/char/console.c.orig Sun Mar 3 17:46:45 1996
--- drivers/char/console.c Sun Mar 3 17:54:53 1996
***************
*** 141,144 ****
--- 141,145 ----
static void reset_terminal(int currcons, int do_clear);
extern void reset_vc(unsigned int new_console);
+ static void set_scrollback(int newscroll);
extern void vt_init(void);
extern void register_console(void (*proc)(const char *));
***************
*** 153,156 ****
--- 154,159 ----
extern int set_get_font(unsigned char *, int, int);

+ extern unsigned short blind_flag;
+
/* Description of the hardware situation */
/* used in vga.c/tga.c/etc.c... :-) */
***************
*** 185,188 ****
--- 188,192 ----
static int vesa_off_interval = 0;
static long blank_origin, blank__origin, unblank_origin;
+ static int hardscroll_enabled = 1;

struct vc vc_cons [MAX_NR_CONSOLES];
***************
*** 586,592 ****
}

void scrup(int currcons, unsigned int t, unsigned int b)
{
! int hardscroll = 1;

if (b > video_num_lines || t >= b)
--- 590,614 ----
}

+ static void set_scrollback(int newscroll)
+ {
+ if(hardscroll_enabled && !newscroll) {
+ /* Switch off scrollback */
+ hardscroll_enabled = 0;
+
+ /* Reset screen to origin */
+ get_scrmem(fg_console);
+ set_scrmem(fg_console,0);
+ set_origin(fg_console);
+ set_cursor(fg_console);
+
+ } else if(!hardscroll_enabled && newscroll) {
+ /* Switch on scrollback */
+ hardscroll_enabled = 1;
+ }
+ }
+
void scrup(int currcons, unsigned int t, unsigned int b)
{
! int hardscroll = hardscroll_enabled;

if (b > video_num_lines || t >= b)
***************
*** 1167,1170 ****
--- 1189,1195 ----
vesa_off_interval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
break;
+ case 15: /* enable/disable scrollback */
+ set_scrollback(par[1]);
+ break;
}
}
***************
*** 2058,2061 ****
--- 2083,2090 ----

currcons = fg_console = 0;
+
+ /* If the blind_flag has been set, then disable scrollback */
+ if(blind_flag)
+ hardscroll_enabled = 0;

video_mem_start = video_mem_base;
***************
*** 2092,2095 ****
--- 2121,2126 ----
MIN_NR_CONSOLES, (MIN_NR_CONSOLES == 1) ? "" : "s",
MAX_NR_CONSOLES);
+ if(blind_flag)
+ printk("Console: blind accessible mode enabled\n");

/*
*** include/linux/config.h.orig Sun Mar 3 17:55:02 1996
--- include/linux/config.h Sun Mar 3 18:06:46 1996
***************
*** 38,41 ****
--- 38,42 ----
#define EXTENDED_VGA 0xfffe /* 80x50 mode */
#define ASK_VGA 0xfffd /* ask for it at bootup */
+ #define BLIND_VGA 0xfffc /* 80x25 + blind_flag */

#endif
*** init/main.c.orig Sun Mar 3 17:55:27 1996
--- init/main.c Mon Mar 4 21:46:15 1996
***************
*** 143,146 ****
--- 143,147 ----
int root_mountflags = MS_RDONLY;
char *execute_command = 0;
+ unsigned short blind_flag = 0; /* Set in i386/kernel/setup.c */

#ifdef CONFIG_ROOT_NFS
***************
*** 186,189 ****
--- 187,199 ----
}

+ static void blind_setup(char *str, int *ints)
+ {
+ /* Currently blind_setup only needs to set blind_flag */
+ if(ints[0] > 0)
+ blind_flag = ints[1];
+ else
+ blind_flag = 0;
+ }
+
struct {
const char *str;
***************
*** 192,195 ****
--- 202,206 ----
{ "reserve=", reserve_setup },
{ "profile=", profile_setup },
+ { "blind=", blind_setup },
#ifdef CONFIG_BLK_DEV_RAM
{ "ramdisk_start=", ramdisk_start_setup },

--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)