Difference between revisions of "83Plus:Software:usb8x/Sample Code"
(→Mouse Demo: Added ZDS code) |
(I have fixed the links on this page and hid the comments. This is the worst page I have seen so far. I have no idea what the author was trying to do with the code, but it needs to be fixed.) |
||
(12 intermediate revisions by 2 users not shown) | |||
Line 2: | Line 2: | ||
== BASIC == | == BASIC == | ||
=== Mouse Demo === | === Mouse Demo === | ||
− | This example uses the [[ | + | This example uses the [[83Plus:Software:usb8x/BASIC_Interface/MouseInit|MouseInit]], [[83Plus:Software:usb8x/BASIC_Interface/MouseDo|MouseDo]], and [[83Plus:Software:usb8x/BASIC_Interface/KillUSB|KillUSB]] entry points to control a point on the screen with a USB mouse. |
<nowiki>OpenLib(USBDRV8X | <nowiki>OpenLib(USBDRV8X | ||
{2 ;MouseInit | {2 ;MouseInit | ||
Line 32: | Line 32: | ||
{1 ;KillUSB | {1 ;KillUSB | ||
ExecLib</nowiki> | ExecLib</nowiki> | ||
+ | |||
+ | === Keyboard demo === | ||
+ | ==== Simple Example ==== | ||
+ | This program waits for you to press a key and then echos back which one. Unlike the ASM demo in USB Tools, this one handles all of 'em. | ||
+ | |||
+ | The requirement of <span style="font-variant: small-caps; font-size: 65%;">L</span>KBDSC being used to index an index is leftover from the early stages of this and somebody should reorganize the string so this isn't needed. Or not. Just an idea. | ||
+ | : | ||
+ | :OpenLib(USBDRV8X | ||
+ | :{10 | ||
+ | :ExecLib | ||
+ | :{40,0,12,153,120,0,132}→<span style="font-variant: small-caps; font-size: 65%;">L</span>BLANK | ||
+ | : | ||
+ | :While 1 | ||
+ | :{40,0,12,153,120,0,132} | ||
+ | :While prod(Ans=<span style="font-variant: small-caps; font-size: 65%;">L</span>BLANK)=1 | ||
+ | :If getKey≠0 | ||
+ | :Goto SP | ||
+ | :{11 | ||
+ | :ExecLib | ||
+ | :End | ||
+ | : | ||
+ | :Ans(3→A | ||
+ | :<span style="font-variant: small-caps; font-size: 65%;">L</span>KBDSC(A)→B | ||
+ | :Disp sub(Str2,<span style="font-variant: small-caps; font-size: 65%;">L</span>KBLOC(B),<span style="font-variant: small-caps; font-size: 65%;">L</span>KBLEN(B | ||
+ | : | ||
+ | :End | ||
+ | : | ||
+ | :Lbl SP | ||
+ | :{1 | ||
+ | :ExecLib | ||
+ | : | ||
+ | :Stop | ||
+ | <!--Change the first line to "Goto D" and run this program once to get all of this information updated.--> | ||
+ | :Lbl D | ||
+ | :{94,95,96,53,76,74,55,37,56,57,58,42,59,60,61,78,77,43,44,35,38,54,39,41,75,36, | ||
+ | 73,40,72,15,16,17,18,19,20,21,22,23,24,64,1,28,34,86,25,26,45,46,27,0,62,63,14,7 | ||
+ | 9,80,81,0,2,3,4,5,6,7,8,9,10,11,12,13,29,0,30,47,48,49,65,66,67,90,88,89,82,0,31 | ||
+ | ,32,33,71,93,83,84,85,68,69,70,50,51,52,91,92,0,87}→<span style="font-variant: small-caps; font-size: 65%;">L</span>KBDSC | ||
+ | :{3,2,2,2,2,2,2,2,2,2,3,3,3,5,1,1,1,1,1,1,1,1,1,1,1,1,4,9,12,5,5,5,5,3,1,1,1,1,1 | ||
+ | ,1,1,1,1,1,1,1,6,4,7,5,5,5,1,1,1,1,1,1,1,1,1,1,1,5,6,3,9,5,5,5,5,1,1,1,1,1,1,1,1 | ||
+ | ,1,1,2,5,5,5,5,13,4,4,5,5,5,9,4,4,4}→<span style="font-variant: small-caps; font-size: 65%;">L</span>KBLEN | ||
+ | :{1,4,6,8,10,12,14,16,18,20,22,25,28,31,36,37,38,39,40,41,42,43,44,45,46,47,48,5 | ||
+ | 2,61,73,78,83,88,93,96,97,98,99,100,101,102,103,104,105,106,107,108,114,118,125, | ||
+ | 130,135,140,141,142,143,144,145,146,147,148,149,150,151,156,162,165,174,179,184, | ||
+ | 189,194,195,196,197,198,199,200,201,202,203,204,206,211,216,221,226,239,243,247, | ||
+ | 252,257,262,271,275,279}→<span style="font-variant: small-caps; font-size: 65%;">L</span>KBLOC | ||
+ | :"ESCF1F2F3F4F5F6F7F8F9F10F11F12Tilde1234567890-=SlshBackspacePrint ScreenPauseN | ||
+ | UM /NUM *NUM -TABQWERTYUIOP[]InsertHomePage UpNUM 7NUM 8NUM 9ASDFGHJKL:'EnterDel | ||
+ | eteEndPage DownNUM 4NUM 5NUM 6NUM +ZXCVBNM,./UpNUM 1NUM 2NUM 3Space<Right Click> | ||
+ | LeftDownRightNUM 0NUM .NUM Enter<01><02><03>"→Str2 | ||
+ | |||
+ | ==== More Useful Example ==== | ||
+ | This example lets you type a string in using your actual keyboard. It doesn't know how to scroll, so you won't be able to type more than 128 characters, but they're still there. | ||
+ | <!--The following lines are really frickin' long and stretched screens, so I put hard-returns without <br> tags. You can figure out where there's not supposed to be a break.--> | ||
+ | <!--The <sup>−</sup> is supposed to be a quote, but there's no way to store a quote into a string from within a string.--> | ||
+ | :"abcdefghijklmnopqrstuvwxyz1234567890-=[]',./ ABCDEFGHIJKLMNOPQ | ||
+ | RSTUVWXYZ~!^*()+_{} :<sup>−</sup><>? "→Str2 | ||
+ | :{0,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,28, | ||
+ | 29,30,31,32,33,34,35,36,37,0,0,0,0,48,38,39,41,42,40,0,43,44,27,45,46,47,0,0,0,0 | ||
+ | ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 | ||
+ | ,0}→<span style="font-variant: small-caps; font-size: 65%;">L</span>KBSCL | ||
+ | :OpenLib(USBDRV8X | ||
+ | :{10 | ||
+ | :ExecLib | ||
+ | :{40,0,12,153,120,0,132}→<span style="font-variant: small-caps; font-size: 65%;">L</span>BLANK | ||
+ | :"π→Str1 | ||
+ | :While 1 | ||
+ | :{40,0,12,153,120,0,132} | ||
+ | :While prod(Ans=<span style="font-variant: small-caps; font-size: 65%;">L</span>BLANK)=1 | ||
+ | :If getKey≠0 | ||
+ | :Goto SP | ||
+ | :{11 | ||
+ | :ExecLib | ||
+ | :End | ||
+ | :Ans→<span style="font-variant: small-caps; font-size: 65%;">L</span>TEMP | ||
+ | :<span style="font-variant: small-caps; font-size: 65%;">L</span>TEMP(3→A | ||
+ | :If A=42 and length(Str1)>1 | ||
+ | :Then | ||
+ | :sub(Str1,1,length(Str1)-1→Str1 | ||
+ | :ClrHome | ||
+ | :Output(1,1,Str1 | ||
+ | :End | ||
+ | :If A=40 | ||
+ | :Goto E | ||
+ | :If <span style="font-variant: small-caps; font-size: 65%;">L</span>KBSCL(A)=0 | ||
+ | :End | ||
+ | : | ||
+ | : | ||
+ | : | ||
+ | :<span style="font-variant: small-caps; font-size: 65%;">L</span>TEMP(2→S | ||
+ | :0→T | ||
+ | :S+(S-128<u>></u>0)(<sup>−</sup>128→S | ||
+ | :S+(S-64<u>></u>0)(<sup>−</sup>64→S | ||
+ | :If S-32<u>></u>0 | ||
+ | :Then | ||
+ | :1→T | ||
+ | :S-32→S | ||
+ | :End | ||
+ | :S+(S-16<u>></u>0)(<sup>−</sup>16→S | ||
+ | :S+(S-8<u>></u>0)(<sup>−</sup>8→S | ||
+ | :S+(S-4<u>></u>0)(<sup>−</sup>4→S | ||
+ | :If S-2<u>></u>0 | ||
+ | :Then | ||
+ | :1→T | ||
+ | :S-2→S | ||
+ | :End | ||
+ | :Str1+sub(Str2,<span style="font-variant: small-caps; font-size: 65%;">L</span>KBSCL(A)+(T=1)48,1→Str1 | ||
+ | :If length(Str1)=2 and sub(Str1,1,1)="π | ||
+ | :sub(Str1,2,1→Str1 | ||
+ | :Output(1,1,Str1 | ||
+ | :End | ||
+ | :Lbl E | ||
+ | :Lbl SP | ||
+ | :{1 | ||
+ | :ExecLib | ||
+ | :DelVar <span style="font-variant: small-caps; font-size: 65%;">L</span>TEMP | ||
+ | :DelVar <span style="font-variant: small-caps; font-size: 65%;">L</span>MODS | ||
== Assembly (TASM) == | == Assembly (TASM) == | ||
− | Code for TASM-compatible assemblers. Though usb8x is designed for use with ZDS, | + | Code for TASM-compatible assemblers. Though usb8x is designed for use with ZDS, a TASM-syntax include file is provided as well. TASM itself is apparently incompatible with usb8x macros, but they have been tested to work correctly with [http://benryves.com/bin/brass/ Brass]. Use [http://usb8x.cvs.sourceforge.net/*checkout*/usb8x/usb8x/usb8xtsm.inc usb8xtsm.inc] instead of [http://usb8x.cvs.sourceforge.net/*checkout*/usb8x/usb8x/usb8x.inc usb8x.inc]. |
=== Mouse Demo === | === Mouse Demo === | ||
− | This code uses [[ | + | This code uses [[83Plus:Software:usb8x/Asm_Interface/DriverInit|DriverInit]], [[83Plus:Software:usb8x/Asm_Interface/Mouse/MouseInit|MouseInit]], [[83Plus:Software:usb8x/Asm_Interface/Mouse/MouseGetKey|MouseGetKey]], [[83Plus:Software:usb8x/Asm_Interface/HostKill|HostKill]], and [[83Plus:Software:usb8x/Asm_Interface/DriverKill|DriverKill]]. It is a replica of the mouse demo code from usb8x, though it doesn't include routines unrelated to USB. In this case the address of the callback routine passed to U_CALL_INIT doesn't matter, because MouseInit redefines the callback to handle the mouse data. |
Line 42: | Line 159: | ||
|- | |- | ||
|| | || | ||
− | ||'''<center> | + | ||'''<center>Brass</center>''' |
||'''<center>ZDS</center>''' | ||'''<center>ZDS</center>''' | ||
|- | |- | ||
Line 92: | Line 209: | ||
jp c,error | jp c,error | ||
ld hl,USBDriverBuf | ld hl,USBDriverBuf | ||
− | U_CALL( | + | U_CALL(DriverInit) |
jp c,error | jp c,error | ||
ld hl,DBuf | ld hl,DBuf | ||
ld bc,256 | ld bc,256 | ||
bcall(_MemClear) | bcall(_MemClear) | ||
− | ld | + | ld de,DBuf |
ld b,0 | ld b,0 | ||
− | U_CALL( | + | U_CALL(MouseInit) |
jp c,error | jp c,error | ||
bcall(_GrBufClr) | bcall(_GrBufClr) | ||
Line 118: | Line 235: | ||
push bc | push bc | ||
− | U_CALL( | + | U_CALL(MouseGetKey) |
call MouseUpdateCursor | call MouseUpdateCursor | ||
pop bc | pop bc | ||
Line 126: | Line 243: | ||
− | U_CALL( | + | U_CALL(HostKill) |
− | U_CALL( | + | U_CALL(DriverKill) |
ret</nowiki> | ret</nowiki> | ||
|| | || | ||
Line 140: | Line 257: | ||
ld bc,256 | ld bc,256 | ||
B_CALL MemClear | B_CALL MemClear | ||
− | ld | + | ld de,DBuf |
ld b,0 | ld b,0 | ||
U_CALL MouseInit | U_CALL MouseInit | ||
Line 170: | Line 287: | ||
U_CALL HostKill | U_CALL HostKill | ||
− | U_CALL DriverKill | + | U_CALL DriverKill |
ret</nowiki> | ret</nowiki> | ||
Line 178: | Line 295: | ||
− | ;Initialize | + | ;Initialize usb8x driver |
Line 185: | Line 302: | ||
;allow diagonal keys | ;allow diagonal keys | ||
− | ;Initialize | + | ;Initialize mouse driver |
Line 217: | Line 334: | ||
|} | |} | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
== Assembly (ZDS) == | == Assembly (ZDS) == | ||
Line 266: | Line 339: | ||
=== FindPipe === | === FindPipe === | ||
− | This code segment, taken from the mass storage driver, illustrates the use of [[ | + | This code segment, taken from the mass storage driver, illustrates the use of [[83Plus:Software:usb8x/Asm_Interface/FindPipe|FindPipe]] to get the address of an endpoint matching certain characteristics. |
<nowiki> ld b,pipeBulk | <nowiki> ld b,pipeBulk | ||
ld c,pipeOut | ld c,pipeOut | ||
Line 284: | Line 357: | ||
=== Keyboard Detect === | === Keyboard Detect === | ||
− | This code illustrates the use of [[ | + | This code illustrates the use of [[83Plus:Software:usb8x/Asm_Interface/AutoSetup|AutoSetup]] and [[83Plus:Software:usb8x/Asm_Interface/GetClass|GetClass]] to determine if the attached device is a keyboard. |
− | <nowiki> U_CALL_INIT KBDCallBack ; | + | <nowiki> U_CALL_INIT KBDCallBack ;Initialize U_CALL and Callback RAM calls |
jr c,NoUSBDriver ;If it returns C, that means USB8X isn't loaded on calc | jr c,NoUSBDriver ;If it returns C, that means USB8X isn't loaded on calc | ||
ld hl,USBDriverBuf | ld hl,USBDriverBuf |
Latest revision as of 08:26, 10 November 2009
Example code using the usb8x assembly and BASIC interfaces
Contents
BASIC
Mouse Demo
This example uses the MouseInit, MouseDo, and KillUSB entry points to control a point on the screen with a USB mouse.
OpenLib(USBDRV8X {2 ;MouseInit ExecLib If Ans(1 ;If MouseInit returns error, Return ; then quit -1452->Xmin 1452->Xmax -960->Ymin 960->Ymax 0->X 0->Y Repeat getKey {3 ;MouseDo ExecLib Ans->L1 If L1(1 ;If MouseDo returns error, Goto 1 ; restart loop If 127<L1(3 ;If x direction is left, L1(3)-256->L1(3 ; change to negative # If 127<L1(4 ;If y direction is up, L1(4)-256->L1(4 ; change to negative # Pt-Off(X,Y X+L1(3->X Y-L1(4->Y Pt-On(X,Y Lbl 1 End {1 ;KillUSB ExecLib
Keyboard demo
Simple Example
This program waits for you to press a key and then echos back which one. Unlike the ASM demo in USB Tools, this one handles all of 'em.
The requirement of LKBDSC being used to index an index is leftover from the early stages of this and somebody should reorganize the string so this isn't needed. Or not. Just an idea.
: :OpenLib(USBDRV8X :{10 :ExecLib :{40,0,12,153,120,0,132}→LBLANK : :While 1 :{40,0,12,153,120,0,132} :While prod(Ans=LBLANK)=1 :If getKey≠0 :Goto SP :{11 :ExecLib :End : :Ans(3→A :LKBDSC(A)→B :Disp sub(Str2,LKBLOC(B),LKBLEN(B : :End : :Lbl SP :{1 :ExecLib : :Stop :Lbl D :{94,95,96,53,76,74,55,37,56,57,58,42,59,60,61,78,77,43,44,35,38,54,39,41,75,36, 73,40,72,15,16,17,18,19,20,21,22,23,24,64,1,28,34,86,25,26,45,46,27,0,62,63,14,7 9,80,81,0,2,3,4,5,6,7,8,9,10,11,12,13,29,0,30,47,48,49,65,66,67,90,88,89,82,0,31 ,32,33,71,93,83,84,85,68,69,70,50,51,52,91,92,0,87}→LKBDSC :{3,2,2,2,2,2,2,2,2,2,3,3,3,5,1,1,1,1,1,1,1,1,1,1,1,1,4,9,12,5,5,5,5,3,1,1,1,1,1 ,1,1,1,1,1,1,1,6,4,7,5,5,5,1,1,1,1,1,1,1,1,1,1,1,5,6,3,9,5,5,5,5,1,1,1,1,1,1,1,1 ,1,1,2,5,5,5,5,13,4,4,5,5,5,9,4,4,4}→LKBLEN :{1,4,6,8,10,12,14,16,18,20,22,25,28,31,36,37,38,39,40,41,42,43,44,45,46,47,48,5 2,61,73,78,83,88,93,96,97,98,99,100,101,102,103,104,105,106,107,108,114,118,125, 130,135,140,141,142,143,144,145,146,147,148,149,150,151,156,162,165,174,179,184, 189,194,195,196,197,198,199,200,201,202,203,204,206,211,216,221,226,239,243,247, 252,257,262,271,275,279}→LKBLOC :"ESCF1F2F3F4F5F6F7F8F9F10F11F12Tilde1234567890-=SlshBackspacePrint ScreenPauseN UM /NUM *NUM -TABQWERTYUIOP[]InsertHomePage UpNUM 7NUM 8NUM 9ASDFGHJKL:'EnterDel eteEndPage DownNUM 4NUM 5NUM 6NUM +ZXCVBNM,./UpNUM 1NUM 2NUM 3Space<Right Click> LeftDownRightNUM 0NUM .NUM Enter<01><02><03>"→Str2
More Useful Example
This example lets you type a string in using your actual keyboard. It doesn't know how to scroll, so you won't be able to type more than 128 characters, but they're still there.
:"abcdefghijklmnopqrstuvwxyz1234567890-=[]',./ ABCDEFGHIJKLMNOPQ RSTUVWXYZ~!^*()+_{} :−<>? "→Str2 :{0,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,28, 29,30,31,32,33,34,35,36,37,0,0,0,0,48,38,39,41,42,40,0,43,44,27,45,46,47,0,0,0,0 ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ,0}→LKBSCL :OpenLib(USBDRV8X :{10 :ExecLib :{40,0,12,153,120,0,132}→LBLANK :"π→Str1 :While 1 :{40,0,12,153,120,0,132} :While prod(Ans=LBLANK)=1 :If getKey≠0 :Goto SP :{11 :ExecLib :End :Ans→LTEMP :LTEMP(3→A :If A=42 and length(Str1)>1 :Then :sub(Str1,1,length(Str1)-1→Str1 :ClrHome :Output(1,1,Str1 :End :If A=40 :Goto E :If LKBSCL(A)=0 :End : : : :LTEMP(2→S :0→T :S+(S-128>0)(−128→S :S+(S-64>0)(−64→S :If S-32>0 :Then :1→T :S-32→S :End :S+(S-16>0)(−16→S :S+(S-8>0)(−8→S :S+(S-4>0)(−4→S :If S-2>0 :Then :1→T :S-2→S :End :Str1+sub(Str2,LKBSCL(A)+(T=1)48,1→Str1 :If length(Str1)=2 and sub(Str1,1,1)="π :sub(Str1,2,1→Str1 :Output(1,1,Str1 :End :Lbl E :Lbl SP :{1 :ExecLib :DelVar LTEMP :DelVar LMODS
Assembly (TASM)
Code for TASM-compatible assemblers. Though usb8x is designed for use with ZDS, a TASM-syntax include file is provided as well. TASM itself is apparently incompatible with usb8x macros, but they have been tested to work correctly with Brass. Use usb8xtsm.inc instead of usb8x.inc.
Mouse Demo
This code uses DriverInit, MouseInit, MouseGetKey, HostKill, and DriverKill. It is a replica of the mouse demo code from usb8x, though it doesn't include routines unrelated to USB. In this case the address of the callback routine passed to U_CALL_INIT doesn't matter, because MouseInit redefines the callback to handle the mouse data.
MainLoop: gkloop: MouseDone: |
U_CALL_INIT(Stub) jp c,error ld hl,USBDriverBuf U_CALL(DriverInit) jp c,error ld hl,DBuf ld bc,256 bcall(_MemClear) ld de,DBuf ld b,0 U_CALL(MouseInit) jp c,error bcall(_GrBufClr) xor a ld (MouseBtn),a ld a,50*2 ld (MouseX),a ld a,32*2 ld (MouseY),a call DispCursor bcall(_GrBufCpy) bcall(_GetCSC) cp skClear jr z,MouseDone call DispCursor ld b,4 push bc U_CALL(MouseGetKey) call MouseUpdateCursor pop bc djnz gkloop call DispCursor jr MainLoop U_CALL(HostKill) U_CALL(DriverKill) ret |
U_CALL_INIT Stub jp c,error ld hl,USBDriverBuf U_CALL DriverInit jp c,error ld hl,DBuf ld bc,256 B_CALL MemClear ld de,DBuf ld b,0 U_CALL MouseInit jp c,error B_CALL GrBufClr xor a ld (MouseBtn),a ld a,50*2 ld (MouseX),a ld a,32*2 ld (MouseY),a call DispCursor B_CALL GrBufCpy B_CALL GetCSC cp skClear jr z,MouseDone call DispCursor ld b,4 push bc U_CALL MouseGetKey call MouseUpdateCursor pop bc djnz gkloop call DispCursor jr MainLoop U_CALL HostKill U_CALL DriverKill ret |
;Initialize U_CALL system ;Initialize usb8x driver ;Clear descriptor buffer ;allow diagonal keys ;Initialize mouse driver ;Display mouse cursor ;Erase cursor ;Buffer copy is slow, so ; update cursor a few times ;Get mouse info from usb8x ;Update cursor position ;Re-display cursor ;Disconnect power from mouse ;Kill driver |
Assembly (ZDS)
Code for ZDS compatible assemblers. usb8x is designed to be used with a ZDS-compatible assembler.
FindPipe
This code segment, taken from the mass storage driver, illustrates the use of FindPipe to get the address of an endpoint matching certain characteristics.
ld b,pipeBulk ld c,pipeOut ld hl,DescBuf U_CALL FindPipe ;Find an outgoing bulk endpoint jr c,error ld a,b ld (OutPipe),a ;Store the endpoint address for later use ld b,pipeBulk ld c,pipeIn ld hl,DescBuf U_CALL FindPipe ;Find an incoming bulk endpoint jr c,error ld a,b ld (InPipe),a
Keyboard Detect
This code illustrates the use of AutoSetup and GetClass to determine if the attached device is a keyboard.
U_CALL_INIT KBDCallBack ;Initialize U_CALL and Callback RAM calls jr c,NoUSBDriver ;If it returns C, that means USB8X isn't loaded on calc ld hl,USBDriverBuf U_CALL DriverInit ;Initialize USB driver ld hl,DescBuf U_CALL AutoSetup ;Initialize and configure USB device jr c,USBError ld hl,DescBuf U_CALL GetClass ;Get the class information for the attached device jr c,USBError cp 3 ;Keyboard class = 3 jr nz,NotKBD dec b ;subclass = 1 jr nz,NotKBD dec c ;protocol = 1 jr nz,NotKBD ;Keyboard is attached. Code would continue here. ;Typically at this point you would call ReqData to start reading data from the keyboard