Habilitar uma interface USB personalizada para uma impressora 3D

A arquitetura descrita neste tópico permite o suporte para impressoras 3D de interface USB personalizada nos ecossistemas de impressão v3 e v4. Um monitor de porta padrão, 3dmon.dll, encaminha comandos de trabalho de impressão 3D para um Windows 3DPrintService em execução com credenciais de serviço local. O serviço carrega e se comunica com uma DLL de parceiro para executar os comandos personalizados necessários para um trabalho de impressão 3D. A DLL do parceiro, bem como as 3dmon.dll e 3dprintservice.exe redistribuíveis, são instaladas pelo pacote de driver USB do dispositivo. A DLL do parceiro deve implementar e exportar um conjunto de funções para se comunicar com o 3DPrintService. O restante da funcionalidade necessária para interagir com o serviço de spooler de impressão é implementado no 3dmon.dll.

Observação

Essa arquitetura requer a DLL do parceiro para várias instâncias, thread-safe.

Decisões de arquitetura

O serviço windows 3DPrintService é usado para carregar e invocar APIs definidas específicas em DLLs fornecidas pelo parceiro durante um fluxo de trabalho de impressão. Essas APIs permitirão a comunicação com a impressora.

Os pacotes de driver de filtro USB KMDF são publicados em Windows Update para instalação via PnP para uma impressora 3D com suporte. O driver KMDF instala o software parceiro e cria um nó de dispositivo de impressora 3D. O nó do dispositivo de impressora 3D é instalado usando um driver de impressão v4 publicado pelo parceiro de Windows Update.

Decisões de empacotamento

Binários e dependências binárias

A arquitetura usa um driver publicado pelo fabricante do hardware no Windows Update. Esse driver inclui os seguintes binários redistribuíveis fornecidos pela Microsoft e suas dependências:

  • 3dmon.dll

  • 3dprintservice.exe

  • ms3dprintusb.sys

Driver de filtro USB no modo kernel

O driver KMDF é publicado pelo parceiro e consiste em componentes mostrados no diagrama abaixo. Isso corresponde ao dispositivo com uma ID de hardware (normalmente, uma VID & PID). O driver cria um nó de dispositivo de impressora 3D na instalação que dispara a instalação da fila de impressão e dos drivers de segmentação de dados. O parceiro fornece drivers de impressora v4 para o nó de dispositivo de impressora 3D criado.

driver de filtro usb kmdf.

MS3DPrintUSB.sys

O driver de dispositivo do modo kernel que cria o nó de desenvolvimento da impressora 3D em Enum\3DPrint. Ele é invocado pelo subsistema PnP por meio de uma correspondência direta da VID & PID com base no nó do dispositivo criado por Winusb.sys. O arquivo .inf do driver configura a DLL personalizada usada para definir o 3DPrintService (se ainda não estiver instalado no sistema).

3dmon.dll

3DMon.dll é um binário redistribuível do monitor de porta publicado pela Microsoft invocado pelo spooler para se comunicar com a impressora 3D.

3dprintservice.exe

3DPrintService.exe é um binário publicado pela Microsoft instalado como um serviço Windows durante a instalação do driver. O 3DMon se comunica com esse serviço para executar operações como impressão, bidi e assim por diante com a impressora 3D.

Partnerimpl.dll

Partnerimp.dll é a implementação do parceiro da interface da Microsoft publicada. A DLL se comunica com o dispositivo do parceiro usando seus protocolos. 3DPrintService.exe carrega essa DLL em runtime para conduzir as operações do dispositivo de impressora 3D.

Diagrama que mostra o fluxo de comunicação do dispositivo para operações de dispositivo de impressora 3D.

Sequência de uso da impressora

  • O spooler se comunica com 3dmon.dll que envia comandos para o serviço windows 3DPrintService

  • O 3DPrintService.exe é executado com as credenciais da conta de NetworkService

  • O spooler, via 3dmon.dll, envia comandos para 3DPrintService sempre que a impressora 3D é usada

  • O 3DPrintService processa comandos e invoca APIs em runtime em DLLs de implementação fornecidas pelo parceiro

  • O 3DPrintService entrega as respostas de DLLs fornecidas pelo parceiro de volta para o spooler

Interfaces e interações

A DLL do parceiro deve exportar as seguintes funções de API:

HRESULT Install([in] LPCWSTR args)

Essa API é opcional e pode ser usada pelo fabricante para instalar o software personalizado ou o registro para seu dispositivo. Por exemplo, a instalação da modelagem incluída com o pacote de driver para o dispositivo. Essa API é invocada com credenciais SYSTEM para habilitar a instalação.

DWORD PrintApiSupported()

Essa API é usada pelos fabricantes de terceiros para indicar a versão da API do serviço de impressão 3D com suporte. As APIs abaixo são compatíveis com a versão 1 do 3DPrintService.

HRESULT InitializePrint(LPCWSTR pPrinterName, LPCWSTR pPortName, DWORD dwJobId, LPVOID* ppPartnerData)

Essa API é invocada antes de um evento de impressão começar a inicializar a impressora. A impressora pode salvar o estado específico do trabalho no parâmetro ppPartnerData. Essa chamada é análoga a uma invocação StartDocPort.

  • jobId – ID do trabalho usada para acompanhar o trabalho

  • portName - portname para a impressora 3D

  • printerName - nome da impressora para a qual este trabalho de impressão está sendo enviado

  • ppPartnerData - ponteiro para ponteiro que pode ser usado para armazenar dados específicos do trabalho

HRESULT PrintFile([in] DWORD jobId, [in] LPWSTR portName, [in] LPWSTR printerName, [in] LPWSTR pathToRenderedFile,[in]LPVOID* ppPartnerData)

Essa API é usada por fabricantes de terceiros para imprimir o documento em sua impressora.

  • jobId – ID do trabalho usada para acompanhar o trabalho

  • portName - portname para a impressora 3D

  • printerName - nome da impressora para a qual o trabalho de impressão está sendo enviado

  • pathToRenderedFile – caminho UNC para o local do arquivo em spool após a renderização ter sido executada. O fabricante de terceiros processa o arquivo desse local e imprime o documento em seu dispositivo

  • ppPartnerData - ponteiro para o ponteiro emitido para armazenar a configuração de dados específica do parceiro durante a chamada à API InitializePrint.

  • printerName pode ser obtido do registro usando o nome da porta. Os fabricantes de terceiros podem não ser capazes de usar o nome da porta para se comunicar com seu dispositivo. O nome da impressora é exclusivo em um computador Windows e seu software será capaz de identificar em qual impressora imprimir o trabalho. Todas as impressoras ativas em um computador podem ser encontradas na seguinte chave do Registro:

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Printers

Registro de impressora 3d.

HRESULT Query(_In_ LPCWSTR command, _In_ LPCWSTR commandData, _Out_ LPWSTR resultBuffer, _Out_ resultBufferSize, , _In_ LPVOID* ppPartnerData)

  • command – comando de cadeia de caracteres enviado como uma consulta

  • commandData - argumentos de comando (opcional)

  • resultBuffer – resultado da invocação de argumentos de consulta>

  • resultBufferSize - tamanho da cadeia de caracteres do buffer de resultado

  • ppPartnerData - ponteiro para ponteiro para a instância de DLL do parceiro atual

O serviço 3Dprint invoca a DLL do parceiro para obter o tamanho do buffer a ser alocado para o comando.

Depois de alocar memória para manter a cadeia de caracteres de resposta, a DLL será invocada novamente para obter o resultado real.

A DLL pode usar os dados de instância de uma chamada IntializePrint() anterior para se comunicar com o dispositivo sem abrir um novo canal de comunicação sempre que a função Query() for chamada.

Essa API é usada para se comunicar com a impressora para obter informações sobre a configuração do dispositivo, o progresso da impressão ou para notificar a DLL do parceiro sobre eventos de desconectamento do dispositivo.

Os comandos abaixo devem ter suporte do fabricante:

Comando CommandData Saída Comentários
\\Printer.3DPrint:JobStatus Trabalho Iniciado = {"Status": "ok"}, Status a ser usado na Conclusão {"Status": "Concluído"} O spooler exibirá qualquer valor retornado na interface do usuário da fila de impressão. Isso permite que o dispositivo exiba informações relevantes durante uma impressão na interface do usuário da fila de impressão. O dispositivo pode retornar uma cadeia de caracteres arbitrária aqui (por exemplo, "Ocupado" ou "33% concluído") e isso será exibido textualmente no trabalho da fila de impressão status.
\\Printer.3DPrint:JobCancel {"Status": "Concluído"} O spooler invocará esse comando quando um usuário cancelar uma impressão. A DLL do parceiro retorna esse valor quando o cancelamento foi bem-sucedido e os identificadores e threads foram fechados.
\\Printer.Capabilities:Data Cadeia de caracteres XML em conformidade com o esquema PrintDeviceCapabilites (PDC). A consulta PDC é invocada por aplicativos que desejam obter mais informações sobre a impressora. Os dados são usados para descrever os recursos do dispositivo e podem incluir as configurações de segmentação de dados se o driver depender da segmentação de dados da Microsoft. Veja abaixo um exemplo de PDC.
\\Printer.3DPrint:Disconnect {"Status": "OK"} Essa consulta é disparada sempre que há uma desconexão PnP do dispositivo de impressora. Os parceiros podem realizar todas as ações necessárias, por exemplo, fechar todos os identificadores abertos para permitir a reconexão adequada.
\\Printer.3DPrint:Connect {"Status":"OK"} Essa consulta é disparada sempre que há uma conexão PnP do dispositivo de impressora. Os parceiros podem realizar quaisquer ações necessárias.

Os seguintes recursos de dispositivo de impressão XML podem ser usados como exemplo:

<?xml version="1.0"?>
<PrintDeviceCapabilities
    xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="https://www.w3.org/2001/XMLSchema"
    xmlns:xml="https://www.w3.org/XML/1998/namespace"
    xmlns:psk="https://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords"
    xmlns:psk3d="https://schemas.microsoft.com/3dmanufacturing/2013/01/pskeywords3d"
    xmlns:psk3dx="https://schemas.microsoft.com/3dmanufacturing/2014/11/pskeywords3dextended"
    xmlns:pskv="https://schemas.microsoft.com/3dmanufacturing/2014/11/pskeywordsvendor"
    xmlns:psf="https://schemas.microsoft.com/windows/2003/08/printing/printschemaframework"
    xmlns:psf2="https://schemas.microsoft.com/windows/2013/12/printing/printschemaframework2"
    xmlns="https://schemas.microsoft.com/windows/2013/12/printing/printschemaframework2"
    version="2">
    <CapabilitiesChangeID xsi:type="xsd:string">{9F58AF07-DCB6-4865-8CA3-A52EA5DCB05F}</CapabilitiesChangeID>

  <psk3d:Job3DOutputArea psf2:psftype="Property">
    <psk3d:Job3DOutputAreaWidth>150001</psk3d:Job3DOutputAreaWidth>
    <psk3d:Job3DOutputAreaDepth>150001</psk3d:Job3DOutputAreaDepth>
    <psk3d:Job3DOutputAreaHeight>150001</psk3d:Job3DOutputAreaHeight>
  </psk3d:Job3DOutputArea>

  <psk3d:Job3DMaterials psf2:psftype="Property">

      <psk3dx:MaterialPLA>
         <psk:DisplayName>PLA</psk:DisplayName>
         <psk3d:Job3DMaterialType>psk3d:PLA</psk3d:Job3DMaterialType>
         <psk3d:MaterialColor>#FFFFFFFF</psk3d:MaterialColor>

         <psk3dx:platformtemperature>0</psk3dx:platformtemperature>
         <psk3dx:filamentdiameter>1750</psk3dx:filamentdiameter>
         <psk3dx:filamentcalibrationoverride>1.0</psk3dx:filamentcalibrationoverride>
         <psk3dx:extrudertemperature>207</psk3dx:extrudertemperature>

         <psk3dx:SpeedFactor>1.0</psk3dx:SpeedFactor>

         <psk3dx:SetupCommands>
            <!-- Executed during pre-commands: nozzle pre-heating, priming, etc -->
            <psk3dx:command>M104 S207 T1</psk3dx:command>
            <psk3dx:command>M140 S50</psk3dx:command>
         </psk3dx:SetupCommands>

         <psk3dx:SelectCommands>
            <!-- Executed during printing: T0/T1 selection, nozzle wiping sequence,turn fan on/off/gradual, retract the material, temperature, etc-->
            <psk3dx:command>; PLA on</psk3dx:command>
            <psk3dx:command>M108 T1</psk3dx:command>
         </psk3dx:SelectCommands>

         <psk3dx:DeselectCommands>
            <!-- Executed during printing: retract the material, park the nozzle, reduce temperature, etc -->
            <psk3dx:command>; PLA off</psk3dx:command>
         </psk3dx:DeselectCommands>


      </psk3dx:MaterialPLA>
  </psk3d:Job3DMaterials>

  <psk3dx:customStatus>Slicing</psk3dx:customStatus>
  <psk3dx:userprompt>Confirm the 3D printer is calibrated and ready for the next print</psk3dx:userprompt>

   <!— Additional Slicer settings follow (optional) -->

</PrintDeviceCapabilities>

Para impressoras 3D que não têm exibição a bordo e botões para permitir que o usuário interaja com o dispositivo no início da impressão, defendemos o retorno de um XML PDC com uma mensagem de prompt de usuário adequada definida conforme mostrado acima em psdk3dx:userPrompt. Isso é para impedir o início de uma nova impressão sobre uma existente. A mensagem <de status personalizada psk3dx:customStatus> é usada para exibir qualquer mensagem durante a divisão.

HRESULT Cleanup(LPCWSTR pPrinterName, LPCWSTR pPortName, DWORD dwJobId, LPVOID* ppPartnerData)

  • dwJobId - id do trabalho usada para acompanhar o trabalho no spooler

  • pPortName - portname para a impressora 3D

  • pPrinterName - nome da impressora para a qual este trabalho de impressão está sendo enviado

  • ppPartnerData - ponteiro para o ponteiro que mantém a configuração de dados específica do trabalho durante uma invocação da API InitializePrint

A limpeza é invocada na conclusão bem-sucedida de um trabalho de impressão ou na conclusão de uma consulta de cancelamento em um trabalho de impressão. Ele oferece uma oportunidade para a DLL do parceiro limpar os recursos que foram inicializados para essa impressão.

HRESULT UnInstall([in]LPCWSTR args)

Essa API é chamada ao desinstalar o dispositivo de impressora 3D e fornece um mecanismo para o fabricante desinstalar o software que ele pode ter instalado.