Activer une interface USB personnalisée pour une imprimante 3D
L’architecture décrite dans cette rubrique permet de prendre en charge les imprimantes 3D avec interface USB personnalisée dans les écosystèmes de pilotes d’impression v3 et v4. Un moniteur de port standard, 3dmon.dll, transmet les commandes des travaux d’impression 3D à un service Windows 3DPrintService exécuté avec des informations d’identification de service local. Le service charge et communique avec une DLL partenaire pour exécuter les commandes personnalisées nécessaires à un travail d’impression 3D. La DLL partenaire, ainsi que les redistribuables 3dmon.dll et 3dprintservice.exe, sont installés par le package de pilotes USB de l’appareil. La DLL partenaire doit implémenter et exporter un ensemble de fonctions pour communiquer avec le 3DPrintService. Le reste des fonctionnalités requises pour interagir avec le service de spouleur d’impression est implémenté dans 3dmon.dll.
Remarque
Cette architecture exige que la DLL partenaire soit multi-instance et sûre pour les threads.
Décisions d’architecture
Le service Windows 3DPrintService est utilisé pour charger et invoquer des API spécifiques définies dans des DLL fournies par des partenaires pendant un flux de travail d’impression. Ces API permettent la communication avec l’imprimante.
Les packages de pilotes filtre USB KMDF sont publiés sur Windows Update pour installation via PnP pour une imprimante 3D prise en charge. Le pilote KMDF installe le logiciel partenaire et crée un nœud de périphérique imprimante 3D. Le nœud de périphérique imprimante 3D est installé à l’aide d’un pilote d’impression v4 publié par un partenaire à partir de Windows Update.
Décisions de packaging
Binaires et dépendances binaires
L’architecture utilise un pilote publié par le fabricant du matériel sur Windows Update. Ce pilote inclut les redistribuables fournis par Microsoft suivants ainsi que leurs dépendances :
3dmon.dll
3dprintservice.exe
ms3dprintusb.sys
Pilote filtre USB en mode noyau
Le pilote KMDF est publié par le partenaire et se compose des composants montrés dans le diagramme ci-dessous. Cela correspond à l’appareil avec un identifiant matériel (généralement un VID & PID). Le pilote crée un nœud de périphérique imprimante 3D lors de l’installation, ce qui déclenche l’installation de la file d’attente d’impression et des pilotes de slicer. Le partenaire fournit des pilotes d’imprimante v4 pour le nœud de périphérique imprimante 3D qui est créé.
MS3DPrintUSB.sys
Le pilote de périphérique en mode noyau qui crée le nœud de périphérique imprimante 3D sous Enum\3DPrint. Il est invoqué par le sous-système PnP via une correspondance directe du VID & PID basée sur le nœud de périphérique créé par Winusb.sys. Le fichier .inf du pilote configure la DLL personnalisée utilisée pour configurer le 3DPrintService (si elle n’est pas déjà installée sur le système).
3dmon.dll
3DMon.dll est un binaire redistribuable de moniteur de port publié par Microsoft, invoqué par le spouleur pour communiquer avec l’imprimante 3D.
3dprintservice.exe
3DPrintService.exe est un binaire publié par Microsoft, installé en tant que service Windows lors de l’installation du pilote. 3DMon communique avec ce service pour effectuer des opérations telles que l’impression, la bidirectionnelle, etc., avec l’imprimante 3D.
Partnerimpl.dll
Partnerimp.dll est l’implémentation par le partenaire de l’interface publiée par Microsoft. La DLL communique avec le périphérique partenaire en utilisant leurs protocoles. 3DPrintService.exe charge cette DLL lors de l’exécution pour piloter les opérations du périphérique imprimante 3D.
Séquence d’utilisation de l’imprimante
Le spouleur communique avec 3dmon.dll, qui envoie des commandes au service Windows 3DPrintService.
3DPrintService.exe s’exécute avec les informations d’identification du compte NetworkService.
Le spouleur, via 3dmon.dll, envoie des commandes à 3DPrintService chaque fois que l’imprimante 3D est utilisée.
3DPrintService traite les commandes et invoque des API à l’exécution sur les DLL d’implémentation fournies par le partenaire.
3DPrintService transmet les réponses des DLL fournies par le partenaire au spouleur.
Interfaces et interactions
La DLL partenaire doit exporter les fonctions d’API suivantes :
HRESULT Install([in] LPCWSTR args)
Cette API est facultative et peut être utilisée par le fabricant pour installer des logiciels personnalisés ou des enregistrements pour leur appareil. Par exemple, installation de la modélisation incluse dans le package de pilotes de l’appareil. Cette API est invoquée avec des informations d’identification SYSTEM pour permettre l’installation.
DWORD PrintApiSupported()
Cette API est utilisée par les fabricants tiers pour indiquer la version de l’API du service d’impression 3D prise en charge. Les API ci-dessous sont compatibles avec la version 1 du 3DPrintService.
HRESULT InitializePrint(LPCWSTR pPrinterName, LPCWSTR pPortName, DWORD dwJobId, LPVOID* ppPartnerData)
Cette API est invoquée avant qu’un événement d’impression ne commence pour initialiser l’imprimante. L’imprimante peut enregistrer l’état spécifique du travail dans le paramètre ppPartnerData. Cet appel est analogue à une invocation StartDocPort.
jobId : id de travail utilisé pour suivre le travail
portName : nom du port pour l’imprimante 3D
printerName : nom de l’imprimante à laquelle ce travail d’impression est envoyé
ppPartnerData : pointeur vers un pointeur qui peut être utilisé pour stocker des données spécifiques au travail
HRESULT PrintFile([in] DWORD jobId, [in] LPWSTR portName, [in] LPWSTR printerName, [in] LPWSTR pathToRenderedFile, [in] LPVOID* ppPartnerData)
Cette API est utilisée par des fabricants tiers pour imprimer le document sur leur imprimante.
jobId : id de travail utilisé pour suivre le travail
portName : nom du port pour l’imprimante 3D
printerName : nom de l’imprimante à laquelle le travail d’impression est envoyé
pathToRenderedFile : chemin UNC vers l’emplacement du fichier mis en file d’attente après le rendu. Le fabricant tiers traite le fichier à partir de cet emplacement et imprime le document sur son appareil.
ppPartnerData : pointeur vers un pointeur utilisé pour stocker les données spécifiques au partenaire configurées lors de l’appel API InitializePrint.
printerName peut être obtenu à partir du registre en utilisant le nom du port. Les fabricants tiers peuvent ne pas être en mesure d’utiliser le nom du port pour communiquer avec leur appareil. Le nom de l’imprimante est unique sur une machine Windows et leur logiciel sera capable d’identifier quelle imprimante imprimer le travail. Toutes les imprimantes actives sur une machine peuvent être trouvées à la clé de registre suivante :
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Printers
HRESULT Query(_In_ LPCWSTR command, _In_ LPCWSTR commandData, _Out_ LPWSTR resultBuffer, _Out_ resultBufferSize, , _In_ LPVOID* ppPartnerData)
command : commande sous forme de chaîne envoyée en tant que requête
commandData : arguments de commande (facultatif)
resultBuffer : résultat de l’invocation des arguments de requête>
resultBufferSize : taille de la chaîne du tampon de résultat
ppPartnerData : pointeur vers un pointeur pour l’instance actuelle de la DLL partenaire
Le service d’impression 3D invoque la DLL partenaire pour obtenir la taille du tampon à allouer pour la commande.
Après avoir alloué de la mémoire pour contenir la chaîne de réponse, la DLL sera de nouveau invoquée pour obtenir le résultat réel.
La DLL peut utiliser les données d’instance d’un appel précédent InitializePrint() pour communiquer avec l’appareil sans ouvrir un nouveau canal de communication à chaque appel de fonction Query().
Cette API est utilisée pour communiquer avec l’imprimante afin d’obtenir des informations sur la configuration de l’appareil, la progression de l’impression, ou pour notifier la DLL partenaire des événements de débranchement de l’appareil.
Les commandes ci-dessous doivent être prises en charge par le fabricant :
Commande | CommandData | Sortie | Commentaires |
---|---|---|---|
\\Printer.3DPrint:JobStatus | Travail commencé = {"Statut" : "ok"}, Statut à utiliser à la fin {"Statut" : "Terminé"} | Le spouleur affichera toute valeur retournée dans l’interface utilisateur de la file d’attente d’impression. Cela permet à l’appareil d’afficher des informations pertinentes pendant une impression sur l’interface utilisateur de la file d’attente d’impression. L’appareil peut retourner une chaîne arbitraire ici (par exemple « Occupé » ou « 33% terminé ») et cela sera affiché tel quel dans le statut du travail de la file d’attente d’impression. | |
\\Printer.3DPrint:JobCancel | {"Statut" : "Terminé"} | Le spouleur invoquera cette commande lorsqu’un utilisateur annule une impression. La DLL partenaire retourne cette valeur lorsque l’annulation a réussi et que les handles et threads ont été fermés. | |
\\Printer.Capabilities:Data | Chaîne XML conforme au schéma PrintDeviceCapabilites (PDC). | La requête PDC est invoquée par des applications qui souhaitent obtenir plus d’informations sur l’imprimante. Les données sont utilisées pour décrire les capacités de l’appareil et peuvent inclure les paramètres du slicer si le pilote repose sur le slicer de Microsoft. Voir ci-dessous un exemple de PDC. | |
\\Printer.3DPrint:Disconnect | {"Statut" : "OK"} | Cette requête est déclenchée chaque fois qu’il y a une déconnexion PnP du périphérique imprimante. Les partenaires peuvent entreprendre les actions requises, par exemple fermer tous les handles ouverts pour permettre une reconnexion correcte. | |
\\Printer.3DPrint:Connect | {"Statut" : "OK"} | Cette requête est déclenchée chaque fois qu’il y a une connexion PnP du périphérique imprimante. Les partenaires peuvent entreprendre les actions nécessaires. |
Capacités de l’appareil d’impression XML
Le fichier XML des capacités de l’appareil d’impression suivant peut être utilisé comme exemple :
<?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>
Pour les imprimantes 3D qui n’ont pas d’écran ou de boutons permettant à l’utilisateur d’interagir avec l’appareil au début de l’impression, nous préconisons de retourner un fichier XML PDC avec un message d’invite utilisateur approprié comme indiqué ci-dessus dans psdk3dx:userPrompt. Cela permet d’éviter de lancer une nouvelle impression par-dessus une impression existante. Le message d’état personnalisé <psk3dx:customStatus> est utilisé pour afficher tout message pendant le slicing.
HRESULT Cleanup(LPCWSTR pPrinterName, LPCWSTR pPortName, DWORD dwJobId, LPVOID* ppPartnerData)
dwJobId : id de travail utilisé pour suivre le travail dans le spouleur
pPortName : nom du port pour l’imprimante 3D
pPrinterName : nom de l’imprimante à laquelle ce travail d’impression est envoyé
ppPartnerData : pointeur vers un pointeur qui contient les données spécifiques au travail configurées lors de l’appel de l’API InitializePrint
Cleanup est invoqué lors de la réussite d’un travail d’impression, ou lors de la complétion d’une requête d’annulation d’un travail d’impression. Il fournit l’occasion à la DLL partenaire de libérer les ressources qui ont été initialisées pour cette impression.
HRESULT UnInstall([in]LPCWSTR args)
Cette API est appelée lors de la désinstallation du périphérique imprimante 3D et fournit un mécanisme au fabricant pour désinstaller les logiciels qu’il pourrait avoir installés.