Translate

Mostrando postagens com marcador XFS. Mostrar todas as postagens
Mostrando postagens com marcador XFS. Mostrar todas as postagens

quinta-feira, 29 de setembro de 2011

Desenvolvendo Drivers XFS - Detalhes

Olá leitores. Tenho recebido vários e-mails com pedidos de mais informações de como construir um Service Provider. Há algum tempo, eu publiquei um overview sobre isso (Desenvolvendo Drivers XFS - Overview), mas realmente não passou de um breve resumo. De fato não é uma coisa trivial, e não há muito material disponível. Por isso, vou tentar colocar as informações essenciais (sem muitos detalhes) para guiar o desenvolvimento dos incautos que quiserem tentar construir um Service Provider.

Por motivos econômicos, vou referir-me a Service Provider apenas como SP.

Pré-requisitos para essa peleja
Para conseguir desenvolver satisfatoriamente um SP, é necessário um conhecimento intermediário-avançado sobre threads e desenvolvimento Win32. Além disso, será necessário ter um bom conhecimento sobre o desenvolvimento de DLLs em alguma plataforma de desenvolvimento, como por exemplo: Microsoft Visual C++, Borland C++ Builder ou outra qualquer.

Além disso é necessário ler o documento 1 da especificação CEN/XFS (na versão que se pretende para o SP), e o documento relativo a classe de dispositivo que se pretende desenvolver. Por exemplo, caso se esteja usando a especificação versão 2 de Dezembro de 1998, e o objetivo seja o desenvolvimento para uma impressora, os documentos necessários seriam: CWA13449-1.pdf e CWA13449-3.pdf.

Requisitos do SP
Tudo o que é preciso ter em um SP está descrito nos dois documentos da especificação indicados acima. No entanto, a seguir eu relacionou os requisitos chave de qualquer SP:

  1. Exportar as 11 funções WFPXXXXX descritas na especificação: são através dessas funções que se garante a aderência à especificação, por isso elas precisam existir no SP, e precisam também ter um comportamento aderente à especificação;
  2. Funcionamento assíncrono: O SP é assíncrono. Isso é muito importante, mas às vezes passa desapercebido. O ponto é que o protocolo de comunicação entre o SP e o XFS Manager é baseando em regras assíncronas. O XFS Manager é quem permite, artificialmente, que uma aplicação faça chamadas síncronas. Basicamente o que ele faz é aguardar o retorno do atendimento da request por parte do SP antes de retornar a chamada para a aplicação;
  3. Suportar multi-sessões: O SP precisa ser projetado para atender mais de uma aplicação ao mesmo tempo. Isso é muito importante, pois praticamente todos os sistemas de autoatendimento possuem agentes de monitoração que funcionam de modo não integrado à aplicação, e com isso um SP multi-sessão é indispensável;
Arquitetura do SP
Um SP tem, basicamente, duas grandes partes com responsabilidades bem definidas nas quais se concentram os componentes constituintes de qualquer SP:
  1. Estrutura compartilhada: Essa parte do SP é onde se concentra a maior complexidade desse desenvolvimento. Ela é comum a qualquer SP, sem mudanças (se for projetado corretamente).  Em geral, se constrói um ambiente de desenvolvimento de SPs, onde essa parte é compartilhada entre todos os SPs da solução. Mas, essa parte tem tantos componentes críticos que são tão complexos que é muito comum que as empresas e pessoas comprem essa parte pronta de alguma outra empresa que já a tenha construída e debugada (que é o mais importante). Essa parte do desenvolvimento se concentra quase que inteiramente no documento 1 da especificação. Os componentes mais básicos dessa parte são:
    • Gestor de Trace: responsável pela geração de logs do SP. Esse componente pode ser bem simples, onde apenas se escreve o que se quer em um arquivo de log, ou então pode ser bem complexo definindo níveis dos logs que serão gravados, estratégia de rotate, limite de tamanho e etc. Para essa parte, utilizar um framework de mercado como o log4cxx é uma alternativa bem interessante;
    • Gestor de eventos: o SP é basicamente orientado à eventos, ou seja, ele envia e recebe eventos o tempo todo para poder informar que uma operação foi concluída ou que um marco foi alcançado no processamento ou ainda que um limite foi atingido;
    • Agendador de requisições: o SP tem que ser assíncrono conforme os requisitos chaves. Isso quer dizer que qualquer comando que o SP receber deverá ser agendado para execução posterior. Isso é muito importante, pois é preciso prever que um mesmo comando será chamado várias vezes (várias aplicações acessando o SP). Com isso, o agendador precisa implementar uma estratégia de agendamento baseada em fila;
  2. Estrutura específica: Essa parte do SP muda de acordo com a classe de dispositivo e também de acordo com a interface do device driver. Essa é a parte do SP que precisa se comunicar efetivamente com o device driver, que é o controlador do dispositivo. Essa parte pode ser projetada de modo que o comportamento especifico da classe XFS seja resolvido junto com a interface do device driver. No entanto, a solução que mais me agrada é separar as duas coisas; Essa parte do desenvolvimento se concentra inteiramente no documento relativo a classe de dispositivo no qual o SP será construído. Os componentes mais básicos dessa parte são:
    • Interface do Device Driver: este é o ponto de acesso ao dispositivo. Então aqui, em geral, existe uma classe com métodos que dão acesso a funções exportadas em uma dll ou lib do device driver que controla o dispositivo;
    • Implementação da classe de dispositivo XFS: aqui deve ser implementado o comportamento específico da classe de dispositivo XFS de qual trata o SP. Por exemplo, se o SP for para impressora, então a classe de dispositivo é a PTR e deve-se então consultar a especificação dessa classe no conjunto de documentos XFS. No caso da impressora o documento é CWA13449-3.pdf;

Codificação
Aqui a dica é criar um projeto de DLL. Essa DLL precisa exportar as 11 funções previstas na especificação, e toda vez que essas funções forem executadas, uma sequencia de acontecimento deve ocorrer no interior do SP. Basicamente a sequencia é a seguinte:
  1. Verificar informações básicas a cerca dos parâmetros recebidos e também o estado em que se encontra a sessão. Por exemplo, um WFSExecute só pode ser executado após um WFSOpen. Ainda, se for executado um WFSLock, somente a aplicação que possui o "lock" poderá executar WFSExecute. As demais aplicações que não possuírem o "lock" poderão apenas consultar informações, executando, por exemplo WFSGetInfo;
  2. Agendar o processamento dessa "solicitação", armazenando todos os parâmetros da chamada em uma fila;
  3. Retornar WFS_SUCCESS para a chamada da função. Obviamente esse retorno significa apenas: "Ok, tudo certo até aqui, eu posso processar sua requisição...". Caso não seja esse o caso, precisa então ser retornado um código de erro que melhor indique o motivo pelo qual a solicitação não pôde ser atendida;
  4. Assim que possível, retirar solicitações da fila, analisar seus parâmetros e processa-los de acordo com a especificação para aquela classe de dispositivo. O resultado do processamento é SEMPRE um evento. Ou seja, mesmo que o resultado do processamento seja um erro, um evento deve ser gerado para o XFS Manager, informando-o desse resultado. Esse evento nada mais é do que uma mensagem windows, direcionada para o handle indicado nos parâmetros da chamada. Claro que isso aqui é uma aproximação simplista. De fato, existem mais questões envolvidas aqui como: verificar se não foi atingido o timeout para execução da solicitação, lançar eventos intermediários, notificar aplicações ouvintes que se registram para receber certo tipos de eventos e etc;

Testes
Bom, para testar o SP é necessário uma aplicação XFS para a classe de dispositivo em questão. Essa parte é bem mais fácil, e é possível construir rapidamente essa aplicação de testes. A aplicação pode ser inclusive construída para operar com uma interface de linha de comando. Para fazer essa construção basta utilizar o documento 1 da especificação, buscando informações sobre as funções WFSXXXX contidas no capitulo 4 (Application Programming Interface (API) Functions). A sequência básica de comandos para uma aplicação XFS é a seguinte:
  1. WFSStartUp;
  2. WFSOpen;
A partir daí, é possível executar os comandos específicos da classe utilizando os comandos WFSExecute e WFSGetInfo.


É isso. Té mais!!!



sábado, 30 de outubro de 2010

Desenvolvendo Drivers XFS - Overview

Olá leitores,

Atendendo à pedidos, vou postar aqui um overview sobre o desenvolvimento de drivers XFS. Eu estava evitando postar artigos tão técnicos, pois este blog também é lido por pessoas leigas. Mas, sou refém de minha palavra. Assim, se você não é desenvolvedor, e nem quer ser, melhor então não perder tempo lendo a este post (mas não temas, pois mais posts interessantes e orientados ao público em geral estão por vir!).

Vamos lá então. Vou começar falando um pouco da motivação e escolhas do ponto de vista da empresa que tem que fornecer drivers, e depois entro na parte mais técnica, explicando as conseqüências dessas escolhas e como lidar com elas.

Escolha: XFS, J/XFS ou padrão proprietário?
Se você trabalha em uma empresa que fornece equipamentos para a automação bancária e comercial, diretamente para o cliente final, então você muito provavelmente deve ter tido essa discussão internamente em sua empresa. Qual a melhor escolha, para montarmos a infra-estrutura de drivers do equipamento? Devo projetar tudo em XFS, J/XFS ou faço a coisa funcionar em um padrão proprietário? Bem, normalmente são as demandas dos clientes que nos auxiliam nessa tomada de decisão. Afinal, não adianta você construir sua infra-estrutura em um padrão proprietário, se seus clientes não quiserem fazer uso desse padrão em suas aplicações! E sua empresa não vai querer perder projetos com potencial de milhões de reais, só porque ninguém havia pensado em investigar um pouco o que o mercado demanda em relação a essa questão.

Pois bem, no que diz respeito ao mercado de ATMs e terminais de auto-atendimento em geral, se você é uma empresa que fornece esses equipamentos, então você pode descartar o padrão proprietário (para a camada de negócio), e você terá que adotar o padrão XFS e também o J/XFS. O fato é que o mercado usa XFS, a maioria dos bancos o usam, então essa é a primeira infra-estrutura na qual você terá que investir. Quanto ao padrão J/XFS o fato decorre do advento da expansão de tecnologias como Java e Linux (vide meu post: Guia da Automação Bancária para Iniciantes). Assim, importantes bancos como Caixa Econômica Federal e Banco do Brasil estão utilizando drivers J/XFS em seus ATMs e terminais financeiros, e essa tem sido realmente uma tendência. A prioridade é menor do que a necessidade de um driver XFS, mas é importante que você planeje ter uma infra-estrutura em J/XFS, até para tentar aproveitar o trabalho a ser realizado junto ao desenvolvimento do driver XFS.

Agora, se você é uma empresa que fornece dispositivos a serem utilizados na automação bancária e comercial em geral, é mais provável que você consiga atender a maioria de seus clientes, utilizando até mesmo um padrão proprietário para a camada de acesso ao dispositivo. Isso ocorre porque em geral, o teu dispositivo é parte de uma solução maior (exemplo, você fornece a impressora térmica que é utilizada em um ATM), e a responsabilidade de fornecer a infra-estrutura de drivers da camada de negócio (ou seja, a parte que fará interface com a aplicação), é em geral da empresa que está fornecendo essa solução integrada final.

Qual versão de XFS?
Se você já decidiu que, o que você precisa é uma infra-estrutura XFS, então essa será sua próxima dúvida. O padrão XFS existe há muitos anos, e já se encontra na versão 3.10 de drivers e especificação. No entanto no mercado, ainda existem clientes que utilizam o antigo XFS 2. Nesse caso, não há muita dúvida, prefira sempre a versão mais atual disponível para a infra-estrutura. A própria especificação fornece meios de construir sua infra-estrutura de modo que a mesma funcione sem problemas mesmo sendo acessada a partir de uma aplicação baseada em XFS 2.

Em geral, ao longo da evolução da especificação XFS são adicionados novas classes de dispositivos. No entanto, também é comum haver correções para as classes já existentes, e é por isso que os mecanismos oferecidos de interoperabilidade entre versões XFS é importante, pois você poderá projetar seu driver para levar até isso em consideração, e com uma única infra-estrutura de driver, você poderá atender a um número maior de clientes, usando seja lá qual for a versão do padrão XFS.

Mãos à obra: Por onde eu começo?
Até aqui você, desenvolvedor, estava levantando informações para a tomada de decisão de sua empresa. A decisão final cabe, em geral, ao gerente de projetos, e uma vez que a decisão foi tomada, será responsabilidade sua e de sua equipe, o desenvolvimento da infra-estrutura de drivers no padrão escolhido. A boa notícia é que essa é a parte mais legal do processo :)

Dirimidas todas as dúvidas da tomada de decisão, o momento agora é de realizar downloads! Você terá que fazer o download dos seguintes itens: especificação XFS e SDK, todos coincidentes a versão escolhida. Vamos tomar como exemplo um driver XFS na versão ultima que é a 3.10. Nesse caso, você conseguirá o download dos dois itens no seguinte endereço: CEN WS/XFS.

Com esse material em mãos, você precisará ler, pelo menos, aos documentos da Part 1 - API/SPI Programer's Reference e Part 2 - Service Class Definition - Programmer's Reference. E além desses dois você precisará também ler o documento referente a classe que especifica o tipo de dispositivo para o qual você quer construir o driver XFS. Por exemplo, se você quer desenvolver um driver XFS para uma impressora térmica, então a classe de dispositivo em questão é a PTR, e você encontrará sua especificação no documento CWA 15748- 3.

Conseqüências: Plataforma de desenvolvimento e execução
A tomada inicial de decisão, resultará na definição da plataforma de desenvolvimento da sua infra-estrutura de drivers, e também definirá em que plataforma de sistema operacional ela poderá ser executada.

Se a sua escolha foi por desenvolver a infra-estrutura em XFS, então você deverá saber que sua infra-estrutura somente executará em sistemas Windows. Deverá ter consciência também de que a plataforma de desenvolvimento terá que ser uma que permita a criação de DLL. O SDK do XFS é baseado na API da linguagem C. Por isso, como plataforma de desenvolvimento o melhor é utilizar C ou C++.

Veja que se a escolha tivesse sido desenvolver um driver J/XFS, então as conseqüências seriam bastante diferentes, uma vez que você teria que desenvolver todo ou a maior parte do código em Java, e a solução final seria multi-plataforma, ou seja, executaria em sistemas Windows e também Linux.

Desenvolvendo o driver
Abaixo segue uma figura que mostra a arquitetura de uma solução executando em XFS. Aqui, a sua responsabilidade está na camada mais inferior da solução, que é o Service Provider. Você terá pelo menos um Service Provider, para cada classe de dispositivo que compuser a sua solução, mas você poderá ter um Service Provider por DLL ou uma DLL para vários Service Providers, ou ainda uma única DLL para todos os Services Provider existentes em sua solução (não recomendo essa ultima abordagem):


Sua DLL precisará exportar todas as funções com o prefixo WFP, especificadas no capítulo 6 do primeiro documento da especificação. Abaixo segue uma imagem extraída do Dependency Walker, onde são listadas as funções exportadas por uma DLL que implementa um Service Provider:


Além de exportar essas funções em sua DLL, você terá também que implementá-las de acordo com a especificação, atentando principalmente para o comportamento esperado para cada uma delas. Isso é assim, justamente para que a idéia de se ter um framework realmente funcione. Veja que o objetivo do framework XFS é permitir que aplicações sejam desenvolvidas para a automação bancária e comercial, de uma maneira independente da plataforma de hardware. Quando a especificação é atendida, normalmente os clientes tem livre escolha de fornecedores de hardware, e geralmente utilizam muitos dos principais fornecedores para compor seu parque de equipamentos na produção, e tudo isso utilizando uma única aplicação, que não possui qualquer característica técnica amarrada a nenhum desses fornecedores. Essa é a idéia e é por isso que é necessário se atendar para o que diz a especificação.

Você notará que todas essas funções exportadas são comuns a todos os drivers XFS, sejam eles drivers que atendam a classe PTR (impressora), ou a qualquer outra classe. Na verdade, o comportamento específico de cada classe só vem à tona a partir da função WFPExecute. É com essa função que se acionam os comportamentos ou "comandos" específicos de cada classe de dispositivo. 

Olhando a especificação, você verá que essa função recebe vários parâmetros de execução. Dentre eles está o parâmetro dwCommand. É nesse parâmetro que você receberá a identificação do comando que a aplicação do cliente quer executar junto ao dispositivo implementado pelo seu driver. Por exemplo, se a aplicação quisesse solicitar o status de sua impressora térmica, então ela preencheria esse campo com o valor definido na constante: WFS_INF_PTR_STATUS. E você teria que construir a resposta a esse comando, tomando por base o que diz a especificação no documento da classe PTR. Você notará nesse documento, que todos os "comandos" são identificados por constantes como essa aí, e se dividem em duas categorias: Info Commands, para comandos de informações a cerca do dispositivo e Execute Commands, para comandos de ação junto ao dispositivo. Abaixo segue uma listagem dos comandos suportados pela classe PTR do XFS 3.10:


Você precisará então, ler com atenção a especificação da classe de dispositivo que você está implementando, para que o seu driver se comporte o mais próximo possível do esperado segundo essa especificação.

Como saber se está tudo certo?
Após algum tempo trabalhando com XFS e J/XFS, você notará que as especificações tem brechas ou lacunas. Essas são partes das especificações nas quais um determinado detalhe não ficou tão claro quanto deveria, causando margem a erros de interpretação. Isso ocorre com freqüência, e é realmente um problema para os bancos e demais clientes que utilizam esses padrões, assim como para os fabricantes que fornecem esses drivers. Pois cada um implementa a refirada parte da especificação da maneira que interpretou, e no final das contas um comportamento ou retorno que deveria ser sempre esperado, acaba por ser diferente para cada fornecedor.

Uma boa estratégia é o cliente criar um documento com uma especificação mínima do XFS, contendo todos os retornos e comportamentos que ele espera de um determinado driver XFS. Claro que para dizer que o produto final disso é XFS, terá que se fazer essa mini-especificação baseada na especificação XFS oficial. O fato é que após criado esse "documento de aderência", os fornecedores poderiam adequar seus drivers para que se comportem exatamente conforme o cliente quer, atendendo a especificação XFS do ponto de vista do cliente. Para o cliente isso é muito bom, mas algumas empresas fornecedoras não vêem isso com bons olhos, pois essa estratégia facilmente implicaria em ter uma infra-estrutura de drivers XFS para cada cliente, o que aumenta os custos de manutenção das empresas fornecedoras. Bem, nem tudo é perfeito :)

Um exemplo dessa estratégia é adotada na Espanha, onde um orgão local, equivalente a nossa Febraban, determina que os bancos somente podem comprar terminais de auto-atendimento que sejam certificados/homologados por uma entidade certificadora , normalmente uma empresa terceira (Dynasty TG, nesse caso), a qual basicamente avalia se a infra-estrutura do fornecedor está minimamente aderente ao padrão XFS nos moldes esperados pelas aplicações em execução nos bancos daquele país. Assim, os fornecedores interessados, entram em contato com a Dynasty TG, para submeter seus Drivers XFS ao processo de certificação, e uma vez aprovados, o fornecedor passa a ser reconhecido como um fornecedor certificado e apto a realizar vendas de seus ATMs e terminais de auto-atendimento para os bancos daquele país.

Bem é isso :)

Nota do autor: esse post foi sugerido por Jerry Varela de Manaus/AM.