Mail Archives: djgpp/1997/07/28/19:18:13
From: | e-mail DOT address AT end DOT of DOT text (Mike Collins)
|
Newsgroups: | comp.os.msdos.djgpp
|
Subject: | One PC shadows another (part 2)
|
Date: | 22 Jul 1997 10:34:00 GMT
|
Organization: | Storage Technology Limited
|
Lines: | 391
|
Message-ID: | <5r22ao$3bq@news.network.com>
|
NNTP-Posting-Host: | 129.80.172.76
|
Mime-Version: | 1.0
|
To: | djgpp AT delorie DOT com
|
DJ-Gateway: | from newsgroup comp.os.msdos.djgpp
|
/* Part-1 of this article contains the description of functions and the
kb.h file. This part contains the kb.c file, which also contains a simple
demonstration in main(). Read part-1 first.
Hope it helps someone.
Mike Collins.
*/
//==============FILE : KB.C====================//
#include <stdio.h>
#include <go32.h>
#include <dpmi.h>
#include <dos.h>
#include <conio.h>
#include <sys/farptr.h>
#include <unistd.h>
#include "kb.h"
/* declare functions */
void Int09(void);
void Int0C(void);
void Int23(void);
void rs232_send(char ch);
void kb_putch(char ch);
void ResetInt(void);
void SetupInt(void);
char hex(char ch);
_go32_dpmi_seginfo KbInt09, KbOldInt09,
KbInt0C, KbOldInt0C,
KbInt23, KbOldInt23;
char ScanCode[256];
int CommsMode = STANDALONE;
int diffs;
#define TEST // remove this line to use these routines with your program
#ifdef TEST
#define FUNC1 '\x3b' /* second character generated by F1 key */
#define FUNC10 '\x44' /* second character generated by F10 key */
main()
{ int i=0;
char ch = '\0', str[80];
clrscr();
SetupInt();
cprintf("Enter some characters on the MASTER or STANDALONE PC\n\r");
cprintf("They will be displayed on it and on the SLAVE PC.\n\n\r");
cprintf("To set this PC to STANDALONE, press ALT-CTL-1 (It defaults to this)\n\r");
cprintf("To set this PC to MASTER, press ALT-CTL-M\n\r");
cprintf("To set this PC to SLAVE, press ALT-CTL-S\n\n\r");
while(1)
{ ch = kb_getch();
if(ch == '\r')
exit(0);
else if(ch == '\0')
{ ch = kb_getch();
if(ch >= FUNC1 && ch <= FUNC10)
cprintf("<F%d>",ch-0x3a); // Second char of FUNC1 = 0x3b
// Only the function keys are detected here, but all two-character sets
// are sent through the serial link (cursor, delete, etc.)
}
else
cprintf("%c", ch);
}
}
#endif
char save21;
/* Interrupt 9 keyboard service (occurs when a key is pressed) */
void Int09(void)
{ int c;
c = inportb(0x60); // Get keyboard scan code from keyboard port
if (c < 0x80) ScanCode[c] = 1;
else ScanCode[c & 0x7F] = 0;
if(ScanCode[0x1d] && ScanCode[0x38])
{ disable();
{ if(ScanCode[MASTER])
CommsMode = MASTER;
else if(ScanCode[SLAVE])
CommsMode = SLAVE;
else if(ScanCode[STANDALONE])
CommsMode = STANDALONE;
}
enable();
}
}
/* Interrupt 0C RS232 service (occurs when a character is received) */
void Int0C(void)
{ /* get a character from COM1 and put it into the keyboard buffer */
char in_ch, gpc;
disable();
// Test for error conditions - see file "UART" for signal definitions
// ScreenSetCursor(24, 60);
// if(((gpc = inportb(0x3fa)) & 0x06) != 0x04) printf("3fa = %02x", gpc);
// if(((gpc = inportb(0x3fd)) & 0x9f) != 0x01) printf("3fd = %02x", gpc);
// if(((gpc = inportb(0x3fe)) & 0x0f) != 0x00) printf("3fe = %02x", gpc);
in_ch = (char)inportb(0x3f8);
outportb(0x20, 0x20);
if((CommsMode == MASTER) && (in_ch & 0x80))
diffs = in_ch & 0x7f;
else if(CommsMode == SLAVE)
kb_putch(in_ch); //### lock kb_putch + all its variables
enable();
}
void Int23(void)
{ exit(0); /* perform normal exit so interrupt vectors can be reset */
}
void rs232_send(char ch)
{ while(!(inportb(0x3fd) & 0x20)); // wait for Tx buffer empty
outportb(0x3f8, ch);
}
void kb_putch(char ch) // put character/scancode into key buffer
{ int chr_pt, scn_pt;
static int special = 0;
// A 'special' character is the first of a two-character set - used for
// function keys, arrows, etc.
unsigned int head, tail, base = 0x400;
head = _farpeekw(_dos_ds, 0x41a);
tail = _farpeekw(_dos_ds, 0x41c);
chr_pt = tail+base;
scn_pt = chr_pt+1;
if(ch == '\0')
{ special = 1;
return;
}
if(special)
{ special = 0;
_farpokeb(_dos_ds, chr_pt, 0);
_farpokeb(_dos_ds, scn_pt, ch);
}
else
{ _farpokeb(_dos_ds, chr_pt, ch);
_farpokeb(_dos_ds, scn_pt, 0);
}
tail += 2;
if(tail > 0x3c)
tail = 0x1e;
_farpokew(_dos_ds, 0x41c, tail);
// SLAVE sends diffs to master
if(CommsMode == SLAVE)
{ diffs = tail - head;
if(diffs<0) diffs += 34;
rs232_send((char)diffs | 0x80);
}
}
/* Reset interrupt 9 & C vector */
void ResetInt(void)
{ _go32_dpmi_set_protected_mode_interrupt_vector(9, &KbOldInt09);
_go32_dpmi_set_protected_mode_interrupt_vector(0x23, &KbOldInt23);
_go32_dpmi_set_protected_mode_interrupt_vector(0x0C, &KbOldInt0C);
_go32_dpmi_free_iret_wrapper(&KbInt0C);
_go32_dpmi_free_iret_wrapper(&KbInt23);
outp(0x20, 0x00); // clean up UART - these values read from a clean system
outp(0x21, save21);
outp(0x3f9, 0x00);
outp(0x3fa, 0x00);
outp(0x3fb, 0x03);
outp(0x3fc, 0x00);
}
/* Interrupt 23 Ctrl Break service (gets control for Ctrl Break or Ctrl C) */
void SetupInt(void)
{ static char first_time = '\xff';
union REGS regs;
// Check to see if this is first time called
if(first_time)
{ first_time = 0;
diffs = 0;
_go32_dpmi_lock_code(Int09, (unsigned long)(ResetInt - Int09));
_go32_dpmi_lock_data(ScanCode, sizeof(ScanCode));
_go32_dpmi_lock_data(&CommsMode, sizeof(CommsMode));
_go32_dpmi_lock_data(&diffs, sizeof(diffs));
/* Interrupt 9 keyboard service (occurs when a key is pressed) */
_go32_dpmi_get_protected_mode_interrupt_vector(0x09, &KbOldInt09);
KbInt09.pm_offset = (int)Int09;
KbInt09.pm_selector = _go32_my_cs();
_go32_dpmi_get_protected_mode_interrupt_vector(0x0C, &KbOldInt0C);
KbInt0C.pm_offset = (int)Int0C;
KbInt0C.pm_selector = _go32_my_cs();
_go32_dpmi_allocate_iret_wrapper(&KbInt0C);
/* perform normal exit if program interrupted by Ctrl C or Ctrl Break */
_go32_dpmi_get_protected_mode_interrupt_vector(0x23, &KbOldInt23);
KbInt23.pm_offset = (int)Int23;
KbInt23.pm_selector = _go32_my_cs();
_go32_dpmi_allocate_iret_wrapper(&KbInt23);
_go32_dpmi_set_protected_mode_interrupt_vector(0x23, &KbInt23);
atexit(ResetInt);
/* set the comms port 0 to 9600, no parity, 1 stop bit, 8 data bits */
// regs.h.ah = 0;
// regs.h.al = 0xc7; /* 9600bd, 1stop, NoPar, 8bits */
// regs.w.dx = 0;
// int86(14, ®s, ®s);
outportb(0x3fb, 0x83); /* set msb of Line Ctrl Reg */
outportb(0x3f8, 12); /* set BRD = 6 for 19200, 12 for 9600 */
outportb(0x3fb, 0x03); /* reset msb of Line Ctrl Reg */
outportb(0x3fe, 0x00);
/* Set UART Data Received interrupt on */
outportb(0x3fc, 0x0f);
outportb(0x3f9, 0x01);
/* Trap RS232 interrupt 0x0C */
_go32_dpmi_set_protected_mode_interrupt_vector(0x0C, &KbInt0C);
/* unmask the PIC */
save21 = (char)inportb(0x21);
outportb(0x21, save21 & 0xEF);
/* Trap keyboard interrupt 0x09 */
_go32_dpmi_chain_protected_mode_interrupt_vector(0x09, &KbInt09);
}
}
char hex(char ch)
{ if(ch >= 10) return('A'+ch-10);
return('0'+ch);
}
void disp_kb_bfr(int period)
// displays the buffer without updating anything
{ int pt;
int head, tail;
head = _farpeekw(_dos_ds, 0x41a)+0x400;
tail = _farpeekw(_dos_ds, 0x41c)+0x400;
ScreenSetCursor(4, 0);
cprintf("\n\rHead = %02x Tail = %02x", head, tail);
for(pt = 0x41e; pt <= 0x43c; )
{ cprintf("\n\r %02x - %02x ",_farpeekb(_dos_ds, pt), _farpeekb(_dos_ds, (pt+1)));
if(pt == tail) cprintf("< | %x", pt);
else cprintf(" | %x", pt);
if(pt == head) cprintf("\r >");
pt += 2;
}
sleep(period);
}
char kb_getch() // replaces getch() in your program (see 'main()' above)
{ int head, tail, chr_pt, scn_pt, base = 0x400;
char hold, c_char, c_scan;
static int special = 0, OldCommsMode;
// cprintf("\nCommsMode - %02x",CommsMode);
if(CommsMode != OldCommsMode)
{ diffs = 0;
if(CommsMode == SLAVE)
{ outportb(0x03f9, 0x01);
outportb(0x3fa, 0x00); // unhangs the RS232 when it gets hung up
outportb(0x3fc, 0x0f); // (learned from analysis of other S/W)
}
OldCommsMode = CommsMode;
}
if(special) // 'specials' are function keys, arrows, ALT-key, etc
{ hold = (char)special;
special = 0;
goto ts_getch_end; // without updating 'head'
}
// wait till slave kb_buf contains less than 15 characters
while(CommsMode == MASTER && diffs > 14) /* wait here */;
// wait for key press then set pointers chr & scn get c_char, c_scan
do { head = _farpeekw(_dos_ds, 0x41a);
tail = _farpeekw(_dos_ds, 0x41c);
} while(head == tail);
chr_pt = base + head;
scn_pt = chr_pt + 1;
c_char = _farpeekb(_dos_ds, chr_pt);
c_scan = _farpeekb(_dos_ds, scn_pt);
if(c_char & 0x80 || c_char == 0)
{ special = c_scan;
hold = 0;
}
else
hold = c_char;
head += 2;
if(head > 0x3c)
head = 0x1e;
_farpokew(_dos_ds, 0x41a, head);
ts_getch_end:
// SLAVE sends diffs to master
if(CommsMode == SLAVE)
{ diffs = tail - head;
if(diffs<0) diffs += 34;
{ //cprintf("Point A");
rs232_send((char)diffs | 0x80);
}
}
if(CommsMode == MASTER) // send it through the serial port - std DOS call
{ //cprintf("Point B");
rs232_send(hold);
}
return hold;
}
void kb_ungetch(char ch) // puts character back into the keyboard buffer
{ int chr_pt, scn_pt;
static int special = 0;
unsigned int head, tail, base = 0x400;
head = _farpeekw(_dos_ds, 0x41a);
tail = _farpeekw(_dos_ds, 0x41c);
if(ch == '\0')
{ special = 1;
return;
}
if((head -= 2) < 0x1e)
head = 0x3c;
chr_pt = base + head;
scn_pt = chr_pt + 1;
if(special)
{ _farpokeb(_dos_ds, chr_pt, '\0');
_farpokeb(_dos_ds, scn_pt, ch);
special = 0;
}
else
{ _farpokeb(_dos_ds, chr_pt, ch);
_farpokeb(_dos_ds, scn_pt, '\0');
}
_farpokew(_dos_ds, 0x41a, head);
}
int kb_hit(void) // tests to see if 'next' and 'last' pointers are equal
{ int head, tail;
head = _farpeekw(_dos_ds, 0x41a);
tail = _farpeekw(_dos_ds, 0x41c);
return(tail>=head ? tail-head : head - tail);
}
void kb_ungets(char *str)
{ char *pt;
if(CommsMode != SLAVE)
{ if(str[0] == '\0') // if this is the first (zero) character of a function
{ kb_ungetch('\0');// key, there will only be two chars in all. Don't
kb_ungetch(str[1]); // assume a zero length.
}
else
{ pt = str + strlen(str) - 1; // Otherwise, get ready to copy a string.
while(pt >= str)
kb_ungetch(*pt--);
}
}
}
--
Don't just hit "reply" - my E-mail address is bogus
to avoid automatic browsers from sending junk mail.
Please use collim'at'anubis'dot'network'dot'com
Actually, even this doesn't stop all of them ...
- Raw text -