#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>

#define LPT1_S 0x379

/* Endereco 0x379 (LPT1_S)

   7    6    5    4    3    2    1    0    ÍNDICE
 ---------------------------------------
| 11 | 10 | 12 | 13 | 15 | -- | -- | -- |  PINOS
 ---------------------------------------
   6    5    7    8    4                   CHAVES

A definição das CHAVES leva em consideração ao índice que ele está
Ex: #define LD1 0

OBS: O pino 11 tem sempre seu valor invertido
*/


#define CH6 7
#define CH5 6
#define CH7 5
#define CH8 4
#define CH4 3

#define DEVC++

#ifdef DEVC++
         #include < windows.h>
#endif
#ifdef TURBOC++
         #include <dos.h>
#endif


#define ENTRADA_INICIAL inp32(LPT1_S)
#define N_DIGITOS_DA_SENHA 4

// Senha contendo 4 dígitos
int senha[N_DIGITOS_DA_SENHA]={CH8,CH8,CH8,CH8}; //senha de 4 inteiros (ou melhor, 4 chaves)

/* prototype (function typedef) for DLL function Inp32: */

     typedef short _stdcall (*inpfuncPtr)(short portaddr);
     typedef void _stdcall (*oupfuncPtr)(short portaddr, short datum);

// variaveis globais
     HINSTANCE hLib;
     inpfuncPtr inp32;
     oupfuncPtr oup32;



/*******************************
 * Autor: Frederico Brito Fernandes
 * Data: 22/11/2006
 * Última Alteração: 22/11/2006
 *
 * Objetivo: Função que retorna o nome da Chave
 * Entrada: o valor da chave
 * Retorno: o numero que identifica a chave. Ex: nomeDaChave(CH8) retorna 8,
 *          apesar de CH8 ter o valor 4
 * Saida: nenhuma
 */
int nomeDaChave(int chave){
     switch (chave) {
            case CH4     : return 4;       
            case CH5     : return 5;
            case CH6     : return 6;       
            case CH7     : return 7;       
            case CH8     : return 8;       
     }
}



/*******************************
 * Autor: Frederico Brito Fernandes
 * Data: 22/11/2006
 * Última Alteração: 22/11/2006
 *
 * Objetivo: Imprimir a senha do sistema
 * Entrada: nenhuma
 * Retorno: nenhum
 * Saida: impressão na tela da senha
 */
void imprimeSenha(){
                    int i;
                    for (i=0;i<N_DIGITOS_DA_SENHA;i++){
                        printf("%d",nomeDaChave(senha[i]));
                        }
     }


/*******************************
 * Autor: Frederico Brito Fernandes
 * Data: 22/11/2006
 * Última Alteração: 22/11/2006
 *
 * Objetivo: Função que implementa uma espera em milissegundos
 * Entrada: o tempo de espera (em milissegundos)
 * Retorno: nada
 * Saida: nenhuma impressão na tela, porém a instrução seguinte vai demorar
 *        tempo ms para ser executada
 */
void espera(long tempo){
#ifdef DEVC++
      Sleep(tempo);
#endif
#ifdef TURBOC++
      delay(tempo);
#endif
}



/*******************************
 * Autor: Frederico Brito Fernandes
 * Data: 22/11/2006
 * Última Alteração: 22/11/2006
 *
 * Objetivo: Função que verifica se a chave esta pressionada ou não
 * Entrada: a entrada da porta paralela (LPT1_S) e a chave
 * Retorno: 1, caso a chave foi pressionada
            0, caso contrário
 * Saida: nenhuma
 */
int taPressionada(int entrada, int chave){
    int saida = (( (ENTRADA_INICIAL ^ entrada) >> chave) % 2);
}



/*******************************
 * Autor: Frederico Brito Fernandes
 * Data: 22/11/2006
 * Última Alteração: 22/11/2006
 *
 * Objetivo: Função que retorna qual chave foi pressionada
 * Entrada: o valor da da porta paralela (LPT1_S)
 * Retorno: a chave que foi pressionada
 *          -1, caso nenhuma chave tenha sido pressionada
 * Saida: nenhuma
 */
int retornaPressionada(int entrada){
    if (taPressionada(entrada,CH5)) return CH5;
    if (taPressionada(entrada,CH6)) return CH6;
    if (taPressionada(entrada,CH7)) return CH7;
    if (taPressionada(entrada,CH8)) return CH8;
    return -1;
}



/*******************************
 * Autor: Frederico Brito Fernandes
 * Data: 22/11/2006
 * Última Alteração: 22/11/2006
 *
 * Objetivo: Função que solicita a gravação da senha de 4 dígitos a partir do
 *           pressionamento das chaves
 * Entrada: nenhuma, mas as chaves devem ser pressionadas
 * Retorno: nenhum
 * Saida: (a) para cada pressionamento de chave, será impresso na tela um *
 *        (b) a senha será gravada na variável global 'senha'
 */
int gravaSenha(){
      int entrada = inp32(LPT1_S), contSenha=0, saida=1;
      while(contSenha<N_DIGITOS_DA_SENHA){
                do {
                     entrada = inp32(LPT1_S);
                } while (entrada==ENTRADA_INICIAL);
                senha[contSenha] = retornaPressionada(entrada);
                contSenha++;            
                printf("*");
                espera(500);
                }
                return saida;
}


/*******************************
 * Autor: Frederico Brito Fernandes
 * Data: 22/11/2006
 * Última Alteração: 22/11/2006
 *
 * Objetivo: Função que verifica se a senha digitada, a partir da chaves, é válida
 * Entrada: nenhuma, mas as chaves devem ser pressionadas
 * Retorno:  1, caso a senha esteja correta
 *          -1, caso contrário
 * Saida: para cada pressionamento de chave, será impresso na tela um *
 */
int validaSenha(){
      int entrada, contSenha=0, saida=1;
      while(contSenha<N_DIGITOS_DA_SENHA){
                do {
                     entrada = inp32(LPT1_S);
                } while (entrada==ENTRADA_INICIAL);
                //printf("\nChave pressionada: %d e senha era: %d",retornaPressionada(entrada), senha[contSenha]);               
                if (retornaPressionada(entrada)!=senha[contSenha]) saida=-1;
                contSenha++;            
                printf("*");
                espera(500);
                }
                return saida;
}


/*******************************
 * Autor: Frederico Brito Fernandes
 * Data: 22/11/2006
 * Última Alteração: 22/11/2006
 *
 * Objetivo: Função que inicia a biblioteca inpout32.dll, e inicializa as funções
 *           inp32(int) e oup32(int, int)
 * Entrada: nenhuma, mas usa as variáveis globais hLib, inp32, oup32, assim como
 *          a biblioteca windows.h
 * Retorno:  0, sucesso
 *          -1, caso ocorra algum erro (arquivo inpout32.dll não presente, ou se ele
                estiver corrompido)
 * Saida: mensagens de erro ou de sucesso sendo impressas na tela *
 */
int iniciaBiblioteca(){
     /* Load the library */
     hLib = LoadLibrary("inpout32.dll ");

     if (hLib == NULL) {
          printf("A biblioteca inpout32.dll nao foi encontrada\n\n");
          espera(2000);
          return -1;
     }else {
           printf("Biblioteca inpout32.dll aberta com sucesso...\n\n");
           getch();
           }
     

     /* get the address of the function */

     inp32 = (inpfuncPtr) GetProcAddress(hLib, "Inp32");

     if (inp32 == NULL) {
          printf("GetProcAddress for Inp32 Failed.\n");
          return -1;
     }


     oup32 = (oupfuncPtr) GetProcAddress(hLib, "Out32");

     if (oup32 == NULL) {
          printf("GetProcAddress for Oup32 Failed.\n");
          return -1;
     }  
     
     return 0;   
     
}   



/*******************************
 * Autor: Frederico Brito Fernandes
 * Data: 22/11/2006
 * Última Alteração: 22/11/2006
 *
 * Objetivo: Procedimento teste para verificar qual chave foi pressionada
 * Entrada: nenhuma, mas as chaves devem ser pressionadas, para causar algum efeito
 * Retorno:  o nome da chave pressionada. Ex: se a CH8 for pressionada, ela tem valor
 *           4, porém será retornado o nome dela, que é 8
 * Saida: será impresso na tela o nome da chave pressionada
 */
void procVerificaChavePressionada(){
       // *************************************************************
       // PROCEDIMENTO PARA VERIFICAR QUAL CHAVE ESTÁ SENDO PRESSIONADA       
       //**************************************************************
       while(1){
                system("cls");                                
                printf("Chave pressionada: %d", nomeDaChave(retornaPressionada(LPT1_S)));
                }
     }

     
     
/*******************************
 * Autor: Frederico Brito Fernandes
 * Data: 22/11/2006
 * Última Alteração: 22/11/2006
 *
 * Objetivo: Procedimento para gerar o prompt de validação da senha
 * Entrada: nenhuma, mas ele usa a função validaSenha()
 * Retorno: nenhum
 * Saida: será impresso na tela o módulo para validação da senha
 */     
void procValidaSenha(){
       // ******************************************
       // PROCEDIMENTO PARA PARA VALIDAÇÃO DA SENHA       
       //******************************************
       printf("\n===MODULO PARA VALIDACAO DE SENHA===");            
       printf("\nDigite sua senha: ");
       if (validaSenha()==1){
          printf(" (senha correta)");
          printf("\n\nEntrando no sistema");
          espera(1000);printf(".");espera(1000);printf(".");espera(1000);printf(".");
          }
       else printf(" (senha ERRADA)");
       printf("\n=====================================");            
       espera(2000);
     }



/*******************************
 * Autor: Frederico Brito Fernandes
 * Data: 22/11/2006
 * Última Alteração: 22/11/2006
 *
 * Objetivo: Procedimento para gerar o prompt de gravação da senha
 * Entrada: nenhuma, mas ele usa a função gravaSenha() e imprimeSenha()
 * Retorno: nenhum
 * Saida: será impresso na tela o módulo para gravação da senha nova
 */
void procGravaSenha(){
       // ***************************************
       // PROCEDIMENTO PARA PARA MUDANÇA DE SENHA
       // ***************************************  
       printf("\n===MODULO PARA GRAVACAO DE SENHA===");            
       printf("\nDigite sua senha: ");
       gravaSenha();
       printf("\n\nA senha digitada foi: ");
       imprimeSenha();
       printf("\n===================================");
       espera(2000);
     }


main(){
       int opcao=-1, entrada;
       printf("\nSenha padrao: CH8 CH8 CH8 CH8\n");
       iniciaBiblioteca();   

      
       while (opcao!=CH5){
             system("cls");
             printf("\n\n###########################################\n");        
             printf("############ Tranca Eletronica ############\n");              
             printf("###########################################\n");  
             printf("\nChave 8 - Para validar a senha do sistema");
             printf("\nChave 7 - Para trocar a senha do sistema");
             printf("\nChave 6 - Para resetar a senha do sistema (nao implementada!)");
             printf("\nChave 5 - Sair do programa");
             printf("\n\n\n   Digite sua opcao: ");
             opcao=-1;
             while ( opcao == -1) {
                   opcao=retornaPressionada(inp32(LPT1_S));
             }
             printf("%d\n\n\n", nomeDaChave(opcao));
             espera(1000);
             
             switch(opcao){
                           case CH8: procValidaSenha();break;
                           case CH7: procGravaSenha();break;
                           case CH6: break; //falta fazer, tornar a senha CH8 CH8 CH8 CH8
                           case CH5: break;
                           }
             }
             
      
       printf("\n\nbye...");       
       espera(2000);
       FreeLibrary(hLib);
       }
