⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jan axelson's parallel port faq.htm

📁 Parallel Port description of the communication port
💻 HTM
📖 第 1 页 / 共 5 页
字号:
      <P>1. Write a couple of values to each of the addresses and read back the 
      result. If the values match, the port exists. This won't detect a port 
      where access is denied by a system-level driver, or a port in PS/2-input 
      mode (though you can also test for this). Requires an Inpout DLL or other 
      driver for port I/O. <BR><BR>2. 16-bit only: Use Vbasm's Peek function to 
      read the addresses stored in the BIOS data area at 40:08 through 40:0D. 
      May not include all ports.<BR><BR>3. Under Windows 95, the port addresses 
      are stored in the registry, under 
      <BR><BR>[HKEY_LOCAL_MACHINE\Enum\Root\<BR>[HKEY_LOCAL_MACHINE\Enum\BIOS\<BR>[HKEY_DYN_DATA\Config 
      Manager\Enum\ <BR><BR>You can read the registry data with API calls.</P>
      <P>From Dominic On: Option 3 is difficult in Windows 95. I tested many PCs 
      and found that the byte location of the port address is different from one 
      PC to another. But in windows NT it's OK. Based on the 3 options above, I 
      came up with a solution: 1. Use an API call to detect which platform is 
      running. (95 or NT) 2. If 95, use Toolhelp32ReadProcessMemory() function 
      to find the port address. 3. If NT, read the port address from the 
      registry. My application/DLL runs OK in windows 95. But when it runs in 
      NT, I receive an error that Toolhelp32ReadProcessMemory() is not found in 
      the Kernel32. Therefore, when I release my program/DLL, I have to compile 
      conditionally in 2 versions (Windows 95 and NT).</P>
      <P>And Bill McCarthy contributes this code that shows how to use 
      Toolhelp32ReadProcessMemory to obtain port addresses:</P>
      <P><FONT face="Courier New, Courier, mono">Declare Function 
      Toolhelp32ReadProcessMemory Lib "KERNEL32" _ <BR>&nbsp;&nbsp;(ByVal 
      th32ProcessID As Long, _ <BR>&nbsp;&nbsp;ByVal lpBaseAddress As Long, _ 
      <BR>&nbsp;&nbsp;lpBuffer As Any, _ <BR>&nbsp;&nbsp;ByVal cbRead As Long, _ 
      <BR>&nbsp;&nbsp;ByRef lpNumberOfBytesRead As Long) <BR>As Long </FONT></P>
      <P><FONT face="Courier New, Courier, mono">Sub Main() <BR>Dim i As Long, 
      rtn As Long <BR>Dim portAddresses(3) As Integer <BR>Dim cbLen As Long 
      <BR></FONT></P>
      <P><FONT face="Courier New, Courier, mono">cbLen = 8 <BR>rtn = 
      Toolhelp32ReadProcessMemory _<BR>&nbsp;&nbsp; </FONT><FONT 
      face="Courier New, Courier, mono">(0&amp;, _<BR>&nbsp;&nbsp; 
      &amp;H408&amp;, _<BR>&nbsp;&nbsp; </FONT><FONT 
      face="Courier New, Courier, mono">portAddresses(0), _<BR>&nbsp;&nbsp; 8, 
      _<BR>&nbsp;&nbsp; cbLen) <BR>'Debug.Print rtn, cbLen <BR></FONT></P>
      <P><FONT face="Courier New, Courier, mono">For i = 0 To 3 
      <BR>&nbsp;&nbsp;If portAddresses(i) = 0 Then Exit For 
      <BR>&nbsp;&nbsp;Debug.Print _<BR></FONT><FONT 
      face="Courier New, Courier, mono">&nbsp;&nbsp;"port address " &amp; i 
      &amp; " = &amp;H" &amp; Hex$(portAddresses(i)) <BR>Next i <BR></FONT></P>
      <P><FONT face="Courier New, Courier, mono">End Sub</FONT></P>
      <P>Peter Burke offers this code that dynamically loads the 
      Toolhelp32ReadProcessMemory <BR>function under WIN9X only, thus allowing a 
      single binary for both WIN9X/NT.<BR><BR><FONT 
      face="Courier New, Courier, mono">#include &lt;windows.h&gt;<BR>#define 
      TEST_WINDOWS_NT (!(GetVersion() &amp; 
      0x80000000))<BR>/*********************************************************************<BR>******************/<BR>int 
      GetParallelControllerKey(char *parKey)<BR>{<BR>HKEY hKey;<BR>char 
      myData[255];<BR>LONG res;<BR>DWORD mySize;<BR>FILETIME 
      ftLastWriteTime;<BR><BR>if 
      (NULL==parKey)<BR>return(-1);<BR><BR>*parKey=0;<BR><BR>char 
      myKey[255];<BR>sprintf(myKey,"HARDWARE\\DESCRIPTION\\System");<BR><BR>res 
      = RegOpenKeyEx(HKEY_LOCAL_MACHINE,myKey, 0, KEY_READ, 
      &amp;hKey);<BR><BR>if (res!=ERROR_SUCCESS)<BR>return(-1);<BR><BR>DWORD 
      dwIndex1;<BR>char myKey1[255];<BR>for 
      (dwIndex1=0;dwIndex1&lt;=10;dwIndex1++)<BR>{<BR>mySize=sizeof(myData);<BR>res 
      = 
      <BR>RegEnumKeyEx(hKey,dwIndex1,myData,&amp;mySize,NULL,NULL,NULL,&amp;ftLastWriteT<BR>ime);<BR><BR>if 
      (res==ERROR_SUCCESS) // ERROR_SUCCESS 
      1<BR>{<BR>strcpy(myKey1,myKey);<BR>strcat(myKey1,"\\");<BR>strcat(myKey1,myData);<BR><BR>HKEY 
      hKey1;<BR>res = RegOpenKeyEx(HKEY_LOCAL_MACHINE,myKey1, 0, KEY_READ, 
      <BR>&amp;hKey1);<BR><BR>if 
      (res!=ERROR_SUCCESS)<BR>return(-1);<BR><BR>DWORD dwIndex2;<BR>char 
      myKey2[255];<BR>for 
      (dwIndex2=0;dwIndex2&lt;=10;dwIndex2++)<BR>{<BR>mySize=sizeof(myData);<BR>res 
      = 
      <BR>RegEnumKeyEx(hKey1,dwIndex2,myData,&amp;mySize,NULL,NULL,NULL,&amp;ftLastWrite<BR>Time);<BR><BR>if 
      (res==ERROR_SUCCESS) // ERROR_SUCCESS 
      2<BR>{<BR>strcpy(myKey2,myKey1);<BR>strcat(myKey2,"\\");<BR>strcat(myKey2,myData);<BR><BR>HKEY 
      hKey2;<BR>res = <BR>RegOpenKeyEx(HKEY_LOCAL_MACHINE,myKey2, 0, KEY_READ, 
      &amp;hKey2);<BR><BR>if (res!=ERROR_SUCCESS)<BR>return(-1);<BR><BR>DWORD 
      dwIndex3;<BR>for 
      (dwIndex3=0;dwIndex3&lt;=10;dwIndex3++)<BR>{<BR>mySize=sizeof(myData);<BR>res 
      = 
      <BR>RegEnumKeyEx(hKey2,dwIndex3,myData,&amp;mySize,NULL,NULL,NULL,&amp;ftLastWrite<BR>Time);<BR><BR>if 
      (res==ERROR_SUCCESS) // <BR>ERROR_SUCCESS 3<BR>{<BR>if 
      <BR>(0==strcmp(myData,"ParallelController") 
      )<BR>{<BR><BR>strcpy(parKey,myKey2);<BR><BR>strcat(parKey,"\\");<BR><BR>strcat(parKey,myData);<BR>return(0);<BR>}<BR>} 
      // ERROR_SUCCESS 3<BR><BR>} // for (dwIndex3<BR><BR>} // // ERROR_SUCCESS 
      2<BR><BR>} // for (dwIndex2<BR><BR>} // ERROR_SUCCESS 1<BR><BR>} // for 
      (dwIndex1<BR><BR>return(-1);<BR>} //GetParallelControllerKey 
      <BR><BR>/*********************************************************************<BR>******************/<BR>int 
      GetAddressLptPortInTheRegistry(int myPort)<BR>{<BR>HKEY phkResult;<BR>char 
      myKey[255];<BR>char myData[255];<BR>LONG res;<BR>DWORD mySize;<BR>DWORD 
      myType;<BR><BR>res=GetParallelControllerKey(myKey);<BR>if (res &lt; 
      0)<BR>return(-1);<BR><BR>sprintf(myData,"%s\\%d",myKey,myPort-1);<BR><BR>res 
      = RegOpenKeyEx(HKEY_LOCAL_MACHINE,myData, 0, KEY_READ, 
      <BR>&amp;phkResult);<BR>if (res != 
      ERROR_SUCCESS)<BR>return(-1);<BR><BR>mySize=sizeof(myData);<BR>myType=REG_BINARY;<BR><BR>res=RegQueryValueEx(<BR>phkResult, 
      // handle to key to query<BR>"Configuration Data", // address of name of 
      value to query<BR>NULL, // reserved<BR>&amp;myType, // address of buffer 
      for value type<BR>(unsigned char *)myData, // address of data 
      buffer<BR>&amp;mySize // address of data buffer size<BR>);<BR>if (res != 
      ERROR_SUCCESS)<BR>return(-1);<BR><BR>//printf("config data port %d 0x14 = 
      0x%02X 0x15 = 
      <BR>0x%02X\n",myPort,myData[0x14],myData[0x15]);<BR>return(myData[0x14] | 
      myData[0x15]&lt;&lt;8 );<BR>}<BR><BR>typedef BOOL (CALLBACK * 
      PROCTYPE_Toolhelp32ReadProcessMemory)( DWORD <BR>, LPCVOID, LPVOID, DWORD 
      ,LPDWORD);<BR>/*********************************************************************<BR>******************/<BR>int 
      GetAddressLptPortInTheMemory(int myPort)<BR>{<BR>HINSTANCE hDLL=NULL; // 
      Handle to DLL<BR>PROCTYPE_Toolhelp32ReadProcessMemory 
      myProcPointer=NULL;<BR><BR>hDLL = LoadLibrary("kernel32");<BR>if 
      (hDLL==NULL)<BR>return(-1);<BR><BR>myProcPointer=(PROCTYPE_Toolhelp32ReadProcessMemory)GetProcAddress(hDL<BR>L,"Toolhelp32ReadProcessMemory");<BR>if 
      (myProcPointer==NULL) /*handle the error*/<BR>{ <BR>FreeLibrary(hDLL); 
      <BR>return -1;<BR>}<BR><BR>int portAddresses[]={0,0,0,0,0};<BR>BOOL 
      rtn=0;<BR>DWORD cbLen=0;<BR>//rtn = Toolhelp32ReadProcessMemory <BR>rtn = 
      myProcPointer<BR>(0,<BR>(LPCVOID *) 
      0x408,<BR>portAddresses,<BR>8,<BR>NULL) ;<BR><BR>FreeLibrary(hDLL); 
      <BR><BR>if (rtn==0)<BR>return(-1);<BR><BR>if 
      (portAddresses[myPort-1]&lt;=0)<BR>return(-1);<BR><BR>if 
      (portAddresses[myPort-1]&gt;=0x1000)<BR>return(-1);<BR><BR>return(portAddresses[myPort-1]);<BR>}<BR><BR>/*********************************************************************<BR>******************/<BR>int 
      GetAddressLptPort(int 
      myPort)<BR>{<BR>if(myPort&lt;1)<BR>return(-1);<BR><BR>if(myPort&gt;3)<BR>return(-1);<BR><BR>if 
      (TEST_WINDOWS_NT)<BR>return(GetAddressLptPortInTheRegistry(myPort));<BR><BR>return(GetAddressLptPortInTheMemory(myPort));<BR>}<BR></FONT></P>
      <P><I>Q: How can I access ports using Perl?</I></P>
      <P>A: (from Ron Glick)</P>
      <P>You must have the Win32::API module (available at www.cpan.org) 
      installed.</P>
      <P><FONT face="Courier New, Courier, mono">use Win32::API; #load API 
      module to interface DLL's <BR>$GetPortVal= new Win32::API("inpout32", 
      "Inp32", [I], I); #import Inp32 from DLL <BR>$SetPortVal= new 
      Win32::API("inpout32", "Out32", [I,I], I); #import Out32 from 
      DLL<BR>$input= $GetPortVal-&gt;Call(0x378) &amp; 255; #get and display 
      current value of address <BR>378 hex print "$input\n"; 
      <BR>$return=$SetPortVal-&gt;Call(0x378,35); #set pins 2,3,7 <BR>$input= 
      $GetPortVal-&gt;Call(0x378) &amp; 255; #get and display updated value of 
      address 378 hex <BR>print "$input\n";</FONT></P>
      <H2>What Type of Port? </H2>
      <P><I>Q: How can I tell what type of port I have? </I></P>
      <P>A: These are some ways to detect what type of port a system has: SPP 
      (original), PS/2 (simple bidirectional), EPP, or ECP. The explanations 
      assume that you have some familiarity with the different port types and 
      how to access port registers. These tests detect only what type of port is 
      currently enabled! If the advanced modes are disabled on the port 
      controller chip, the tests won't detect them. </P>
      <P>On many ports that support advanced modes, you can configure the port 
      either in the CMOS setup, or with jumpers, or with configuration software 
      that comes with the port. Most have an option that causes the port to 
      emulate the original SPP, plus one or more options that enable the 
      advanced modes. If the port is configured as an SPP, the advanced modes 
      will be locked out and the port will fail any tests for PS/2, EPP, or ECP 
      abilities. </P>
      <P>Detecting an ECP </P>
      <P>In testing a port, you might think that the first step would be to test 
      for an SPP, and work your way on up from there. But if the port is an ECP, 
      and it happens to be in its internal SPP-emulation mode, the port will 
      fail the PS/2 (bidirectional) test. For this reason, I begin by testing 
      for an ECP, and work down from there. This is the method Microsoft's ECP 
      document (in the Developer's Network CD-ROM) recommends for detecting an 
      ECP: 1. Read the ECP's extended control register (ECR) at base address + 
      402h and verify that bit 0 (fifo empty) =1 and bit 1 (fifo full) =0. These 
      bits should be distinct from bits 0 and 1 in the port's control register 
      (at base address + 2). You can verify this by toggling one of the bits in 
      the control register, and seeing that the corresponding bit in the ECR 
      doesn't change. 2. A further test is to write 34h to the ECR and read it 
      back. Bits 0 and 1 in the ECR are read-only, so if you read 35h, you 
      almost certainly have an ECP. If an ECP exists, you can read and set the 
      ECP's internal mode in the ECR. (See below.) </P>
      <P>Detecting an EPP </P>
      <P>In addition to the SPP's three registers, an EPP has four additional 
      registers, at base address + 3 through base address + 6. These additional 
      registers provide a way to test for the presence of an EPP, by writing a 
      couple of values to one of the EPP registers and reading them back, much 
      like you would test for an SPP. If the reads are successful, the register 
      exists and you probably have an EPP. I'm not sure if this test works on 
      all EPPs. Because the EPP handshake doesn't complete, there's no guarantee 
      of the contents of the register after the transfer times out. But on the 
      tests I've done, I was able to read back the values written. Be sure to 
      clear the EPP timeout bit (bit 0 of the status port, at base address + 1) 
      after each read or write. Unfortunately, the method for clearing the bit 
      varies with the controller chip. On some ports, you clear the bit by 
      writing 1 to it. On others, simply reading the status register clears the 
      bit. And, though I haven't seen any controllers that clear the bit in the 
      conventional way, by writing 0 to it, you may as well do that too, just to 
      be safe. </P>
      <P>Beware #1: on SMC's chips (&amp; maybe others), a set timeout bit can 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -