Compare commits

...

19 Commits

Author SHA1 Message Date
0f53a99e56
feat: add integration tests with snapshot for some CPS cards in kits 2024-10-09 22:51:51 +02:00
c37b7f241d
feat: implement group2, CPS situation for SSV_LireCartePS 2024-10-09 22:51:51 +02:00
91d574e31e
feat: Une enums for deserializable fields in CPS Holder group (01) 2024-10-09 22:51:50 +02:00
f186fb20ce
feat: Take the size into account for Block reading, to handle missing fields 2024-10-09 22:51:50 +02:00
a53360d114
feat: use an enum instead of raw ID for CPS type 2024-10-09 22:51:50 +02:00
213f94c6e7
feat: raw (non-deserialized) implementation of the 01 group of LireCartePS 2024-10-09 22:51:50 +02:00
8f935ab81e
feat: implement a full SSV_LireConfig output parsing, using deku for a declarative bytes parsing
Co-authored-by: theo <t.lettermann@criteo.com>
2024-10-09 22:50:38 +02:00
c83824ae34 Merge pull request 'Initialisation de la crate FSV, couche haut-niveau des accès aux fonctions SSV' (#71) from 38-fsv-high-level-lib into main
### Détails

- Création de la crate fsv, couche de haut niveau pour l'usage des librairies FSV
- Implémentation partielle des appels "haut niveau" aux fonctions SSV_InitLIB2, SSV_LireCartePS et SSV_LireConfig
- Implémentation de la gestion des erreurs numériques de la librairie C pour ces fonctions

### Pourquoi ?

L'usage est de séparer les couches bas niveau, exposant des versions légèrement "rustifiées" des appels aux fonctions des librairies C, des couches "haut niveau", garantissant un usage "safe" et "user friendly".

Contribue à #38
Closes #49

Reviewed-on: #71
Reviewed-by: kosssi <simon@p4pillon.org>
2024-10-09 22:46:41 +02:00
1b94fefad3
fixup! feat: implémentation partielle de la fonction get_config et de ses erreurs 2024-10-09 22:45:01 +02:00
5f7229c307
fixup! feat: Implémentation de la gestion des erreurs numériques de la librairie C pour la fonction InitLIB2 2024-10-09 22:43:25 +02:00
d043915a29
feat: implémentation partielle de la fonction get_config et de ses erreurs 2024-10-09 22:38:53 +02:00
2260b0cfa8
feat: implement LireCartePS with hardcoded reader and all errors 2024-10-09 22:38:53 +02:00
203521fe01
feat: Implémentation de la gestion des erreurs numériques de la librairie C pour la fonction InitLIB2
Co-authored-by: theo <t.lettermann@criteo.com>
2024-10-09 22:38:53 +02:00
3c1e691cb8
feat: Création de la crate fsv, couche de haut niveau pour l'usage des librairies FSV 2024-10-09 22:38:53 +02:00
add40f32c5 Merge pull request 'Création d'une sys-crate pour la gestion des librairies FSV' (#70) from feat/38-fsv-sys-crate into main
### Détails

Début d'implémentation de bindings pour FSV SESAM-Vitale

- Création de la crates/fsv-sys
- Ajout des headers des versions FSV 1.40.14 et 1.40.13 dans un sous-dossier crates/fsv-sys/vendor
- Génération des bindings depuis ces headers avec bindgen
- Implémentation d'une structure de loading de la librairie au runtime
    - Un pattern similaire au "TypeState pattern" est utilisé pour gérer plusieurs versions possibles des bindings FSV
    - Une macro permet de générer avec un peu moins de boilerplate que nécessaire la couche d'accès aux fonctions de la librairie

### Pourquoi ?

Cette PR est une étape importante du ticket #38

Une telle sys-crate, respectant (à peu près) les bonnes pratiques d'une telle implem, permet :
- Pouvoir être diffusée publiquement en tant que telle, pour faciliter le travail à des copaines
- De concentrer le travail très spécifique et bas niveau de gestion des librairies et des bindings dans une crate dédiée
- De ne pas "forcer" une approche "orientée" sur l'API plus haut niveau qu'on décide de brancher sur ces bindings
    - En effet, l'implem haut niveau fait des choix non neutres, comme le choix de certains types, la technique de gestion des erreurs, etc.

### Documentation

# Aide reçue sur les forums Rust
- [Génération des bindings avec Bindgen](https://users.rust-lang.org/t/how-to-handle-bindgen-generating-types-aliases-instead-of-callable-functions/118083)
- [Gestion des versions multiples avec la structure de loading de la librairie](https://users.rust-lang.org/t/manage-various-versions-of-a-c-library-loaded-at-runtime/118973)

# Documentations
- [Making a sys-crate](https://kornel.ski/rust-sys-crate)
- [LibLoading](https://docs.rs/libloading/latest/libloading/)
- [Bindgen](https://rust-lang.github.io/rust-bindgen/)

Reviewed-on: #70
Reviewed-by: kosssi <simon@p4pillon.org>
2024-10-09 22:37:36 +02:00
d8b8ce9a77
feat: improve the fsv-sys README, and add a PROGESS.md for implementation tracking 2024-10-09 22:31:26 +02:00
9997ee43f8
feat: Gestion des versions multiples de FSV dans le wrapper exposant les fonctions de la librairie 2024-10-09 22:31:26 +02:00
4ab8a1de81
feat: handle multi-version bindings generation 2024-10-09 22:31:26 +02:00
d13f36c5e2
feat: Première implémentation de bindings pour FSV SESAM-Vitale
- Création de la crates/fsv-sys
- Ajout des headers de la FSV 1.40.14.13 dans crates/fsv-sys/vendor
- Génération des bindings depuis ces headers avec bindgen
- Implémentation d'une structure de loading de la librairie au runtime
- Implémentation d'une macro permettant de générer facilement la couche d'accès aux fonctions de la librairie
2024-10-09 22:31:26 +02:00
42 changed files with 5315 additions and 15 deletions

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
Cargo.lock -merge linguist-generated=false

View File

@ -621,6 +621,26 @@ dependencies = [
"num-traits",
]
[[package]]
name = "bindgen"
version = "0.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f"
dependencies = [
"bitflags 2.6.0",
"cexpr",
"clang-sys",
"itertools",
"log",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn 2.0.77",
]
[[package]]
name = "bitflags"
version = "1.3.2"
@ -702,7 +722,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf4918709cc4dd777ad2b6303ed03cb37f3ca0ccede8c1b0d28ac6db8f4710e0"
dependencies = [
"once_cell",
"proc-macro-crate 2.0.2",
"proc-macro-crate 2.0.0",
"proc-macro2",
"quote",
"syn 2.0.77",
@ -901,6 +921,15 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom 7.1.3",
]
[[package]]
name = "cfb"
version = "0.7.3"
@ -961,6 +990,17 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "clang-sys"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
dependencies = [
"glob",
"libc",
"libloading 0.8.5",
]
[[package]]
name = "clap"
version = "2.34.0"
@ -1344,6 +1384,32 @@ dependencies = [
"syn 2.0.77",
]
[[package]]
name = "deku"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9711031e209dc1306d66985363b4397d4c7b911597580340b93c9729b55f6eb"
dependencies = [
"bitvec",
"deku_derive",
"log",
"no_std_io2",
"rustversion",
]
[[package]]
name = "deku_derive"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58cb0719583cbe4e81fb40434ace2f0d22ccc3e39a74bb3796c22b451b4f139d"
dependencies = [
"darling 0.20.10",
"proc-macro-crate 3.2.0",
"proc-macro2",
"quote",
"syn 2.0.77",
]
[[package]]
name = "der"
version = "0.7.9"
@ -1707,6 +1773,29 @@ dependencies = [
"syn 2.0.77",
]
[[package]]
name = "env_filter"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab"
dependencies = [
"log",
"regex",
]
[[package]]
name = "env_logger"
version = "0.11.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d"
dependencies = [
"anstream",
"anstyle",
"env_filter",
"humantime",
"log",
]
[[package]]
name = "equivalent"
version = "1.0.1"
@ -1923,6 +2012,33 @@ dependencies = [
"libc",
]
[[package]]
name = "fsv"
version = "0.1.0"
dependencies = [
"anyhow",
"deku",
"env_logger",
"fsv-sys",
"insta",
"libc",
"log",
"num_enum",
"serde",
"thiserror",
"utils",
]
[[package]]
name = "fsv-sys"
version = "0.1.0"
dependencies = [
"bindgen",
"libc",
"libloading 0.8.5",
"thiserror",
]
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
@ -2303,7 +2419,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc"
dependencies = [
"heck 0.4.1",
"proc-macro-crate 2.0.2",
"proc-macro-crate 2.0.0",
"proc-macro-error",
"proc-macro2",
"quote",
@ -2571,6 +2687,12 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "hyper"
version = "1.4.1"
@ -2722,6 +2844,18 @@ dependencies = [
"libc",
]
[[package]]
name = "insta"
version = "1.40.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6593a41c7a73841868772495db7dc1e8ecab43bb5c0b6da2059246c4b506ab60"
dependencies = [
"console",
"lazy_static",
"linked-hash-map",
"similar",
]
[[package]]
name = "instant"
version = "0.1.13"
@ -2782,6 +2916,15 @@ version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "0.4.8"
@ -2949,15 +3092,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf"
dependencies = [
"gtk-sys",
"libloading",
"libloading 0.7.4",
"once_cell",
]
[[package]]
name = "libc"
version = "0.2.158"
version = "0.2.159"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
[[package]]
name = "libloading"
@ -2969,6 +3112,16 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "libloading"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
dependencies = [
"cfg-if 1.0.0",
"windows-targets 0.52.6",
]
[[package]]
name = "libm"
version = "0.2.8"
@ -2997,6 +3150,12 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "linked-hash-map"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]]
name = "linux-raw-sys"
version = "0.3.8"
@ -3386,6 +3545,15 @@ dependencies = [
"memoffset 0.9.1",
]
[[package]]
name = "no_std_io2"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f038b95e66372ec5f4adabd615fc9a46a1fe42bcfe549863921c0e44667b605"
dependencies = [
"memchr",
]
[[package]]
name = "nodrop"
version = "0.1.14"
@ -3531,7 +3699,7 @@ version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56"
dependencies = [
"proc-macro-crate 2.0.2",
"proc-macro-crate 3.2.0",
"proc-macro2",
"quote",
"syn 2.0.77",
@ -4183,6 +4351,16 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]]
name = "prettyplease"
version = "0.2.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba"
dependencies = [
"proc-macro2",
"syn 2.0.77",
]
[[package]]
name = "proc-macro-crate"
version = "1.3.1"
@ -4195,14 +4373,22 @@ dependencies = [
[[package]]
name = "proc-macro-crate"
version = "2.0.2"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24"
checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8"
dependencies = [
"toml_datetime",
"toml_edit 0.20.2",
]
[[package]]
name = "proc-macro-crate"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b"
dependencies = [
"toml_edit 0.22.22",
]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
@ -4578,6 +4764,12 @@ version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustc_version"
version = "0.4.1"
@ -5211,6 +5403,12 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
[[package]]
name = "similar"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e"
[[package]]
name = "siphasher"
version = "0.3.11"
@ -6280,9 +6478,9 @@ dependencies = [
[[package]]
name = "toml_datetime"
version = "0.6.3"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
dependencies = [
"serde",
]
@ -6297,7 +6495,7 @@ dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"winnow",
"winnow 0.5.40",
]
[[package]]
@ -6310,7 +6508,18 @@ dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"winnow",
"winnow 0.5.40",
]
[[package]]
name = "toml_edit"
version = "0.22.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
dependencies = [
"indexmap 2.5.0",
"toml_datetime",
"winnow 0.6.20",
]
[[package]]
@ -7388,6 +7597,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "winnow"
version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
dependencies = [
"memchr",
]
[[package]]
name = "winreg"
version = "0.52.0"

View File

@ -4,6 +4,8 @@ members = [
"crates/backend",
"crates/desktop",
"crates/sesam-vitale",
"crates/fsv",
"crates/fsv-sys",
"crates/utils",
"migration",
"entity",

View File

@ -9,6 +9,7 @@ Logiciel de Pharmacie libre et open-source.
- `crates/desktop`: Client desktop propulsé par Tauri, exposant le `frontend`
- `crates/sesam-vitale`: Bibliothèque de gestion des services SESAM-Vitale (Lecture des cartes CPS et Vitale, téléservices ...)
- `crates/utils`: Bibliothèque de fonctions utilitaires
- `crates/fsv-sys`: Bindings Rust pour les librairies dynamiques FSV (SESAM-Vitale)
- `frontend`: Interface web du logiciel, propulsée par Nuxt.js
## Installation
@ -61,9 +62,9 @@ Toutefois, l'usage de la CLI de SeaORM nécessite de renseigner les informations
> Astuce : utilisé un lien symbolique pour éviter de dupliquer le fichier `.env`.
#### SESAM-Vitale
#### FSV-sys
La crate `sesam-vitale` nécessite la présence des librairies dynamiques fournies par le package FSV et la CryptolibCPS. Les instructions d'installation sont disponibles dans le [README](crates/sesam-vitale/README.md) de la crate `sesam-vitale`.
La crate `fsv-sys` nécessite la présence des librairies fournies par le package FSV et la CryptolibCPS. Les instructions d'installation sont disponibles dans le [README](crates/sesam-vitale/README.md) de la crate `fsv-sys`.
#### Backend Hot-reload
@ -90,6 +91,20 @@ cargo tauri dev --no-watch
> - le `backend` n'est rechargé que si des modifications sont détectées dans le dossier précisé par `-w crates/backend`
> - le rechargement du `desktop` est désactivé par l'option `--no-watch` ; en effet, le rechargement du `frontend` est déjà pris en charge par `bun` et ne nécessite pas de rechargement du `desktop`
## Tests
Les tests unitaires et d'intégration utilisants des cartes CPS ou Vitale réelles sont désactivés par défaut et doivent être
[explicitement activés](https://doc.rust-lang.org/book/ch11-02-running-tests.html#ignoring-some-tests-unless-specifically-requested) pour s'exécuter.
### Snapshots
Pour certains modules, des tests d'intégration s'appuient sur la crate [`insta`](https://insta.rs) pour générer et comparer des snapshots.
Pour faciliter la gestion de ces tests, il est recommandé d'installer `cargo-insta` :
```bash
cargo install cargo-insta
```
## Build
Pour packager le client `desktop`, il est nécessaire de faire appel à la CLI Tauri, qui se charge de gérer le build du `frontend` et son intégration au bundle :

18
crates/fsv-sys/Cargo.toml Normal file
View File

@ -0,0 +1,18 @@
[package]
name = "fsv-sys"
version = "0.1.0"
edition = "2021"
links = "ssvlux64,ssvosx,Ssvw64"
# Linux: Libssvlux64.so
# Windows: Ssvw64.dll
# macOS: ssvosx.framework
[dependencies]
libc = "0.2.159"
libloading = "0.8.5"
thiserror.workspace = true
[build-dependencies]
bindgen = "0.70.1"

View File

@ -0,0 +1,32 @@
# État d'avancement de l'implémentation des bindings FSV
| Module | Progression |
|-------------|------------------------------------|
| [SSV](#ssv) | ![](https://geps.dev/progress/5) |
| [SGD](#sgd) | ![](https://geps.dev/progress/0) |
| [SRT](#srt) | ![](https://geps.dev/progress/0) |
| [STS](#sts) | ![](https://geps.dev/progress/0) |
## SSV
| Fonctions implémentées |
|------------------------|
| SSV_InitLIB2 |
| SSV_LireConfig |
| SSV_LireCartePS |
## SGD
| Fonctions implémentées |
|------------------------|
## SRT
| Fonctions implémentées |
|------------------------|
## STS
| Fonctions implémentées |
|------------------------|

36
crates/fsv-sys/README.md Normal file
View File

@ -0,0 +1,36 @@
# FSV-sys, bindings Rust pour le package FSV SESAM-Vitale
## Librairies FSV
### Versions supportées
| Version FSV |
|-------------|
| 1.40.14 |
| 1.40.13 |
### État d'avancement de l'implémentation des bindings FSV
Les détails de l'avancement de l'implémentation des bindings FSV sont donnés dans le fichier [PROGRESS.md](PROGRESS.md)
## Utilisation
### Pré-requis
- Installer le [package FSV](https://industriels.sesam-vitale.fr/group/fournitures-sesam-vitale)
- Les librairies dynamiques (.lib, .dll, ...) fournies ne sont pas installés dans les emplacements standard du système, il faudra donc configurer leur chemin d'installation dans le fichier de configuration `.env.build` (voir ci-dessous)
- Le détail des chemins d'installation est donné dans la documentation du package FSV `fsv-mi-004_pack-FSV1.40.14_V2.3.pdf`
- Linux - par défaut : `/opt/santesocial/fsv/1.40.13/lib`
- Windows - par défaut : `C:\Program Files\santesocial\santesocial\fsv\1.40.14\lib` (ou dans Program Files (x86) si c'est le package 32bits qui a été installé)
- Installer la [CryptolibCPS](https://industriels.sesam-vitale.fr/group/galss-cryptolib-cps)
- Ce package fourni également l'utilitaire "CPS Gestion" pour obtenir des informations sur le lecteur de carte, etc.
- Linux : `cpgeslux`
- Windows : `...`
## Développement
### Pré-requis
- Pour la génération des bindings lors de la phase de `build` à l'aide de `bindgen`, il est nécessaire d'avoir installé `clang` ([documentation](https://rust-lang.github.io/rust-bindgen/requirements.html)).

View File

@ -0,0 +1,7 @@
#ifndef WRAPPER_LINUX_H
#define WRAPPER_LINUX_H
#include "../../vendor/fsv/1.40.14.13/includes/SYS_DEF/linux/mc_sys_def.h"
#include "../../vendor/fsv/1.40.14.13/includes/SSV/pourFSV1.40.13/ssv.h"
#endif // WRAPPER_LINUX_H

View File

@ -0,0 +1,7 @@
#ifndef WRAPPER_MACOSX_H
#define WRAPPER_MACOSX_H
#include "../../vendor/fsv/1.40.14.13/includes/SYS_DEF/macosx/mc_sys_def.h"
#include "../../vendor/fsv/1.40.14.13/includes/SSV/pourFSV1.40.13/ssv.h"
#endif // WRAPPER_MACOSX_H

View File

@ -0,0 +1,7 @@
#ifndef WRAPPER_WIN_H
#define WRAPPER_WIN_H
#include "../../vendor/fsv/1.40.14.13/includes/SYS_DEF/win/mc_sys_def.h"
#include "../../vendor/fsv/1.40.14.13/includes/SSV/pourFSV1.40.13/ssv.h"
#endif // WRAPPER_WIN_H

View File

@ -0,0 +1,7 @@
#ifndef WRAPPER_LINUX_H
#define WRAPPER_LINUX_H
#include "../../vendor/fsv/1.40.14.13/includes/SYS_DEF/linux/mc_sys_def.h"
#include "../../vendor/fsv/1.40.14.13/includes/SSV/pourFSV1.40.14/ssv.h"
#endif // WRAPPER_LINUX_H

View File

@ -0,0 +1,7 @@
#ifndef WRAPPER_MACOSX_H
#define WRAPPER_MACOSX_H
#include "../../vendor/fsv/1.40.14.13/includes/SYS_DEF/macosx/mc_sys_def.h"
#include "../../vendor/fsv/1.40.14.13/includes/SSV/pourFSV1.40.14/ssv.h"
#endif // WRAPPER_MACOSX_H

View File

@ -0,0 +1,7 @@
#ifndef WRAPPER_WIN_H
#define WRAPPER_WIN_H
#include "../../vendor/fsv/1.40.14.13/includes/SYS_DEF/win/mc_sys_def.h"
#include "../../vendor/fsv/1.40.14.13/includes/SSV/pourFSV1.40.14/ssv.h"
#endif // WRAPPER_WIN_H

57
crates/fsv-sys/build.rs Normal file
View File

@ -0,0 +1,57 @@
use std::{env, path::PathBuf};
// Supported versions of FSV
static SUPPORTED_FSV_VERSIONS: [&str; 2] = ["1.40.14", "1.40.13"];
fn build_bindings(version: &str, target_code: &str) -> PathBuf {
let target = env::var("TARGET").expect("TARGET not set");
let wrapper_path = format!("bindgen-wrappers/{}/wrapper.{}.h", version, target_code);
let bindings = bindgen::Builder::default()
// The input header we would like to generate
// bindings for.
.header(wrapper_path)
// To generate the bindings for specific target
.clang_arg(format!("--target={}", target))
// Limit the bindings generation to the SSV_ prefix
.allowlist_item("SSV_.*")
// Tell cargo to invalidate the built crate whenever any of the
// included header files changed.
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
// Finish the builder and generate the bindings.
.generate()
// Unwrap the Result and panic on failure.
.expect("Unable to generate bindings");
// Write the bindings to the $OUT_DIR/bindings.rs file.
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let out_file = format!("bindings_{}.rs", version);
let out_path = out_dir.join(out_file);
bindings
.write_to_file(&out_path)
.expect("Couldn't write bindings! ");
out_path
}
fn get_target_code() -> String {
// Use CARGO configuration env Variable, because !cfg(target_os) is not available in build.rs
// Source: https://kazlauskas.me/entries/writing-proper-buildrs-scripts
let target_os = env::var("CARGO_CFG_TARGET_OS");
match target_os.as_ref().map(|x| &**x) {
Ok("linux") => "linux", // lib_name = "ssvlux64";
Ok("windows") => "win", // lib_name = "Ssvw64";
Ok("macos") => "macosx", // lib_name = "ssvosx";
tos => panic!("Unsupported target_os {:?}", tos),
}
.to_string()
}
fn main() {
let target_code = get_target_code();
// Build the bindings for each supported version of FSV
let bindings_paths: Vec<PathBuf> = SUPPORTED_FSV_VERSIONS
.iter()
.map(|version| build_bindings(version, &target_code))
.collect();
println!("FSV bindings generated: {:#?}", bindings_paths);
}

View File

@ -0,0 +1,12 @@
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(unused)]
pub mod BINDINGS_V1_40_14 {
include!(concat!(env!("OUT_DIR"), "/bindings_1.40.14.rs"));
}
pub mod BINDINGS_V1_40_13 {
include!(concat!(env!("OUT_DIR"), "/bindings_1.40.13.rs"));
}

212
crates/fsv-sys/src/lib.rs Normal file
View File

@ -0,0 +1,212 @@
#![allow(non_snake_case)]
use std::marker::PhantomData;
mod bindings;
use bindings::*;
#[derive(Debug, Clone)]
pub enum SupportedFsvVersion {
V1_40_14, // 1.40.14
V1_40_13, // 1.40.13
}
impl SupportedFsvVersion {
fn as_str(&self) -> &'static str {
match self {
Self::V1_40_14 => "1.40.14",
Self::V1_40_13 => "1.40.13",
}
}
}
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error(transparent)]
LibLoading(#[from] libloading::Error),
#[error("Symbol missing: {0}")]
SymbolMissing(&'static str),
}
/// Macro to generate a function that implements a call to an external function in BINDINGS
macro_rules! ssv_function {
($binding:ty, $func_name:ident, {$($arg_name:ident: $arg_type:ty),*}) => {
/// # Safety
/// This function is unsafe because it calls an external function through FFI.
/// The caller must ensure that the provided arguments are valid and that the
/// external function is safe to call.
pub unsafe fn $func_name(&self, $($arg_name: $arg_type),*) -> Result<u16, Error> {
let symbol_name = match stringify!($binding)
.split(&[' ', ':'])
.last() {
Some(name) => name,
None => return Err(Error::SymbolMissing(stringify!($binding))),
};
let func_struct: libloading::Symbol<'_, $binding> =
unsafe { self.library.get(symbol_name.as_bytes())? };
let func = match *func_struct {
Some(func) => func,
None => return Err(Error::SymbolMissing(stringify!($binding))),
};
Ok(func($($arg_name),*))
}
};
}
/// `sealed::Sealed` trait is used to prevent external crates from implementing the LibVersion trait.
mod sealed { pub trait Sealed {}}
/// Wrapper around the SESAM-VITALE library
/// This struct is responsible for loading the library and providing an interface to call its functions.
/// The library is loaded at creation and kept in memory until the struct is dropped.
pub trait SSVLibraryCommon {
fn new(path: &str) -> Result<Self, Error> where Self: Sized;
}
pub trait SSVLibraryVersion: sealed::Sealed {}
pub struct V1_40_13 {}
impl sealed::Sealed for V1_40_13 {}
impl SSVLibraryVersion for V1_40_13 {}
pub struct V1_40_14 {}
impl sealed::Sealed for V1_40_14 {}
impl SSVLibraryVersion for V1_40_14 {}
pub struct SSVLibrary<Version: SSVLibraryVersion> {
_version: PhantomData<Version>,
library: libloading::Library,
}
impl<Version: SSVLibraryVersion> SSVLibraryCommon for SSVLibrary<Version> {
fn new(path: &str) -> Result<Self, Error> {
let library = unsafe { libloading::Library::new(path)?};
Ok(Self {
_version: PhantomData,
library
})
}
}
impl SSVLibrary<V1_40_14> {
pub fn library(&self) -> &libloading::Library {
&self.library
}
ssv_function!(BINDINGS_V1_40_14::SSV_InitLIB2, ssv_init_lib2, {
pcFichierSesam: *const i8
});
ssv_function!(BINDINGS_V1_40_14::SSV_LireConfig, ssv_lire_config, {
pZDataOut: *mut *mut libc::c_void,
psTailleDataOut: *mut usize
});
ssv_function!(BINDINGS_V1_40_14::SSV_LireCartePS, ssv_lire_carte_ps, {
NomRessourcePS: *const i8,
NomRessourceLecteur: *const i8,
CodePorteurPS: *const i8,
pZDataOut: *mut *mut libc::c_void,
pTailleZone: *mut usize
});
}
impl SSVLibrary<V1_40_13> {
ssv_function!(BINDINGS_V1_40_13::SSV_InitLIB2, ssv_init_lib2, {
pcFichierSesam: *const i8
});
ssv_function!(BINDINGS_V1_40_13::SSV_LireConfig, ssv_lire_config, {
pZDataOut: *mut *mut libc::c_void,
psTailleDataOut: *mut usize
});
ssv_function!(BINDINGS_V1_40_13::SSV_LireCartePS, ssv_lire_carte_ps, {
NomRessourcePS: *const i8,
NomRessourceLecteur: *const i8,
CodePorteurPS: *const i8,
pZDataOut: *mut *mut libc::c_void,
pTailleZone: *mut usize
});
}
pub fn get_library_path(version: &SupportedFsvVersion) -> String {
let root_path = get_library_root_path();
let library_name = get_library_name();
let version = version.as_str();
format!("{root_path}/{version}/lib/{library_name}")
}
pub fn sesam_ini_path(version: &SupportedFsvVersion) -> String {
let root_path = get_sesam_ini_root_path();
let version = version.as_str();
format!("{root_path}/{version}/conf/sesam.ini")
}
fn get_library_name() -> &'static str {
// TODO : Use libloading::library_filename to get platform-specific filename ?
"libssvlux64.so"
}
fn get_library_root_path() -> &'static str {
"/opt/santesocial/fsv"
}
fn get_sesam_ini_root_path() -> &'static str {
"/etc/opt/santesocial/fsv"
}
#[cfg(test)]
mod test {
use std::{ffi::CString, ptr};
use super::*;
#[test]
fn test_initlib2() {
let lib_path = &get_library_path(&SupportedFsvVersion::V1_40_13);
let ssv_library = SSVLibrary::<V1_40_13>::new(lib_path).expect("SSVLibrary::new failed");
let sesam_ini_str =
CString::new(sesam_ini_path(&SupportedFsvVersion::V1_40_13)).expect("CString::new failed");
let result = unsafe { ssv_library.ssv_init_lib2(sesam_ini_str.as_ptr()) }.unwrap();
assert_eq!(result, 0);
}
#[test]
fn test_lire_config_and_carte_ps() {
let lib_path = &get_library_path(&SupportedFsvVersion::V1_40_13);
let ssv_library = SSVLibrary::<V1_40_13>::new(lib_path).expect("SSVLibrary::new failed");
let sesam_ini_str =
CString::new(sesam_ini_path(&SupportedFsvVersion::V1_40_13)).expect("CString::new failed");
let result = unsafe { ssv_library.ssv_init_lib2(sesam_ini_str.as_ptr()) }.unwrap();
assert_eq!(result, 0);
let mut buffer_ptr: *mut libc::c_void = ptr::null_mut();
let mut size: libc::size_t = 0;
let result = unsafe { ssv_library.ssv_lire_config(&mut buffer_ptr, &mut size) }.unwrap();
assert_eq!(result, 0);
unsafe { libc::free(buffer_ptr) };
let nom_ressource_ps =
CString::new("Gemalto PC Twin Reader (645D94C3) 00 00").expect("CString::new failed");
let nom_ressource_lecteur =
CString::new("Gemalto PC Twin Reader (645D94C3) 00 00").expect("CString::new failed");
let code_porteur_ps = CString::new("1234").expect("CString::new failed");
let mut buffer_ptr: *mut libc::c_void = ptr::null_mut();
let mut size: libc::size_t = 0;
let result = unsafe {
ssv_library.ssv_lire_carte_ps(
nom_ressource_ps.as_ptr(),
nom_ressource_lecteur.as_ptr(),
code_porteur_ps.as_ptr(),
&mut buffer_ptr,
&mut size,
)
}
.unwrap();
assert_eq!(result, 0);
unsafe { libc::free(buffer_ptr) };
}
}

View File

@ -0,0 +1,123 @@
/*
* -------------------------------------------------------------------
* (c) 2001 GIE SESAM-VITALE
*
* PROJET : Services de Gestion de Donnees
*
* FICHIER : sgd.h (v4)
*
* Declaration des prototypes des fonctions SGD pour les progiciels.
* -------------------------------------------------------------------
*/
#ifndef __SGD_H__
#define __SGD_H__
#ifdef __cplusplus
extern "C" {
#endif
/*
* Inclusions
*/
#include <stddef.h>
#include "mc_sys_def.h"
/* Reservation d'un session d'echange. */
extern unsigned short API_ENTRY SGD_ReserverSession (size_t Taille, unsigned short* NumeroSession);
/* Redimensionnement d'une zone d'entree interne. */
extern unsigned short API_ENTRY
SGD_RedimensionnerBuffer (unsigned short NumeroSession,
size_t NouvelleTaille);
/* Liberation d'une session d'echange. */
extern unsigned short API_ENTRY
SGD_LibererSession (unsigned short NumeroSession);
/* Ajout d'un groupe. */
extern unsigned short API_ENTRY
SGD_AjouterGroupe (unsigned short NumeroSession,
unsigned short IdGroupe);
/* Ajout d'un champ. */
extern unsigned short API_ENTRY
SGD_AjouterChamp (unsigned short NumeroSession,
const char* ValeurChamp);
/* Ajout d'un champ d'octets. */
extern unsigned short API_ENTRY
SGD_AjouterChampBin (unsigned short NumeroSession,
const char* ValeurChamp,
size_t TailleChamp);
/* Ajout d'un champ d'octets d'un Fichier. */
extern unsigned short API_ENTRY
SGD_AjouterChampFichier (unsigned short NumeroSession,
const char* NomFichier);
/* Lecture du numero du groupe suivant. */
extern unsigned short API_ENTRY
SGD_LireGroupeSuivant (unsigned short NumeroSession,
unsigned short IdGroupeCourant,
unsigned short OccurrenceGroupeCourant,
unsigned short* IdGroupeSuivant,
unsigned short* OccurrenceGroupeSuivant);
/* Lecture d'un champ. */
extern unsigned short API_ENTRY
SGD_LireChamp (unsigned short NumeroSession,
unsigned short IdGroupe,
unsigned short OccurrenceGroupe,
unsigned short NumeroChamp,
char* ValeurChamp,
size_t* TailleMax);
/* Lecture d'un champ d'octets. */
extern unsigned short API_ENTRY
SGD_LireChampBin (unsigned short NumeroSession,
unsigned short IdGroupe,
unsigned short OccurrenceGroupe,
unsigned short NumeroChamp,
char* ValeurChamp,
size_t* TailleMax);
/* Lecture d'un champ vers un fichier. */
extern unsigned short API_ENTRY
SGD_LireChampFichier (unsigned short NumeroSession,
unsigned short IdGroupe,
unsigned short OccurrenceGroupe,
unsigned short NumeroChamp,
const char* NomFichier);
/* Activation de la trace. */
extern unsigned short API_ENTRY
SGD_InitTrace (const char* NomFichier,
const char* ModeOuverture,
unsigned short Module,
unsigned char Niveau);
/*Initialisation de SGD*/
unsigned short API_ENTRY SGD_Init(const char *fichierSesam);
/* Transmission de la zone d'entrée. */
extern unsigned short API_ENTRY SGD_LireZoneIn(unsigned short NumeroSession,
void** ZDonneesEntree,
size_t* TailleDonneesEntree);
/* Transmission de la zone de sortie. */
typedef void (API_ENTRY *LibererZoneMem) (void* Zone);
extern unsigned short API_ENTRY SGD_EcrireZoneOut(unsigned short NumeroSession,
void* ZDonneesSortie,
size_t TailleDonneesSortie,
LibererZoneMem Fonction);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,176 @@
/*
* -------------------------------------------------------------------
* (c) 2001-2003 GIE SESAM-VITALE
*
* PROJET : Services Reglementation et Tarification
*
* FICHIER : srt.h (v5)
*
* Declaration des prototypes des fonctions SRT
* -------------------------------------------------------------------
*/
#ifndef __SRT_H__
#define __SRT_H__
#ifdef __cplusplus
extern "C" {
#endif
/*
* Inclusions
*/
#include <stddef.h>
/* Inclure le fichier de déclarations spécifiques système : win32def.h, macosdef.h, unixdef.h, etc. */
/*
* Declarations des fonctions publiques "standards"
*/
/* Recherche de codes CCAM par mot cle. */
typedef unsigned short (API_ENTRY FARPTR SRT_RechercherParMotCle)
(const char* MotCle,
unsigned long CadreRecherche,
void** ZDonneesSortie,
size_t* TailleDonneesSortie);
/* Recherche de codes CCAM par filtre. */
typedef unsigned short (API_ENTRY FARPTR SRT_RechercherParFiltre)
(const char* Filtre,
void** ZDonneesSortie,
size_t* TailleDonneesSortie);
/* Consultation de donnees CCAM. */
typedef unsigned short (API_ENTRY FARPTR SRT_ConsulterDonnee)
(const char* Identifiant,
const char* DateReference,
void* ZDonneesEntree,
size_t TailleDonneesEntree,
void** ZDonneesSortie,
size_t* TailleDonneesSortie);
/* Modification d'un champ mono-occurrent. */
typedef unsigned short (API_ENTRY FARPTR SRT_ModifierDonnee)
(const char* Identifiant,
const char* DateEffet,
void* ZDonneesEntree,
size_t TailleDonneesEntree);
/* Annulation d'une modification */
typedef unsigned short (API_ENTRY FARPTR SRT_AnnulerModification)
(const char* Identifiant,
void* ZDonneesEntree,
size_t TailleDonneesEntree);
/* Controle de la validite d'une ou plusieurs donnees. */
typedef unsigned short (API_ENTRY FARPTR SRT_ControlerDonnees)
(const char* Identifiant,
const char* DateReference,
void* ZDonneesEntree,
size_t TailleDonneesEntree,
unsigned char* Resultat);
/* Regle de gestion ou de tarification. */
typedef unsigned short (API_ENTRY FARPTR SRT_AppliquerRegle)
(const char* Identifiant,
void* ZDonneesEntree,
size_t TailleDonneesEntree,
void** ZDonneesSortie,
size_t* TailleDonneesSortie);
/* Controle complet. */
typedef unsigned short (API_ENTRY FARPTR SRT_ControleComplet)
(void* ZDonneesEntree,
size_t TailleDonneesEntree,
void** ZDonneesSortie,
size_t* TailleDonneesSortie);
/* Chargement du referentiel. */
typedef unsigned short (API_ENTRY FARPTR SRT_InitLIB2)(const char* SesamIni);
/* Dechargement du referentiel. */
typedef unsigned short (API_ENTRY FARPTR SRT_TermLIB)(void);
/* Sauvegarde des modifications. */
typedef unsigned short (API_ENTRY FARPTR SRT_SauvegarderReferentiel)(const char* Commentaire);
/* Version du referentiel. */
typedef unsigned short (API_ENTRY FARPTR SRT_LireVersion)
(void** ZDonneesSortie,
size_t* TailleDonneesSortie);
/* Activation de la trace. */
typedef unsigned short (API_ENTRY FARPTR SRT_InitTrace)
(const char* pathConf,
const char* ModeOuverture,
unsigned short Module,
unsigned char Niveau);
/* Allocation d'une zone memoire. */
typedef unsigned short (API_ENTRY FARPTR SRT_AllouerZoneMem)
(void** Zone,
size_t Taille);
/* Allocation d'une zone memoire. */
typedef void (API_ENTRY FARPTR SRT_LibererZoneMem) (void* Zone);
/*
* Declarations des fonctions publiques "simplifiees"
*/
/* Recherche de codes CCAM par mot cle. */
typedef unsigned short (API_ENTRY FARPTR SRT_RechercherParMotCle_S)
(const char* MotCle,
unsigned long CadreRecherche,
unsigned short NumeroSession);
/* Recherche de codes CCAM par filtre. */
typedef unsigned short (API_ENTRY FARPTR SRT_RechercherParFiltre_S)
(const char* Filtre,
unsigned short NumeroSession);
/* Consultation de donnees CCAM. */
typedef unsigned short (API_ENTRY FARPTR SRT_ConsulterDonnee_S)
(const char* Identifiant,
const char* DateReference,
unsigned short NumeroSession);
/* Modification d'un champ mono-occurrent. */
typedef unsigned short (API_ENTRY FARPTR SRT_ModifierDonnee_S)
(const char* Identifiant,
const char* DateEffet,
unsigned short NumeroSession);
/* Annulation des modifications d'une donnee. */
typedef unsigned short (API_ENTRY FARPTR SRT_AnnulerModification_S)
(const char* Identifiant,
unsigned short NumeroSession);
/* Controle de la validite d'une ou plusieurs donnees. */
typedef unsigned short (API_ENTRY FARPTR SRT_ControlerDonnees_S)
(const char* Identifiant,
const char* DateReference,
unsigned short NumeroSession,
unsigned char* Resultat);
/* Regle de gestion ou de tarification. */
typedef unsigned short (API_ENTRY FARPTR SRT_AppliquerRegle_S)
(const char* Identifiant,
unsigned short NumeroSession);
/* Controle complet. */
typedef unsigned short (API_ENTRY FARPTR SRT_ControleComplet_S)
(unsigned short NumeroSession);
/* Version du referentiel. */
typedef unsigned short (API_ENTRY FARPTR SRT_LireVersion_S)
(unsigned short NumeroSession);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,327 @@
/*
* -------------------------------------------------------------------
* (c) 2001-2003 GIE SESAM-VITALE
*
* PROJET : Services SESAM Vitale
*
* FICHIER : ssv.h
*
* Declaration des prototypes des fonctions SSV
* -------------------------------------------------------------------
*/
#ifndef __SSV_H__
#define __SSV_H__
#ifdef __cplusplus
extern "C" {
#endif
/*
* Inclusions
*/
#include <stddef.h>
/* Inclure le fichier de déclarations spécifiques système :
win32def.h, macosdef.h, aixdef.h, etc. */
/****** FONCTIONS STANDARDS *********/
typedef unsigned short (API_ENTRY FARPTR SSV_TraduireARL)
(short NbZDataIn,
void FARPTR FARPTR TZDataIn,
size_t FARPTR TTailleZoneIn,
void FARPTR FARPTR pZDataOut,
size_t FARPTR pTailleZoneOut);
typedef unsigned short (API_ENTRY FARPTR SSV_LireCartePS)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
void FARPTR FARPTR pZDataOut,
size_t FARPTR pTailleZone);
typedef unsigned short (API_ENTRY FARPTR SSV_LireConfig)
(void FARPTR FARPTR pZDataOut,
size_t FARPTR psTailleDataOut);
typedef unsigned short (API_ENTRY FARPTR SSV_FormaterFactures)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
char cFactureACreer,
char cModeSecur,
void FARPTR pZDataIn,
size_t TailleDataIn,
void FARPTR FARPTR pZDataOut,
size_t FARPTR pTailleZone);
typedef unsigned short (API_ENTRY FARPTR SSV_FormaterLot)
( const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
short NBZDataIn,
void FARPTR FARPTR TZDataIn,
size_t FARPTR TTailleZoneIn,
short FARPTR pNbZDataOut,
void FARPTR FARPTR TZDataOut,
size_t FARPTR TTailleZoneOut);
typedef unsigned short (API_ENTRY FARPTR SSV_FormaterFichier)
(void FARPTR pZDataIn,size_t TailleDataIn,
void FARPTR FARPTR pZDataOut,size_t FARPTR pTailleZone);
typedef unsigned short (API_ENTRY FARPTR SSV_InitTrace)
(char FARPTR pathConf, char FARPTR ModeOuverture,
unsigned short Module, unsigned char Niveau);
typedef unsigned short (API_ENTRY FARPTR SSV_AllouerZoneMem)
(void FARPTR FARPTR pZDataIn,
size_t taille);
typedef void (API_ENTRY FARPTR SSV_LibererZoneMem)
(void FARPTR pZone);
typedef unsigned short (API_ENTRY FARPTR SSV_MajDateLecteur)
(const char FARPTR pcNomRessourceLecteur,
const char FARPTR pcDateHeure);
typedef unsigned short (API_ENTRY FARPTR SSV_LireDateLecteur)
(const char FARPTR pcNomRessourceLecteur,
char FARPTR pcDateHeure);
typedef unsigned short (API_ENTRY FARPTR SSV_LireDroitsVitale)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR DateConsultation,
void FARPTR FARPTR pZDataOut,
size_t FARPTR pTailleZone);
typedef unsigned short (API_ENTRY FARPTR SSV_IdentifierTLA)
(const char FARPTR pcNomRessourceLecteur,
const char FARPTR NumVersionCDC,
void FARPTR FARPTR pZDataOut,
size_t FARPTR tailleDataOut);
typedef unsigned short (API_ENTRY FARPTR SSV_DechargerFacturesPdT)
( const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR pcNumFact,
short sNbZDataIn,
void FARPTR FARPTR pvTZDataIn,
size_t FARPTR psTTailleDataIn,
short FARPTR pNbZDataOut,
void FARPTR FARPTR TZDataOut,
size_t FARPTR TTailleZoneOut);
typedef unsigned short (API_ENTRY FARPTR SSV_DechargerFSETLA)
( const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR pcNumFact,
short FARPTR pNbZDataOut,
void FARPTR FARPTR TZDataOut,
size_t FARPTR TTailleZoneOut);
typedef unsigned short (API_ENTRY FARPTR SSV_DechargerFSETLANC)
( const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR pcNumFact,
short FARPTR pNbZDataOut,
void FARPTR FARPTR TZDataOut,
size_t FARPTR TTailleZoneOut);
typedef unsigned short (API_ENTRY FARPTR SSV_EffacerTLA)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR cNumFacturation,
const char FARPTR cTypeDonnee);
typedef unsigned short (API_ENTRY FARPTR SSV_ChargerFacturesPdT)
(const char FARPTR pcNomRessourceLecteur,
const char FARPTR pcNumFacturation,
short sNbZDataIn,
void FARPTR FARPTR pvTZDataIn,
size_t FARPTR psTTailleDataIn,
short FARPTR pNbZDataOut,
void FARPTR FARPTR TZDataOut,
size_t FARPTR TTailleZoneOut);
typedef unsigned short (API_ENTRY FARPTR SSV_ChargerAppli)
(const char FARPTR pcNomRessourceLecteur,
short sNbZDataIn,
void FARPTR FARPTR pvTZDataIn,
size_t FARPTR psTTailleDataIn);
typedef unsigned short (API_ENTRY FARPTR SSV_ChargerDonneesTLA)
(const char FARPTR pcNomRessourceLecteur,
short sNbZDataIn,
void FARPTR FARPTR pvTZDataIn,
size_t FARPTR psTTailleDataIn);
typedef unsigned short (API_ENTRY FARPTR SSV_DechargerBeneficiaires)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR cNumFacturation,
short FARPTR sNbZDataOut,
void FARPTR FARPTR pTZDataOut,
size_t FARPTR sTTailleDataOut);
typedef unsigned short (API_ENTRY FARPTR SSV_TraduireFSE)
(void FARPTR pZDataIn,
size_t TailleDataIn,
void FARPTR FARPTR pZDataOut,
size_t FARPTR pTailleZone);
typedef unsigned short (API_ENTRY FARPTR SSV_SecuriserFacture)
(const char FARPTR pcNomRessourcePS,
const char FARPTR pcNomRessourceLecteur,
const char FARPTR pcCodePorteurPS,
char cNologSituation,
const char FARPTR pcNumFact,
void FARPTR pvDataIn,
size_t szTailleDataIn ,
void FARPTR FARPTR pvDataOut,
size_t FARPTR pszTailleDataOut);
typedef unsigned short (API_ENTRY FARPTR SSV_InitLIB2) (const char FARPTR pcFichierSesam);
typedef unsigned short (API_ENTRY FARPTR SSV_TermLIB)();
/****** FONCTIONS SIMPLIFIEES *********/
typedef unsigned short (API_ENTRY FARPTR SIS_TraduireARL)
(unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_LireCartePS)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_LireConfig)
(unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_FormaterFactures)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
char cFacturesACreer,
char ModeSecur,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_FormaterLot)
( const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_FormaterFichier)
(unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_InitTrace)
(char FARPTR NomFichier, char FARPTR ModeOuverture,
unsigned short Module, unsigned char Niveau);
typedef unsigned short (API_ENTRY FARPTR SIS_MajDateLecteur)
(const char FARPTR pcNomRessourceLecteur,
const char FARPTR pcDateHeure);
typedef unsigned short (API_ENTRY FARPTR SIS_LireDateLecteur)
(const char FARPTR pcNomRessourceLecteur,
char FARPTR pcDateHeure);
typedef unsigned short (API_ENTRY FARPTR SIS_LireDroitsVitale)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR DateConsultation,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_IdentifierTLA)
(const char FARPTR pcNomRessourceLecteur,
const char FARPTR NumVersionCDC,
unsigned short numeroSession );
typedef unsigned short (API_ENTRY FARPTR SIS_DechargerFacturesPdT)
( const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR pcNumFact,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_DechargerFSETLA)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR pcNumFact,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_DechargerFSETLANC)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR pcNumFact,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_EffacerTLA)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR cNumFacturation,
const char FARPTR cTypeDonnee);
typedef unsigned short (API_ENTRY FARPTR SIS_ChargerFacturesPdT)
(const char FARPTR pcNomRessourceLecteur,
const char FARPTR pcNumFacturation,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_ChargerAppli)
(const char FARPTR pcNomRessourceLecteur,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_ChargerDonneesTLA)
(const char FARPTR pcNomRessourceLecteur,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_DechargerBeneficiaires)
( const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR cNumFacturation,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_TraduireFSE)
(unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_SecuriserFacture)
( const char FARPTR pcNomRessourcePS,
const char FARPTR pcNomRessourceLecteur,
const char FARPTR pcCodePorteurPS,
char cNologSituation,
const char FARPTR pcNumFact,
unsigned short numeroSession);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,412 @@
/*
* -------------------------------------------------------------------
* (c) 2001-2003 GIE SESAM-VITALE
*
* PROJET : Services SESAM Vitale
*
* FICHIER : ssv.h
*
* Declaration des prototypes des fonctions SSV
* -------------------------------------------------------------------
*/
#ifndef __SSV_H__
#define __SSV_H__
#ifdef __cplusplus
extern "C" {
#endif
/*
* Inclusions
*/
#include <stddef.h>
/* Inclure le fichier de déclarations spécifiques système :
win32def.h, macosdef.h, aixdef.h, etc. */
/****** FONCTIONS STANDARDS *********/
typedef unsigned short (API_ENTRY FARPTR SSV_TraduireARL)
(short NbZDataIn,
void FARPTR FARPTR TZDataIn,
size_t FARPTR TTailleZoneIn,
void FARPTR FARPTR pZDataOut,
size_t FARPTR pTailleZoneOut);
typedef unsigned short (API_ENTRY FARPTR SSV_LireCartePS)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
void FARPTR FARPTR pZDataOut,
size_t FARPTR pTailleZone);
typedef unsigned short (API_ENTRY FARPTR SSV_LireConfig)
(void FARPTR FARPTR pZDataOut,
size_t FARPTR psTailleDataOut);
typedef unsigned short (API_ENTRY FARPTR SSV_FormaterFactures)
(char cFactureACreer,
char cModeSecur,
char cTypeFlux,
void FARPTR pZDataIn,
size_t TailleDataIn,
void FARPTR FARPTR pZDataOut,
size_t FARPTR pTailleZone);
typedef unsigned short (API_ENTRY FARPTR SSV_ChiffrerFacture)
(void * pZDataIn,
size_t TailleDataIn,
void * * pZDataOut,
size_t * pTailleZone);
typedef unsigned short (API_ENTRY FARPTR SSV_SignerFactureVitale)
(const char * pcNomRessourceVitale,
void * pZDataIn,
size_t szTailleDataIn,
void * * pZDataOut,
size_t * pszTailleZone);
typedef unsigned short (API_ENTRY FARPTR SSV_CalculerHashFactureAssure)
(const char * pcNumSerie,
void * pZDataIn,
size_t szTailleDataIn,
void * * pZDataOut,
size_t * pszTailleZone);
typedef unsigned short (API_ENTRY FARPTR SSV_AjouterSignatureAssureDansFacture)
(void * pZDataIn,
size_t szTailleDataIn,
void * * pZDataOut,
size_t * pszTailleZone);
typedef unsigned short (API_ENTRY FARPTR SSV_SignerFactureCPS)
(const char * pcNomRessourcePS,
const char * pcNomRessourceLecteur,
const char * pcCodePorteurPS,
char cNologSituation,
void * pZDataIn,
size_t szTailleDataIn,
void * * pZDataOut,
size_t * pszTailleZone);
typedef unsigned short (API_ENTRY SSV_CalculerHashFacturePS)
(const char * pcNumSerieCPS,
void * pZDataIn,
size_t usTailleDataIn,
void * * pZDataOut,
size_t * pusTailleZone);
typedef unsigned short (API_ENTRY SSV_AjouterSignaturePSFacture)
(void * pZDataIn,
size_t szTailleDataIn,
void * * pZDataOut,
size_t * pszTailleZone);
typedef unsigned short (API_ENTRY FARPTR SSV_SignerLotCPS)
(const char * pcNomRessourcePS,
const char * pcNomRessourceLecteur,
const char * pcCodePorteurPS,
char cNologSituation,
void * pZDataIn,
size_t szTailleDataIn,
void * * pZDataOut,
size_t * pszTailleZone);
typedef unsigned short (API_ENTRY FARPTR SSV_FormaterLot)
( short NBZDataIn,
void FARPTR FARPTR TZDataIn,
size_t FARPTR TTailleZoneIn,
short FARPTR pNbZDataOut,
void FARPTR FARPTR TZDataOut,
size_t FARPTR TTailleZoneOut);
typedef unsigned short (API_ENTRY FARPTR SSV_FormaterFichier)
(void FARPTR pZDataIn,size_t TailleDataIn,
void FARPTR FARPTR pZDataOut,size_t FARPTR pTailleZone);
typedef unsigned short (API_ENTRY FARPTR SSV_InitTrace)
(char FARPTR pathConf, char FARPTR ModeOuverture,
unsigned short Module, unsigned char Niveau);
typedef unsigned short (API_ENTRY FARPTR SSV_AllouerZoneMem)
(void FARPTR FARPTR pZDataIn,
size_t taille);
typedef void (API_ENTRY FARPTR SSV_LibererZoneMem)
(void FARPTR pZone);
typedef unsigned short (API_ENTRY FARPTR SSV_MajDateLecteur)
(const char FARPTR pcNomRessourceLecteur,
const char FARPTR pcDateHeure);
typedef unsigned short (API_ENTRY FARPTR SSV_LireDateLecteur)
(const char FARPTR pcNomRessourceLecteur,
char FARPTR pcDateHeure);
typedef unsigned short (API_ENTRY FARPTR SSV_LireDroitsVitale)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR DateConsultation,
void FARPTR FARPTR pZDataOut,
size_t FARPTR pTailleZone);
typedef unsigned short (API_ENTRY FARPTR SSV_IdentifierTLA)
(const char FARPTR pcNomRessourceLecteur,
const char FARPTR NumVersionCDC,
void FARPTR FARPTR pZDataOut,
size_t FARPTR tailleDataOut);
typedef unsigned short (API_ENTRY FARPTR SSV_DechargerFacturesPdT)
( const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR pcNumFact,
short sNbZDataIn,
void FARPTR FARPTR pvTZDataIn,
size_t FARPTR psTTailleDataIn,
short FARPTR pNbZDataOut,
void FARPTR FARPTR TZDataOut,
size_t FARPTR TTailleZoneOut);
typedef unsigned short (API_ENTRY FARPTR SSV_DechargerFSETLA)
( const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR pcNumFact,
short FARPTR pNbZDataOut,
void FARPTR FARPTR TZDataOut,
size_t FARPTR TTailleZoneOut);
typedef unsigned short (API_ENTRY FARPTR SSV_DechargerFSETLANC)
( const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR pcNumFact,
short FARPTR pNbZDataOut,
void FARPTR FARPTR TZDataOut,
size_t FARPTR TTailleZoneOut);
typedef unsigned short (API_ENTRY FARPTR SSV_EffacerTLA)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR cNumFacturation,
const char FARPTR cTypeDonnee);
typedef unsigned short (API_ENTRY FARPTR SSV_ChargerFacturesPdT)
(const char FARPTR pcNomRessourceLecteur,
const char FARPTR pcNumFacturation,
short sNbZDataIn,
void FARPTR FARPTR pvTZDataIn,
size_t FARPTR psTTailleDataIn,
short FARPTR pNbZDataOut,
void FARPTR FARPTR TZDataOut,
size_t FARPTR TTailleZoneOut);
typedef unsigned short (API_ENTRY FARPTR SSV_ChargerAppli)
(const char FARPTR pcNomRessourceLecteur,
short sNbZDataIn,
void FARPTR FARPTR pvTZDataIn,
size_t FARPTR psTTailleDataIn);
typedef unsigned short (API_ENTRY FARPTR SSV_ChargerDonneesTLA)
(const char FARPTR pcNomRessourceLecteur,
short sNbZDataIn,
void FARPTR FARPTR pvTZDataIn,
size_t FARPTR psTTailleDataIn);
typedef unsigned short (API_ENTRY FARPTR SSV_DechargerBeneficiaires)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR cNumFacturation,
short FARPTR sNbZDataOut,
void FARPTR FARPTR pTZDataOut,
size_t FARPTR sTTailleDataOut);
typedef unsigned short (API_ENTRY FARPTR SSV_TraduireFSE)
(void FARPTR pZDataIn,
size_t TailleDataIn,
void FARPTR FARPTR pZDataOut,
size_t FARPTR pTailleZone);
typedef unsigned short (API_ENTRY FARPTR SSV_SecuriserFacture)
(const char FARPTR pcNomRessourcePS,
const char FARPTR pcNomRessourceLecteur,
const char FARPTR pcCodePorteurPS,
char cNologSituation,
const char FARPTR pcNumFact,
void FARPTR pvDataIn,
size_t szTailleDataIn ,
void FARPTR FARPTR pvDataOut,
size_t FARPTR pszTailleDataOut);
typedef unsigned short (API_ENTRY FARPTR SSV_InitLIB2) (const char FARPTR pcFichierSesam);
typedef unsigned short (API_ENTRY FARPTR SSV_TermLIB)();
/****** FONCTIONS SIMPLIFIEES *********/
typedef unsigned short (API_ENTRY FARPTR SIS_TraduireARL)
(unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_LireCartePS)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_LireConfig)
(unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_FormaterFactures)
(char cFacturesACreer,
char ModeSecur,
char cTypeFlux,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_ChiffrerFacture)
(unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_SignerFactureVitale)
(const char * pcNomRessourceVitale,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_CalculerHashFactureAssure)
(const char * pcNumSerie,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_AjouterSignatureAssureDansFacture)
(unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_SignerFactureCPS)
(const char * pcNomRessourcePS,
const char * pcNomRessourceLecteur,
const char * pcCodePorteurPS,
char cNologSituation,
unsigned short numeroSession);
typedef unsigned short (SIS_CalculerHashFacturePS)
(const char * pcNumSerieCPS,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY SIS_AjouterSignaturePSFacture)
(unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_SignerLotCPS)
(const char * pcNomRessourcePS,
const char * pcNomRessourceLecteur,
const char * pcCodePorteurPS,
char cNologSituation,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_FormaterLot)
(unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_FormaterFichier)
(unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_InitTrace)
(char FARPTR NomFichier, char FARPTR ModeOuverture,
unsigned short Module, unsigned char Niveau);
typedef unsigned short (API_ENTRY FARPTR SIS_MajDateLecteur)
(const char FARPTR pcNomRessourceLecteur,
const char FARPTR pcDateHeure);
typedef unsigned short (API_ENTRY FARPTR SIS_LireDateLecteur)
(const char FARPTR pcNomRessourceLecteur,
char FARPTR pcDateHeure);
typedef unsigned short (API_ENTRY FARPTR SIS_LireDroitsVitale)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR DateConsultation,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_IdentifierTLA)
(const char FARPTR pcNomRessourceLecteur,
const char FARPTR NumVersionCDC,
unsigned short numeroSession );
typedef unsigned short (API_ENTRY FARPTR SIS_DechargerFacturesPdT)
( const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR pcNumFact,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_DechargerFSETLA)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR pcNumFact,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_DechargerFSETLANC)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR pcNumFact,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_EffacerTLA)
(const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR cNumFacturation,
const char FARPTR cTypeDonnee);
typedef unsigned short (API_ENTRY FARPTR SIS_ChargerFacturesPdT)
(const char FARPTR pcNomRessourceLecteur,
const char FARPTR pcNumFacturation,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_ChargerAppli)
(const char FARPTR pcNomRessourceLecteur,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_ChargerDonneesTLA)
(const char FARPTR pcNomRessourceLecteur,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_DechargerBeneficiaires)
( const char FARPTR NomRessourcePS,
const char FARPTR NomRessourceLecteur,
const char FARPTR CodePorteurPS,
const char FARPTR cNumFacturation,
unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_TraduireFSE)
(unsigned short numeroSession);
typedef unsigned short (API_ENTRY FARPTR SIS_SecuriserFacture)
( const char FARPTR pcNomRessourcePS,
const char FARPTR pcNomRessourceLecteur,
const char FARPTR pcCodePorteurPS,
char cNologSituation,
const char FARPTR pcNumFact,
unsigned short numeroSession);
/* inclusion temporaire dans ssv.h pour ne pas a avoir à relivrer Sedica (pas d'incidence sur le code) -> à inclure dans sedica.h ou commun.h*/
/* Chaine discriminante d un nom de ressource TL PCSC */
#define TL_PCSC " TL "
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,353 @@
/*
%-----------------------------------------------------------------------------
% PROJET : STS INTERFACE
%
% MODULE : HEADER STS INTERFACE
%
% VERSION : cf #define ci-après
%
% FICHIER : sts.h
%
% Déclaration des prototypes des fonctions STS - INTERFACE
%-----------------------------------------------------------------------------
%
% EDS DHU - 09/04/03 - Création du .h
%
% EDS OCL - 06/06/03 - Defect 91 : Rectification du prototype de InitTrace()
%
% EDS OCL - 04/07/03 - Defect 115 : Nettoyage de stsitf.h (devenu sts.h)
%
%-----------------------------------------------------------------------------
*/
#ifndef __STSITF_H
#define __STSITF_H
#define __STSITF_VERSION "0103"
/* Ne pas oublier d'impacter idef.h aussi */
#ifdef __cplusplus
extern "C" {
#endif
/*
% Bibliothèques ANSI ou système
%------------------------------
*/
/*
% Fichiers h inclus
%------------------
*/
#include "sys_dep.h"
/*
% Macros et Constantes
%---------------------
*/
/* OCL - Defect 115 : Suppression du #define G_xxx ici même */
/* OCL - Defect 115 : Suppression du second #ifdef _cplusplus ici même */
/*********************************************************************************
************************* Fonctions réentrantes *********************************
*********************************************************************************/
/*
%-----------------------------------------------------------------------------
% STS_Tarification
%
% Rôle : Tarification de la part complémentaire des actes de la facture
%
% Paramètres d'entrée :
% MotifAppel (char) : 1er appel ('P') ou Appel sur echec de
% tarification ('E').
% ZDonneesEntree (void*) : Zone d'échange fournie par le Progiciel
% contenant toutes les informations sur la facture
% TailleDonneesEntree (size_t) : Taille de la zone d'échange Zin
%
% Paramètres de sortie :
% ZDonneesSortie (void**) : Zone d'échange fournie par le module STS appelé
% contenant toutes les informations modifiées de la facture
% en entrée et de nouvelles informations.
% TailleDonneesSortie (size_t*) : Taille de la zone d'échange Zout
%
% Valeur retournée :
% OK si pas d'erreur
% ERR_STS_NON_INITIALISE si module STS non initialisé
% et les codes d'erreurs de la tarification du module STS appelé
%
%-----------------------------------------------------------------------------
*/
/* OCL - Defect 115 : Remplacement PTR par FARPTR */
typedef unsigned short (API_ENTRY FARPTR STS_Tarification)(char MotifAppel, void FARPTR ZDonneesEntree,
size_t TailleDonneesEntree, void FARPTR FARPTR ZDonneesSortie,
size_t FARPTR TailleDonneesSortie);
/* Fonction simplifiée */
/* OCL - Defect 115 : Remplacement STS_SIM par SGD */
#ifdef SGD
typedef unsigned short (API_ENTRY FARPTR STS_Tarification_S)(char MotifAppel, unsigned short NumeroSession);
#endif
/*
%-----------------------------------------------------------------------------
% STS_Assistance
%
% Rôle : Assistance à la facturation.
%
% Paramètres d'entrée :
% MotifAppel (char) : 1er appel ('P') ou Appel sur echec de
% tarification ('E').
% PorteeAppel (ushort) : 0 pour une assistance sur toute la facture.
% 1..n pour une assistance sur un acte de rang donné /zone
% ZDonneesEntree (void*) : Zone d'échange fournie par le Progiciel
% contenant toutes les informations sur la facture
% TailleDonneesEntree (size_t) : Taille de la zone d'échange Zin
%
% Paramètres de sortie :
% ZDonneesSortie (void**) : Zone d'échange fournie par le module STS appelé
% TailleDonneesSortie (size_t*) : Taille de la zone d'échange Zout
%
% Valeur retournée : (idem Tarification)
% OK si pas d'erreur
% ERR_STS_NON_INITIALISE si module STS non initialisé
% et les codes d'erreurs de la tarification du module STS appelé
%
%-----------------------------------------------------------------------------
*/
/* OCL - Defect 115 : Remplacement PTR par FARPTR */
typedef unsigned short (API_ENTRY FARPTR STS_Assistance)(char MotifAppel, unsigned short PorteeAppel,
void FARPTR ZDonneesEntree, size_t TailleDonneesEntree,
void FARPTR FARPTR ZDonneesSortie, size_t FARPTR TailleDonneesSortie);
/* Fonction simplifiée */
#ifdef SGD
typedef unsigned short (API_ENTRY FARPTR STS_Assistance_S)(char MotifAppel, unsigned short PorteeAppel,
unsigned short NumeroSession);
#endif
/*
%-----------------------------------------------------------------------------
% STS_LireVersion
%
% Rôle : Lecture de la version de ce module et du fichier de ces tables externes
% dans le groupe 3780. Appeller la lecture de version de chaque module STS
% puis recopier la réponse 3780 de chacun dans la zone de sortie.
%
% Paramètres d'entrée : aucun
%
% Paramètres de sortie :
% ZDonneesSortie (void**) : Zone d'échange fournie par ce module
% contenant les versions (grp 3780) demandées.
% TailleDonneesSortie (size_t*) : Taille de la zone d'échange Zout
%
% Valeur retournée :
% OK si pas d'erreur
% ERR_STS_NON_INITIALISE si module STS non initialisé
% ERR_ZOUT si ZDonneesSortie==NULL ou TailleDonneesSortie==NULL
% ERR_ZONE_ALLOC si mémoire insuffisante pour allouer la Zout
%
%-----------------------------------------------------------------------------
*/
/* OCL - Defect 115 : Remplacement PTR par FARPTR */
typedef unsigned short (API_ENTRY FARPTR STS_LireVersion)(void FARPTR FARPTR ZDonneesSortie, size_t FARPTR TailleDonneesSortie);
/* Fonction simplifiée */
#ifdef SGD
typedef unsigned short (API_ENTRY FARPTR STS_LireVersion_S)(unsigned short NumeroSession);
#endif
/*
%-----------------------------------------------------------------------------
% STS_InitTrace
%
% Rôle : Initialisation des traces du module STS-Interface dans un fichier log.
% Cette fonction permet d'activer ou désactiver (niveau 0) les
% traces. Une activation requiert un nom de fichier et un mode
% d'ouverture. Un changement de niveau peut se faire sur le même
% fichier ou sur un différent s'il est précisé en entrée
%
% Paramètres d'entrée :
% NomFichier (char*) : Chemin et nom de fichier de trace
% ModeOuverture (char*) : Mode d'ouverture du fichier de trace
% "a", "w" (,"ab", "wb").
% Module (ushort) : n° de module 0 à 5 (6=TOUS)
% Niveau (uchar) : Niveau de trace : 0 signifie pas de trace, 1
% signifie traces de profondeur 8 et >=2 signifie traces sans limite
% de profondeur et activation traces module STS_SI
%
% Paramètres de sortie : aucun
%
% Valeur retournée :
% OK si pas d'erreur
% ERR_PARAM si NomFichier/ModeOuverture incorrect quand Niveau > 0
% ERR_TRACE_FILE si erreur d'ouverture du fichier de trace
%
%-----------------------------------------------------------------------------
*/
/* OCL - Defect 91 : Rectification du prototype de InitTrace() */
/* OCL - Defect 115 : Remplacement PTR par FARPTR */
typedef unsigned short (API_ENTRY FARPTR STS_InitTrace)(const char FARPTR pathConf, const char FARPTR ModeOuverture,
unsigned short Module, unsigned char Niveau);
/*********************************************************************************
************************* Fonctions d'initialisation et de terminaison *********
*********************************************************************************/
/*
%-----------------------------------------------------------------------------
% STS_InitLIB
%
% Rôle : Initialisation du module STS-Interface : Chargement des tables externes
% et suivi de parc. Appel de l'nitialisation de chaque module STS
%
% Paramètres d'entrée : aucun
%
% Paramètres de sortie : aucun
%
% Valeur retournée :
% OK si pas d'erreur
% ERR_INTERNE_ITF si erreur interne du module STS-Interface (ou STS SI)
% ERR_MEM_DISPO si plus de mémoire disponible
% ERR_PKG_PATH_INI si le chemin d'accès au fichier binaire est
% inconnu (fichier de configuration inaccessible ou information
% manquante)
% ERR_ITF_PKG_ACCES si fichier binaire de table inaccessible
% ERR_ITF_PKG_VER si version du fichier incohérent avec version du
% module STS-Interface (dans les deux sens)
% ERR_ITF_PKG_CRC si CRC du fichier binaire est incorrect
% ERR_ITF_PKG_FORME si format du fichier incorrect
% ERR_ITF_PKG_INCPT s'il manque une table dans le fichier binaire
% ERR_ITF_PKG_NOM si le nom du fichier est différent du nom dans
% l'en-tête du fichier.
% les codes suivants ne sont pas des erreurs fatales (non bloquant)
% mais juste des avertissements
% WAR_STS_DEJA_INITIALISE si module déjà initialisé
% WAR_ADM_PATH si chemin au suivi de parc non trouvé dans fichier
% de configuration des produits SV
% WAR_ADM_FILE si impossible de créer les fichiers de suivi de
% parc
% ET les codes de retour de chaque module STS appelé
%
%-----------------------------------------------------------------------------
*/
/* extern unsigned short API_ENTRY STS_InitLIB(); */
/*
%-----------------------------------------------------------------------------
% STS_InitLIB2
%
% Rôle : Initialisation du module STS-Interface : Chargement des tables externes
% et suivi de parc. Appel de l'nitialisation de chaque module STS
%
% Paramètres d'entrée :
% NomFichierIni (char*) : Chemin et nom du fichier de configuration des
% produits SESAM Vitale du poste de travail (sesam.ini)
%
% Paramètres de sortie : aucun
%
% Valeur retournée :
% OK si pas d'erreur
% ERR_INTERNE_ITF si erreur interne du module STS-Interface (ou STS SI)
% ERR_MEM_DISPO si plus de mémoire disponible
% ERR_PKG_PATH_INI si le chemin d'accès au fichier binaire est
% inconnu (fichier de configuration inaccessible ou information
% manquante)
% ERR_ITF_PKG_ACCES si fichier binaire de table inaccessible
% ERR_ITF_PKG_VER si version du fichier incohérent avec version du
% module STS-Interface (dans les deux sens)
% ERR_ITF_PKG_CRC si CRC du fichier binaire est incorrect
% ERR_ITF_PKG_FORME si format du fichier incorrect
% ERR_ITF_PKG_INCPT s'il manque une table dans le fichier binaire
% ERR_ITF_PKG_NOM si le nom du fichier est différent du nom dans
% l'en-tête du fichier.
% les codes suivants ne sont pas des erreurs fatales (non bloquant)
% mais juste des avertissements
% WAR_STS_DEJA_INITIALISE si module déjà initialisé
% WAR_ADM_PATH si chemin au suivi de parc non trouvé dans fichier
% de configuration des produits SV
% WAR_ADM_FILE si impossible de créer les fichiers de suivi de
% parc
% ET les codes de retour de chaque module STS appelé
%
%-----------------------------------------------------------------------------
*/
typedef unsigned short (API_ENTRY FARPTR STS_InitLIB2)(const char FARPTR nomFichierIni);
/*
%-----------------------------------------------------------------------------
% STS_TermLIB
%
% Rôle : Terminaison du module STS-Interface : Déchargement des tables externes.
%
% Paramètres d'entrée : aucun
%
% Paramètres de sortie : aucun
%
% Valeur retournée :
% OK si pas d'erreur
% ERR_INTERNE_ITF si erreur interne du module STS-Interface (ou STS SI)
%
%-----------------------------------------------------------------------------
*/
typedef unsigned short (API_ENTRY FARPTR STS_TermLIB)(void);
/*********************************************************************************
************************* Fonctions de gestion de la mémoire *******************
*********************************************************************************/
/*
%-----------------------------------------------------------------------------
% STS_AllouerZoneMem
%
% Rôle : Allocation d'une zone d'échange de sortie par STS Interface.
% Cette fonction permet la réallocation d'une zone d'échange.
% L'allocation d'une nouvelle zone d'échange nécessite un pointeur
% NULL en entrée !
% Cette fonctio est à utiliser conjointement avec STS_LibererZoneMem
% pour faciliter le Debugage (zone allouée par l'écrivain)
%
% Paramètres d'entrée :
% Taille (size_t) : Taille de la zone d'échange à allouer.
%
% Paramètres d'entrée et de sortie :
% Zone (void**) : Zone d'échange préallouée en entrée (ou NULL).
% Zone allouée (réallouée) par le module STS-Interface.
%
% Valeur retournée :
% OK si pas d'erreur
% ERR_ZOUT si Zone==NULL ou Taille==0
% ERR_ZONE_ALLOC si plus de mémoire disponible
%
%-----------------------------------------------------------------------------
*/
/* OCL - Defect 115 : Remplacement PTR par FARPTR */
typedef unsigned short (API_ENTRY FARPTR STS_AllouerZoneMem)(void FARPTR FARPTR Zone, size_t Taille);
/*
%-----------------------------------------------------------------------------
% STS_LibererZoneMem
%
% Rôle : Libération de la zone d'échange de sortie par STS Interface.
%
% Paramètres d'entrée :
% Zone (void*) : Zone d'échange à libérer (allouée précédemment par
% le module STS-Interce par STS_AllouerZoneMem).
%
% Paramètres de sortie : aucun
%
% Valeur retournée : aucune
%
%-----------------------------------------------------------------------------
*/
/* OCL - Defect 115 : Remplacement PTR par FARPTR */
typedef void (API_ENTRY FARPTR STS_LibererZoneMem)(void FARPTR Zone);
#ifdef __cplusplus
}
#endif
#endif /* __STSITF_H */

View File

@ -0,0 +1,189 @@
/*---------------------------------------------------------------------------
PROJET : Couche de portabilite multi-systeme
PLATE-FORME: LINUX
MODULE : Definition des macros et des types utilises par la couche
d'abstraction systeme pour la plate-forme LINUX.
Le fichier de definition des types portable (ce fichier) doit
etre inclus avant tout autre .h de definitions d'APIS gip-cps.
Ce fichier definit tous les types et macros dependants du
systeme.
FICHIER : common\linux\src\linuxdef.h
VERSION : 1.00
DATE : 10/01/2001
AUTEUR : ALVARO ROCHA
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
Modifications: (nouvelle version, date, auteur, explication)
...
- V4.31 - AROC le 12/02/2001 :
Ajout des #define TRUE et FALSE ainsi que le typedef int BOOLEEN
-----------------------------------------------------------------------------
---------------------------------------------------------------------------*/
#ifndef __CPSCASDF_H
#define __CPSCASDF_H
/*----------------- definition des macros portables ------------------------*/
#ifndef far
#define far
#endif
#ifndef FAR
#define FAR
#endif
#ifndef PTR
#define PTR *
#endif
#ifndef PVOID
#define PVOID void PTR
#endif
#ifndef FARPTR
#define FARPTR PTR
#endif
#ifndef FPVOID
#define FPVOID void FARPTR
#endif
/* AROC 12/02/2001 debut : */
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
/* AROC 12/02/2001 fin */
/*----------------- definition des types portables ------------------------*/
#ifndef CHAR
#define CHAR char
#endif
#ifndef PCHAR
#define PCHAR CHAR PTR
#endif
#ifndef PSTRG
#define PSTRG CHAR PTR
#endif
#ifndef UCHAR
#define UCHAR unsigned char
#endif
#ifndef PUCHAR
#define PUCHAR UCHAR PTR
#endif
#ifndef INT8
#define INT8 char
#endif
#ifndef INT16
#define INT16 short
#endif
#ifndef INT32
#define INT32 long
#endif
#ifndef PINT8
#define PINT8 INT8 PTR
#endif
#ifndef PINT16
#define PINT16 INT16 PTR
#endif
#ifndef PINT32
#define PINT32 INT32 PTR
#endif
#ifndef UINT8
#define UINT8 unsigned char
#endif
#ifndef UINT16
#define UINT16 unsigned short
#endif
#ifndef UINT32
#define UINT32 unsigned long
#endif
#ifndef PUINT8
#define PUINT8 UINT8 PTR
#endif
#ifndef PUINT16
#define PUINT16 UINT16 PTR
#endif
#ifndef PUINT32
#define PUINT32 UINT32 PTR
#endif
/* 11/02/1997 : Ajout DRE pour CPSCAS */
#ifndef VOID
#define VOID void
#endif
#ifndef PSTR
#define PSTR char PTR
#endif
/* 11/02/1997 : Fin */
#ifndef WORD
#define WORD unsigned short
#endif
#ifndef DWORD
#define DWORD unsigned long
#endif
//typedef unsigned char BYTE;
#ifndef BYTE
#define BYTE unsigned char
#endif
//typedef BYTE far * LPBYTE;
#ifndef LPBYTE
#define LPBYTE BYTE far *
#endif
//typedef int BOOL;
#ifndef BOOL
#define BOOL int
#endif
#ifndef Unref
#define Unref( a) a=a
#endif
#ifndef min
#define min(a,b) ((a)>(b)?(b):(a))
#endif
#ifndef max
#define max(a,b) ((a)<(b)?(b):(a))
#endif
/* Taille maximale allouée par la fonction "malloc" */
#ifndef MAXBLOC
#define MAXBLOC 4294967295
#endif
#endif

View File

@ -0,0 +1,85 @@
/*
* -------------------------------------------------------------------
* (c) 2002 GIE SESAM-VITALE
*
* FICHIER : sys_def.h (v2)
*
* PLATE-FORME : Windows 32 bits
*
* Définitions dépendantes du système.
* -------------------------------------------------------------------
*/
#include "linuxdef.h"
#include "stdlib.h"
#ifndef __SYS_DEF_H__
#define __SYS_DEF_H__
#ifdef __cplusplus
extern "C" {
#endif
#ifndef API_ENTRY
#define API_ENTRY
#endif
#ifndef _MAX_PATH
#define _MAX_PATH 256
#endif
#ifndef _MAX_FNAME
#define _MAX_FNAME 160
#endif
#ifndef _MAX_DIR
#define _MAX_DIR 800
#endif
#ifndef FARPTR
#define FARPTR *
#endif
#ifndef SYS_MAX_PATH
#define SYS_MAX_PATH _MAX_PATH
#endif
#ifndef SYS_MAX_FNAME
#define SYS_MAX_FNAME _MAX_FNAME
#endif
#ifndef SYS_MAX_DIR
#define SYS_MAX_DIR _MAX_DIR
#endif
#ifndef SYS_HANDLE
#define SYS_HANDLE void *
#endif
#ifndef PTR
#define PTR *
#endif
#ifndef SYSFARPROC_
#define SYSFARPROC_
typedef unsigned short (API_ENTRY FARPTR SYSFARPROC)();
#endif
/* Séparateur utilisé dans le nommage des arborescences de fichiers */
#ifndef SEPARATEUR_REPERTOIRE
#define SEPARATEUR_REPERTOIRE '/'
#endif
/* Activation des fonctions simplifiées. */
#ifndef SGD
#define SGD
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,92 @@
/*
* -------------------------------------------------------------------
* (c) 2002 GIE SESAM-VITALE
*
* FICHIER : sys_def.h (v2)
*
* PLATE-FORME : MAC OSX
*
* Définitions dépendantes du système.
* -------------------------------------------------------------------
*/
//3/11/2004 Modification pour compilation MAC OS X
#include "osxdef.h"
#include <stdarg.h>
#include <errno.h>
#include "stdlib.h"
#ifndef __SYS_DEF_H__
#define __SYS_DEF_H__
#ifdef __cplusplus
extern "C" {
#endif
//3-11-2004 Ajout pour MAc OS X
#define FALSE 0
#define TRUE 1
//3/11/2004 Modification pour compilation MAC OS X
#ifndef API_ENTRY
#define API_ENTRY
#endif
#ifndef FARPTR
#define FARPTR *
#endif
#ifndef SYS_MAX_PATH
#define SYS_MAX_PATH _MAX_PATH
#endif
#ifndef SYS_MAX_FNAME
#define SYS_MAX_FNAME _MAX_FNAME
#endif
#ifndef SYS_MAX_DIR
#define SYS_MAX_DIR _MAX_DIR
#endif
#ifndef PTR
#define PTR *
#endif
#ifndef SYS_HANDLE
//typedef void * SYS_HANDLE;
#define SYS_HANDLE void *
#endif
#ifndef SYSFARPROC_
#define SYSFARPROC_
typedef unsigned short (API_ENTRY FARPTR SYSFARPROC)();
#endif
/* Séparateur utilisé dans le nommage des arborescences de fichiers */
#ifndef SEPARATEUR_REPERTOIRE
#ifdef WIN32
#define SEPARATEUR_REPERTOIRE '\\'
#else
#define SEPARATEUR_REPERTOIRE '/'
#endif
#endif
/* Activation des fonctions simplifiées. */
#ifndef SGD
#define SGD
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,150 @@
/*---------------------------------------------------------------------------
PROJET : Couche de portabilite multi-systeme
PLATE-FORME: MAC OS X
MODULE : Definition des macros et des types utilises par la couche
d'abstraction systeme pour la plate-forme LINUX.
Le fichier de definition des types portable (ce fichier) doit
etre inclus avant tout autre .h de definitions d'APIS gip-cps.
Ce fichier definit tous les types et macros dependants du
systeme.
FICHIER : common\linux\src\linuxdef.h
VERSION : 1.00
DATE : 10/01/2001
AUTEUR : ALVARO ROCHA
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
Modifications: (nouvelle version, date, auteur, explication)
...
- V4.31 - AROC le 12/02/2001 :
Ajout des #define TRUE et FALSE ainsi que le typedef int BOOLEEN
-----------------------------------------------------------------------------
---------------------------------------------------------------------------*/
#ifndef __CPSCASDF_H
#define __CPSCASDF_H
//#ifndef __MACTYPES__
/*#include <CarbonCore/MacTypes.h>*/
//#include"/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/Headers/MacTypes.h"*/
//#endif
/*----------------- definition des macros portables ------------------------*/
/* point d'entree exporte en DLL ????????????????????????????????????????? */
#define API_ENTRY /* pour l'instant */
#define far
#define FAR
#define PTR *
#define PVOID void PTR
#ifndef FARPTR
#define FARPTR PTR
#endif
#define FPVOID void FARPTR
/* AROC 18/O4/2001 ajout pour io_comm*/
#define HCOMM unsigned int
#define PHCOMM HCOMM FARPTR
/* AROC 12/02/2001 debut : */
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
/* AROC 12/02/2001 fin */
/*----------------- definition des types portables ------------------------*/
/* AROC 12/02/2001 debut : */
/* mise en commentaire de ce define car pb avec module sts où BOOLEEN est defini en char*/
//#ifndef BOOLEEN
//typedef int BOOLEEN;
//#define BOOLEEN int
//#endif
/* AROC 12/02/2001 fin */
/* Boolean */
#define BOOL Boolean
//#define _MAX_PATH 1024
typedef char CHAR;
typedef CHAR PTR PCHAR;
typedef CHAR PTR PSTRG;
typedef unsigned char UCHAR;
typedef UCHAR PTR PUCHAR;
typedef char INT8;
typedef short INT16;
typedef long INT32;
typedef INT8 PTR PINT8;
typedef INT16 PTR PINT16;
typedef INT32 PTR PINT32;
typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned long UINT32;
typedef UINT8 PTR PUINT8;
typedef UINT16 PTR PUINT16;
typedef UINT32 PTR PUINT32;
/* 11/02/1997 : Ajout DRE pour CPSCAS */
typedef void VOID;
typedef char PTR PSTR;
/* 11/02/1997 : Fin */
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef unsigned char BYTE;
typedef BYTE far * LPBYTE;
#define Unref( a) a=a
#ifndef min
#define min(a,b) ((a)>(b)?(b):(a))
#endif
#ifndef max
#define max(a,b) ((a)<(b)?(b):(a))
#endif
#ifdef LITTLE_ENDIAN
#undef LITTLE_ENDIAN
#endif
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
#ifndef _MAX_PATH
#define _MAX_PATH PATH_MAX /* PATH_MAX defini dans <usr/include/sys/syslimits.h> */
#endif
/* Taille maximale allouÈe par la fonction "malloc" */
#ifndef MAXBLOC
#define MAXBLOC 0x7FFFFFFF
#endif
#endif

View File

@ -0,0 +1,69 @@
/*
* -------------------------------------------------------------------
* (c) 2002 GIE SESAM-VITALE
*
* FICHIER : sys_def.h (v2)
*
* PLATE-FORME : Windows 32 bits
*
* Définitions dépendantes du système.
* -------------------------------------------------------------------
*/
#include <stdlib.h>
#ifndef __SYS_DEF_H__
#define __SYS_DEF_H__
#ifdef __cplusplus
extern "C" {
#endif
#ifndef API_ENTRY
#define API_ENTRY __stdcall
#endif
#ifndef FARPTR
#define FARPTR *
#endif
#ifndef SYS_MAX_PATH
#define SYS_MAX_PATH _MAX_PATH
#endif
#ifndef SYS_MAX_FNAME
#define SYS_MAX_FNAME _MAX_FNAME
#endif
#ifndef SYS_MAX_DIR
#define SYS_MAX_DIR _MAX_DIR
#endif
typedef void * SYS_HANDLE;
#ifndef PTR
#define PTR *
#endif
typedef unsigned short (API_ENTRY FARPTR SYSFARPROC)();
/* Séparateur utilisé dans le nommage des arborescences de fichiers */
#ifndef SEPARATEUR_REPERTOIRE
#define SEPARATEUR_REPERTOIRE '\\'
#endif
/* Activation des fonctions simplifiées. */
#ifndef SGD
#define SGD
#endif
#ifdef __cplusplus
}
#endif
#endif

28
crates/fsv/Cargo.toml Normal file
View File

@ -0,0 +1,28 @@
[package]
name = "fsv"
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0.89"
libc = "0.2.159"
num_enum = { version = "0.7.3", features = ["complex-expressions"] }
deku = { version = "0.18.1", features = ["logging"] }
thiserror.workspace = true
serde.workspace = true
fsv-sys = { path = "../fsv-sys" }
utils = { path = "../utils" }
#[dev-dependencies]
log = "0.4.22"
env_logger = "0.11.5"
[dev-dependencies]
insta = "1.40.0"
[profile.dev.package]
# Optimize insta (snapshot testing library) for faster compile times
insta.opt-level = 3
similar.opt-level = 3

View File

@ -0,0 +1,238 @@
use deku::deku_derive;
use super::{ groups, size_read, read_with_size };
#[derive(Debug, PartialEq)]
#[deku_derive(DekuRead)]
/// # Data: FSV data structure
/// This structure is the core structure to read FSV raw data
/// It handles directly the raw data returned by the FSV library
/// A `Data` structure is composed of multiple `DataBlock` structures
pub struct Data {
#[deku(read_all)]
pub blocks: Vec<DataBlock>,
}
#[derive(Debug, PartialEq)]
#[deku_derive(DekuRead)]
/// # Data block structure
/// The `DataBlock` are the main structures inside a `Data` struct
pub struct DataBlock {
pub header: BlockHeader,
#[deku(ctx = "header.group_id.0, header.data_size")]
pub content: DataGroup,
}
#[derive(Debug, PartialEq)]
#[deku_derive(DekuRead)]
/// # Block header structure
/// The `BlockHeader` structure is the header of a `DataBlock`
/// It contains the group ID and the size of the `DataBlock` contained data (`inner` field)
pub struct BlockHeader {
pub group_id: GroupId,
#[deku(reader = "size_read(deku::reader)")]
pub data_size: u64,
}
#[derive(Debug, PartialEq)]
#[deku_derive(DekuRead)]
/// # Group ID
/// Allow to identify the type of data contained in a `DataBlock`
/// It is use as matching ID in the `DataGroup` enum. All the
/// IDs are documented on the SSV documentation, pages 23-28
pub struct GroupId(
#[deku(endian="big", bytes= 2)]
pub u16,
);
/// # Data group enum
/// This enum is used to match a `DataBlock` content with the
/// correct data structure, able to parse the data contained in
#[derive(Debug, PartialEq)]
#[deku_derive(DekuRead)]
#[deku(ctx = "group_id: u16, data_size: u64", id = "group_id")]
#[allow(non_camel_case_types)]
pub enum DataGroup {
#[deku(id = 1)]
LireCartePS_Group1_Holder(
#[deku(reader = "read_with_size(deku::reader, data_size as usize)")]
groups::ssv_lire_carte_ps::group_1_holder::Holder),
#[deku(id = 2)]
LireCartePS_Group2_Situation(
#[deku(reader = "read_with_size(deku::reader, data_size as usize)")]
groups::ssv_lire_carte_ps::group_2_situation::Situation),
#[deku(id = 60)]
LireConfig_Group60_ConfigHeader(
#[deku(reader = "read_with_size(deku::reader, data_size as usize)")]
groups::ssv_lire_config::group_60_header_config::ConfigHeader),
#[deku(id = 61)]
LireConfig_Group61_ReaderConfig(
#[deku(reader = "read_with_size(deku::reader, data_size as usize)")]
groups::ssv_lire_config::group_61_reader_config::ReaderConfig),
#[deku(id = 64)]
LireConfig_Group64_SVComponentsConfig(
#[deku(reader = "read_with_size(deku::reader, data_size as usize)")]
groups::ssv_lire_config::group_64_sv_config::SVComponentsConfig),
#[deku(id = 67)]
LireConfig_Group67_PCSCReaderConfig(
#[deku(reader = "read_with_size(deku::reader, data_size as usize)")]
groups::ssv_lire_config::group_67_pcsc_config::PCSCReaderConfig),
}
#[cfg(test)]
mod tests {
use deku::DekuContainerRead as _;
use super::*;
mod deku_testing {
use super::*;
#[derive(Debug, PartialEq)]
#[deku_derive(DekuRead)]
#[deku(endian = "big")]
pub struct DekuTest {
#[deku(bits = 4)]
pub a: u8,
#[deku(bits = 4)]
pub b: u8,
pub c: u16,
}
#[derive(Debug, PartialEq)]
#[deku_derive(DekuRead)]
#[deku(endian = "big")]
pub struct DekuTestWithSizeReader {
#[deku(bytes = 2)]
pub id: u16,
#[deku(reader = "size_read(deku::reader)")]
pub size: u64,
}
#[derive(Debug, PartialEq)]
#[deku_derive(DekuRead)]
pub struct DekuTestWithGroupId {
pub group_id: GroupId,
}
}
#[test]
fn test_deserialize_deku_test() {
let buffer: &[u8] = &[0b0110_1001, 0xBE, 0xEF];
let offset: usize = 0;
let ((rest, offset), val) = deku_testing::DekuTest::from_bytes((buffer, offset)).unwrap();
assert_eq!(val.a, 0b0110);
assert_eq!(val.b, 0b1001);
assert_eq!(val.c, 0xBEEF);
assert_eq!(offset, 0);
assert_eq!(rest, &[]);
}
#[test]
fn test_deserialize_deku_test_with_offset() {
let buffer: &[u8] = &[0b0000_1111, 0b0110_1001, 0xBE, 0xEF];
let offset: usize = 8;
let ((rest, offset), val) = deku_testing::DekuTest::from_bytes((buffer, offset)).unwrap();
assert_eq!(val.a, 0b0110);
assert_eq!(val.b, 0b1001);
assert_eq!(val.c, 0xBEEF);
assert_eq!(offset, 0);
assert_eq!(rest, &[]);
}
#[test]
fn test_serialize_deku_test_with_rest() {
let buffer: &[u8] = &[0b0110_1001, 0xBE, 0xEF, 0x1F, 0x2F];
let offset: usize = 0;
let ((rest, offset), val) = deku_testing::DekuTest::from_bytes((buffer, offset)).unwrap();
assert_eq!(val.a, 0b0110);
assert_eq!(val.b, 0b1001);
assert_eq!(val.c, 0xBEEF);
assert_eq!(offset, 0);
assert_eq!(rest, &[0x1F, 0x2F]);
}
#[test]
fn test_size_read() {
let buffer: &[u8] = &[
0, 60, // ID (60)
0b0100_0000, // Size type bit (0) + Size (64)
3, 4, 5, 6, 7, 8, 9, 10, 11, 12 // Extra data (10 bytes ; should be 64)
];
let ((rest, _offset), val) = deku_testing::DekuTestWithSizeReader::from_bytes((buffer, 0)).unwrap();
assert_eq!(val.id, 60, "EX1: ID");
assert_eq!(val.size, 64, "EX1: Size");
assert_eq!(rest.len(), 10, "EX1: Rest");
let buffer: &[u8] = &[
0, 60, // ID (60)
0b1000_0010, // Size type bit (1) + Size block length (2)
0b0000_0001, 0b0100_0000, // Size (320)
3, 4, 5, 6, 7, 8, 9, 10, 11, 12 // Extra data (10 bytes ; should be 320)
];
let ((rest, _offset), val) = deku_testing::DekuTestWithSizeReader::from_bytes((buffer, 0)).unwrap();
assert_eq!(val.id, 60, "EX2: ID");
assert_eq!(val.size, 320, "EX2: Size");
println!("{:?}", rest);
// assert_eq!(val.size, 320, "EX2: Size");
}
#[test]
fn test_endianness() {
#[derive(Debug, PartialEq)]
#[deku_derive(DekuRead)]
struct DekuTest {
#[deku(endian = "big")]
field_be: u16,
#[deku(endian = "little")]
field_le: u16,
field_default: u16,
}
let buffer: &[u8] = &[
0xAB, 0xCD,
0xAB, 0xCD,
0xAB, 0xCD,
];
let (_rest, result) = DekuTest::from_bytes((buffer, 0)).unwrap();
assert_eq!(result.field_be, 0xABCD, "0xAB,0xCD - Big Endian");
assert_eq!(result.field_le, 0xCDAB, "0xAB,0xCD - Little Endian");
assert_eq!(deku::ctx::Endian::default(), deku::ctx::Endian::Little, "Default Endian");
assert_eq!(result.field_default, 0xCDAB, "0xAB,0xCD - Default Endian");
let buffer: &[u8] = &[
0, 64,
0, 64,
0, 64,
];
let (_rest, result) = DekuTest::from_bytes((buffer, 0)).unwrap();
assert_eq!(result.field_be, 64, "0,64 - Big Endian");
assert_eq!(result.field_le, 16384, "0,64 - Little Endian");
assert_eq!(deku::ctx::Endian::default(), deku::ctx::Endian::Little);
assert_eq!(result.field_default, 16384, "0,64 - Default Endian");
}
#[test]
fn test_group_id() {
// env_logger::init(); // Uncomment and run with RUST_LOG=trace for deku debugging
let buffer: &[u8] = &[
0, 60, // ID (60)
];
let (_rest, val) = deku_testing::DekuTestWithGroupId::from_bytes((buffer, 0)).unwrap();
assert_eq!(val.group_id.0, 60, "EX1: ID");
let buffer: &[u8] = &[
7, 118, // ID (1910)
];
let (_rest, val) = deku_testing::DekuTestWithGroupId::from_bytes((buffer, 0)).unwrap();
assert_eq!(val.group_id.0, 1910, "EX2: ID");
}
}

View File

@ -0,0 +1,153 @@
use std::{fmt, str::FromStr};
use deku::{deku_derive, DekuError};
use super::{ size_read, map_bytes_to_lossy_string };
pub mod ssv_lire_carte_ps;
pub mod ssv_lire_config;
/// # Convert a DataField to a specific type
/// Using this as deku map function to fill a field value from
/// a DataField
fn map_from_data_field<T>(data_field: DataField) -> Result<T, DekuError>
where
T: FromStr,
T::Err: std::fmt::Display,
{
let text = String::from_utf8(data_field.data)
.map_err(|e| DekuError::Parse(e.to_string().into()))?;
text.parse::<T>()
.map_err(|e| DekuError::Parse(e.to_string().into()))
}
/// # Extract raw bytes from a DataField, through a Vec<u8>
/// This function is used as deku map function to extract raw bytes
/// from a DataField
fn map_raw_from_data_field<T>(data_field: DataField) -> Result<T, DekuError>
where
T: From<Vec<u8>>,
{
Ok(data_field.data.into())
}
/// # Extract an enum id from a string
/// Deku enums only supports numbers as id, and we usually extract strings
/// from data fields. This function is used as a context function to convert
/// a string, such as obtained with NumericString, to an enum id
pub fn extract_enum_id_from_str<T>(id_string: &str, default: T) -> T
where T: FromStr {
id_string.parse::<T>().unwrap_or(default)
}
// ------------------- DATA FIELD TYPES -------------------
/// # Data field structure
/// This structure is the core structure to read data fields
/// It is usually used by other structures implementing the
/// `#[deku(map = "map_from_data_field")]` attribute
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
struct DataField {
#[deku(temp, reader = "size_read(deku::reader)")]
pub data_size: u64,
#[deku(bytes_read = "data_size")]
pub data: Vec<u8>,
}
#[deku_derive(DekuRead)]
#[derive(Debug, Clone, PartialEq)]
/// # Data field: Numeric string (x CN)
/// TODO: check if all the characters are numeric
pub struct NumericString(
#[deku(map = "map_from_data_field")]
pub String
);
impl From<&str> for NumericString {
fn from(s: &str) -> Self {
NumericString(s.to_string())
}
}
#[deku_derive(DekuRead)]
#[derive(Debug, Clone, PartialEq)]
/// # Data field: Alphanumeric string (x CA/CE)
pub struct AlphaNumericString(
#[deku(map = "map_from_data_field")]
pub String
);
impl From<&str> for AlphaNumericString {
fn from(s: &str) -> Self {
AlphaNumericString(s.to_string())
}
}
#[deku_derive(DekuRead)]
#[derive(Debug, Clone, PartialEq)]
/// # Data field: Raw bytes (x CB)
pub struct RawBytes(
#[deku(map = "map_raw_from_data_field")]
pub Vec<u8>
);
#[deku_derive(DekuRead)]
#[derive(Debug, Clone, PartialEq)]
/// # Data field: Raw byte (1 CB)
pub struct RawByte(
#[deku(map = "|x: DataField| -> Result<u8, DekuError> { Ok(x.data[0]) }")]
pub u8
);
#[deku_derive(DekuRead)]
#[derive(Debug, Clone, PartialEq)]
#[deku(endian = "big")]
/// # Software version
/// An almost standard software version structure in FSV
/// It is composed of a version and a revision, encoded on 2 bytes each
pub struct SoftwareVersion {
#[deku(temp, reader = "size_read(deku::reader)", assert_eq = "4")]
data_size: u64,
#[deku(bytes= 2, map = "|x: [u8; 2]| map_bytes_to_lossy_string(&x)")]
pub version: String,
#[deku(bytes= 2, map = "|x: [u8; 2]| map_bytes_to_lossy_string(&x)")]
pub revision: String,
}
impl fmt::Display for SoftwareVersion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}.{}", self.version, self.revision)
}
}
#[cfg(test)]
mod test {
use deku::DekuContainerRead as _;
use super::*;
#[test]
fn test() {
let version_bytes: [u8; 2] = [48, 55];
let version = map_bytes_to_lossy_string(&version_bytes).unwrap();
assert_eq!(version, "07");
}
#[test]
fn test_software_version() {
// env_logger::init(); // Uncomment and run with RUST_LOG=trace for deku debugging
let data: [u8; 5] = [4, 48, 55, 50, 48];
let (_rest, software_version) = SoftwareVersion::from_bytes((&data, 0)).unwrap();
// assert_eq!(software_version.data_size, 4);
assert_eq!(software_version.version, "07");
assert_eq!(software_version.revision, "20");
}
#[test]
fn test_map_from_data_field() {
let data_field = DataField {
data: vec![48, 55],
};
let id: u8 = map_from_data_field(data_field).unwrap();
assert_eq!(id, 7);
}
}

View File

@ -0,0 +1,733 @@
//! # Structures de parsing des données de la fonction SSV_LireCartePS
#![allow(clippy::explicit_auto_deref)] // False positive on ctx attributes when using extract_enum_id_from_str
use deku::deku_derive;
use crate::fsv_parsing::groups::{ extract_enum_id_from_str, AlphaNumericString, NumericString, RawByte };
/// # Titulaire
/// 1 occurence
pub mod group_1_holder {
use super::*;
/// Groupe 1 - Titulaire
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
pub struct Holder {
#[deku(temp)]
card_type_raw: NumericString, // Champ 1 : Type de carte PS (2 CN)
#[deku(ctx = "extract_enum_id_from_str::<u8>(&*card_type_raw.0, 255)")]
pub card_type: CardPSType,
#[deku(temp)]
national_id_type_raw: NumericString, // Champ 2 : Type didentification nationale (1 CN)
#[deku(ctx = "extract_enum_id_from_str::<u8>(&*national_id_type_raw.0, 255)")]
pub national_id_type: NationalIDType,
// TODO: handle national_id depending on national_id_type
pub national_id: AlphaNumericString, // /!\ CE and not CA - Champ 3 : N° didentification nationale (8-30 CE)
pub national_id_key: AlphaNumericString, // Champ 4 : Clé du N° didentification nationale (1 CN)
#[deku(temp)]
civility_code_raw: NumericString, // Champ 5 : Code civilité (2 CN)
#[deku(ctx = "extract_enum_id_from_str::<u8>(&*civility_code_raw.0, 255)")]
pub civility_code: CivilityCode,
pub holder_lastname: AlphaNumericString, // /!\ CE and not CA - Champ 6 : Nom du PS (27 CE)
pub holder_firstname: AlphaNumericString, // /!\ CE and not CA - Champ 7 : Prénom du PS (27 CE)
#[deku(temp)]
category_card_size: u8, // Champ 8 : Catégorie Carte (1 CA)
pub category_card: CategoryCard,
}
// Fields
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
#[deku(ctx = "id: u8", id = "id")]
pub enum CardPSType {
#[deku(id = 0)]
CPS, // Carte de Professionnel de Santé (CPS)
#[deku(id = 1)]
CPF, // Carte de Professionnel de Santé en Formation (CPF)
#[deku(id = 2)]
CPE, // Carte de Personnel / Directeur⋅ice d'Établissement de Santé (CDE/CPE)
#[deku(id = 3)]
CPA, // Carte de Personnel / Directeur⋅ice Autorisé⋅e (CDA/CPA)
#[deku(id = 4)]
CPM, // Carte de Personne Morale
}
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
#[deku(ctx = "id: u8", id = "id")]
pub enum NationalIDType {
#[deku(id = 0)]
ADELI, // N° ADELI
#[deku(id = 1)]
ADELICabinet, // Id Cabinet ADELI + N° employé
#[deku(id = 2)]
DRASS, // N° DRASS
#[deku(id = 3)]
FINESS, // N° FINESS + N° employé
#[deku(id = 4)]
SIREN, // N° SIREN + N° employé
#[deku(id = 5)]
SIRET, // N° SIRET + N° employé
#[deku(id = 6)]
RPPSCabinet, // Id Cabinet RPPS + N° employé
#[deku(id = 8)]
RPPS, // N° RPPS
#[deku(id = 9)]
ADELIEtudiantMedecin, // N° Etudiant Médecin type ADELI sur 9 caractères (information transmise par lANS)
}
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
#[deku(ctx = "id: u8", id = "id")]
pub enum CivilityCode {
#[deku(id = 1)]
Adjudant,
#[deku(id = 2)]
Amiral,
#[deku(id = 3)]
Aspirant,
#[deku(id = 4)]
Aumonier,
#[deku(id = 5)]
Capitaine,
#[deku(id = 6)]
Cardinal,
#[deku(id = 7)]
Chanoine,
#[deku(id = 8)]
Colonel,
#[deku(id = 9)]
Commandant,
#[deku(id = 10)]
Commissaire,
#[deku(id = 11)]
Conseiller,
#[deku(id = 12)]
Directeur,
#[deku(id = 13)]
Docteur,
#[deku(id = 14)]
Douanier,
#[deku(id = 15)]
Epouxse,
#[deku(id = 16)]
Eveque,
#[deku(id = 17)]
General,
#[deku(id = 18)]
Gouverneur,
#[deku(id = 19)]
Ingenieur,
#[deku(id = 20)]
Inspecteur,
#[deku(id = 21)]
Lieutenant,
#[deku(id = 22)]
Madame,
#[deku(id = 23)]
Mademoiselle,
#[deku(id = 24)]
Maitre,
#[deku(id = 25)]
Marechal,
#[deku(id = 26)]
Medecin,
#[deku(id = 27)]
Mesdames,
#[deku(id = 28)]
Mesdemoiselles,
#[deku(id = 29)]
Messieurs,
#[deku(id = 30)]
Monseigneur,
#[deku(id = 31)]
Monsieur,
#[deku(id = 32)]
NotreDame,
#[deku(id = 33)]
Pasteur,
#[deku(id = 34)]
Prefet,
#[deku(id = 35)]
President,
#[deku(id = 36)]
Professeur,
#[deku(id = 37)]
Recteur,
#[deku(id = 38)]
Sergent,
#[deku(id = 39)]
SousPrefet,
#[deku(id = 40)]
Technicien,
#[deku(id = 41)]
Veuve,
}
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
#[deku(id_type="u8")]
pub enum CategoryCard {
#[deku(id = 74)] // T
Test,
#[deku(id = 72)] // R
Reelle,
#[deku(id_pat = "_")]
Unknown,
}
}
/// # Situation
/// 1-16 occurences
pub mod group_2_situation {
use super::*;
/// Groupe 2 - Situation du PS
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
pub struct Situation {
pub id: RawByte, // Champ 1 : N° logique de la situation de facturation du PS (1 CB)
#[deku(temp)]
practice_mode_raw: NumericString, // Champ 2 : Mode dexercice (2 CN)
#[deku(ctx = "extract_enum_id_from_str::<u8>(&*practice_mode_raw.0, 255)")]
pub practice_mode: PracticeMode,
// #[deku(temp)]
pub practice_status_raw: NumericString, // Champ 3 : Statut dexercice (3 CN)
// #[deku(ctx = "extract_enum_id_from_str::<u8>(&*practice_status_raw.0, 255)")]
// pub practice_status: PracticeStatus,
#[deku(temp)]
activity_sector_raw: NumericString, // Champ 4 : Secteur dactivité (3 CN)
#[deku(ctx = "extract_enum_id_from_str::<u8>(&*activity_sector_raw.0, 255)")]
pub activity_sector: ActivitySector,
#[deku(temp)]
structure_id_type_raw: NumericString, // Champ 5 : Type didentification structure (1 CN)
#[deku(ctx = "extract_enum_id_from_str::<u8>(&*structure_id_type_raw.0, 255)")]
pub structure_id_type: StructureIDType,
pub structure_id: AlphaNumericString, // Champ 6 : N° didentification structure (14 CA)
pub structure_id_key: NumericString, // Champ 7 : Clé du n° didentification structure (1 CN)
pub structure_name: AlphaNumericString, // Champ 8 : Raison sociale structure (40 CE)
pub ps_billing_number: NumericString, // Champ 9 : N° didentification de facturation du PS (8 CN)
pub ps_billing_number_key: NumericString, // Champ 10 : Clé du n° didentification de facturation du PS (1 CN)
pub ps_replacement_number: AlphaNumericString, // Champ 11 : N° didentification du PS remplaçant (30 CA) -- TODO OPTIONNEL
pub ps_replacement_number_key: NumericString, // Champ 12 : Clé du n° didentification du PS remplaçant (1 CN) -- TODO OPTIONNEL
#[deku(temp)]
convention_code_raw: NumericString, // Champ 13 : Code conventionnel (1 CN)
#[deku(ctx = "extract_enum_id_from_str::<u8>(&*convention_code_raw.0, 255)")]
pub convention_code: ConventionCode,
#[deku(temp)]
specialty_code_raw: NumericString, // Champ 14 : Code spécialité (2 CN)
#[deku(ctx = "extract_enum_id_from_str::<u8>(&*specialty_code_raw.0, 255)")]
pub specialty_code: SpecialtyCode,
// #[deku(temp)]
pub rate_zone_code_raw: NumericString, // Champ 15 : Code zone tarifaire (2 CN)
// #[deku(ctx = "extract_enum_id_from_str::<u8>(&*rate_zone_code_raw.0, 255)")]
// pub rate_zone_code: RateZoneCode, // CF p53-55 - Attribution complexe, dépendant du practice_status, du specialty_code et du convention_code
#[deku(temp)]
ik_zone_code_raw: NumericString, // Champ 16 : Code zone IK - Indemnité kilométrique (2 CN)
#[deku(ctx = "extract_enum_id_from_str::<u8>(&*ik_zone_code_raw.0, 255)")]
pub ik_zone_code: IkZoneCode,
#[deku(temp)]
approval_code_1_raw: NumericString, // Champ 17 : Code agrément 1 (1 CN)
#[deku(ctx = "extract_enum_id_from_str::<u8>(&*approval_code_1_raw.0, 255)")]
pub approval_code_1: ApprovalCode,
pub approval_code_2_raw: NumericString, // Champ 18 : Code agrément 2 (1 CN) - Non utilisé pour le moment
pub approval_code_3_raw: NumericString, // Champ 19 : Code agrément 3 (1 CN) - Non utilisé pour le moment
pub invoice_signature_permission: NumericString, // Champ 20 : Habilitation à signer une facture (1 CN)
pub lot_signature_permission: NumericString, // Champ 21 : Habilitation à signer un lot (1 CN)
}
// Fields
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
#[deku(ctx = "id: u8", id = "id")]
/// Mode d'exercice
pub enum PracticeMode {
#[deku(id = 0)]
Liberal, // Libéral, exploitant, commerçant
#[deku(id = 1)]
Salarie,
#[deku(id = 4)]
Remplacant,
#[deku(id = 7)]
Benevole,
}
//
// #[deku_derive(DekuRead)]
// #[derive(Debug, PartialEq)]
// #[deku(ctx = "id: u8", id = "id")]
// /// Statut d'exercice
// pub enum PracticeStatus {
// // Cf. TAB-Statuts géré par lANS
// }
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
#[deku(ctx = "id: u8", id = "id")]
/// Secteur d'activité
pub enum ActivitySector {
#[deku(id = 10)]
EtablissementPublicDeSante, // Etablissement Public de santé
#[deku(id = 11)]
HopitauxMilitaires, // Hôpitaux Militaires
#[deku(id = 16)]
EtablissementPrivePSPH, // Etablissement Privé PSPH
#[deku(id = 17)]
EtablissementPriveNonPSPH, // Etablissement Privé Non PSPH
#[deku(id = 25)]
DispensaireDeSoins, // Dispensaire de soins
#[deku(id = 26)]
AutresStructuresDeSoinsArmee, // Autres structures de soins relevant du Service de santé des armées
#[deku(id = 31)]
CabinetIndividuel, // Cabinet individuel
#[deku(id = 32)]
CabinetDeGroupe, // Cabinet de Groupe
#[deku(id = 33)]
ExerciceEnSociete, // Exercice en Société
#[deku(id = 34)]
SecteurPrivePHTempsPlein, // Secteur privé PH temps plein
#[deku(id = 35)]
TransportSanitaire, // Transport sanitaire
#[deku(id = 37)]
EntrepriseDInterim, // Entreprise d'intérim
#[deku(id = 41)]
EtablissementDeSoinsEtPrevention, // Etablissement de Soins et Prévention
#[deku(id = 42)]
PreventionEtSoinsEnEntreprise, // Prévention. Et Soins en Entreprise
#[deku(id = 43)]
SanteScolaireEtUniversitaire, // Santé scolaire & universitaire
#[deku(id = 44)]
RecrutementEtGestionRH, // Recrutement & gestion RH
#[deku(id = 45)]
PMIPlanificationFamiliale, // P.M.I. Planification familiale
#[deku(id = 51)]
EtablissementPourHandicapes, // Etablissement pour Handicapés
#[deku(id = 52)]
ComMarketingConsultingMedia, // Com/Marketing/Consulting/Media
#[deku(id = 53)]
EtablissementPersonnesAgees, // Etablissement Personnes Agées
#[deku(id = 54)]
EtablissementAideALaFamille, // Etablissement Aide à la famille
#[deku(id = 55)]
EtablissementDEnseignement, // Etablissement d'enseignement
#[deku(id = 56)]
EtablissementsDeProtectionDeLEnfance, // Etablissements de protection de l'enfance
#[deku(id = 57)]
EtablissementsDHebergementEtDeReadaptation, // Etablissements d'hébergement et de réadaptation
#[deku(id = 58)]
Recherche, // Recherche
#[deku(id = 61)]
AssurancePrivee, // Assurance Privée
#[deku(id = 62)]
OrganismeDeSecuriteSociale, // Organisme de Sécurité Sociale
#[deku(id = 65)]
MinistereEtServicesDeconcentres, // Ministère & Serv. Déconcentrés
#[deku(id = 66)]
CollectivitesTerritoriales, // Collectivités Territoriales
#[deku(id = 68)]
AssoEtOrgaHumanitaire, // Asso et orga humanitaire
#[deku(id = 71)]
LABM, // LABM
#[deku(id = 75)]
AutreEtablissementSanitaire, // Autre établissement Sanitaire
#[deku(id = 81)]
ProdEtComGrosBienMed, // Prod. & Com. Gros Bien Med.
#[deku(id = 85)]
CommDetailDeBiensMedicaux, // Comm. Détail de biens médicaux
#[deku(id = 86)]
PharmacieDOfficine, // Pharmacie d'officine
#[deku(id = 87)]
CentreDeDialyse, // Centre de dialyse
#[deku(id = 88)]
ParaPharmacie, // Para-pharmacie
#[deku(id = 91)]
AutreSecteurDActivite, // Autre secteur d'activité
#[deku(id = 92)]
SecteurNonDefini, // Secteur non défini
#[deku(id = 93)]
CentreAntiCancer, // Centre anti-cancer
#[deku(id = 94)]
CentreDeTransfusionSanguine, // Centre de transfusion sanguine
#[deku(id = 95)]
ChaineDuMedicament, // Répart. Distrib. Fab. Exploit. Import Médicaments
#[deku(id = 96)]
IncendiesEtSecours, // Incendies et secours
#[deku(id = 97)]
EntreprisesIndustriellesNonPharma, // Entreprises industrielles et tertiaires hors industries pharmaceutiques
#[deku(id = 98)]
EntiteDUnTOM, // Entité d'un TOM
#[deku(id = 99)]
ChaineDuDispositifMedical, // Fab. Exploit. Import. Médicaments et Dispositifs Médicaux
}
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
#[deku(ctx = "id: u8", id = "id")]
/// Type d'identification structure
pub enum StructureIDType {
#[deku(id = 0)]
ADELICabinet, // Id Cabinet ADELI
#[deku(id = 1)]
FINESS, // N° FINESS
#[deku(id = 2)]
SIREN, // N° SIREN
#[deku(id = 3)]
SIRET, // N° SIRET
#[deku(id = 4)]
RPPSCabinet, // Id Cabinet RPPS
}
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
#[deku(ctx = "id: u8", id = "id")]
/// Code conventionnel
/// Dictionnaire des données FSV, p37
pub enum ConventionCode {
#[deku(id = 0)]
NonConventionne,
#[deku(id = 1)]
Conventionne,
#[deku(id = 2)]
ConventionneAvecDepassement,
#[deku(id = 3)]
ConventionneAvecHonorairesLibres,
}
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
#[deku(ctx = "id: u8", id = "id")]
/// Code spécialité
/// Dictionnaire des données FSV, p43
pub enum SpecialtyCode {
#[deku(id = 1)]
MedecineGenerale, // Médecine générale
#[deku(id = 2)]
AnesthesieReanimation, // Anesthésie-Réanimation
#[deku(id = 3)]
Cardiologie, // Cardiologie
#[deku(id = 4)]
ChirurgieGenerale, // Chirurgie Générale
#[deku(id = 5)]
DermatoVenerologie, // Dermatologie et Vénérologie
#[deku(id = 6)]
Radiologie, // Radiologie
#[deku(id = 7)]
GynecologieObstetrique, // Gynécologie obstétrique
#[deku(id = 8)]
GastroEnterologieHepatologie, // Gastro-Entérologie et Hépatologie
#[deku(id = 9)]
MedecineInterne, // Médecine interne
#[deku(id = 10)]
NeuroChirurgie, // Neuro-Chirurgie
#[deku(id = 11)]
OtoRhinoLaryngologie, // Oto-Rhino-Laryngologie
#[deku(id = 12)]
Pediatrie, // Pédiatrie
#[deku(id = 13)]
Pneumologie, // Pneumologie
#[deku(id = 14)]
Rhumatologie, // Rhumatologie
#[deku(id = 15)]
Ophtalmologie, // Ophtalmologie
#[deku(id = 16)]
ChirurgieUrologique, // Chirurgie urologique
#[deku(id = 17)]
NeuroPsychiatrie, // Neuro-Psychiatrie
#[deku(id = 18)]
Stomatologie, // Stomatologie
#[deku(id = 19)]
ChirurgienDentiste, // Chirurgien dentiste
#[deku(id = 20)]
ReanimationMedicale, // Réanimation médicale
#[deku(id = 21)]
SageFemme, // Sage-femme
#[deku(id = 22)]
SpécialisteEnMGDiplome, // Spécialiste en médecine générale avec diplôme
#[deku(id = 23)]
SpécialisteEnMGReconnu, // Spécialiste en médecine générale reconnu par lOrdre
#[deku(id = 24)]
Infirmier, // Infirmier
#[deku(id = 25)]
Psychologue, // Psychologue
#[deku(id = 26)]
MasseurKinesitherapeute, // Masseur Kinésithérapeute
#[deku(id = 27)]
PedicurePodologue, // Pédicure Podologue
#[deku(id = 28)]
Orthophoniste, // Orthophoniste
#[deku(id = 29)]
Orthoptiste, // Orthoptiste
#[deku(id = 30)]
LaboAnalysesMedicales, // Laboratoire d'analyses médicales
#[deku(id = 31)]
ReeducationReadaptationFonctionnelle, // Rééducation Réadaptation fonctionnelle
#[deku(id = 32)]
Neurologie, // Neurologie
#[deku(id = 33)]
Psychiatrie, // Psychiatrie
#[deku(id = 34)]
Geriatrie, // Gériatrie
#[deku(id = 35)]
Nephrologie, // Néphrologie
#[deku(id = 36)]
ChirurgieDentaireSpecialiteODF, // Chirurgie Dentaire spécialité O.D.F
#[deku(id = 37)]
AnatomoCytoPathologie, // Anatomo-Cyto-Pathologie
#[deku(id = 38)]
MedecinBiologiste, // Médecin biologiste
#[deku(id = 39)]
LaboPolyvalent, // Laboratoire polyvalent
#[deku(id = 40)]
LaboAnatomoCytoPathologique, // Laboratoire danatomo-cyto-pathologique
#[deku(id = 41)]
ChirurgieOrthopediqueTraumatologie, // Chirurgie Orthopédique et Traumatologie
#[deku(id = 42)]
EndocrinologieMetabolisme, // Endocrinologie et Métabolisme
#[deku(id = 43)]
ChirurgieInfantile, // Chirurgie infantile
#[deku(id = 44)]
ChirurgieMaxilloFaciale, // Chirurgie maxillo-faciale
#[deku(id = 45)]
ChirurgieMaxilloFacialeStomatologie, // Chirurgie maxillo-faciale et stomatologie
#[deku(id = 46)]
ChirurgiePlastiqueReconstructriceEsthetique, // Chirurgie plastique reconstructrice et esthétique
#[deku(id = 47)]
ChirurgieThoraciqueCardioVasculaire, // Chirurgie thoracique et cardio-vasculaire
#[deku(id = 48)]
ChirurgieVasculaire, // Chirurgie vasculaire
#[deku(id = 49)]
ChirurgieVisceraleDigestive, // Chirurgie viscérale et digestive
#[deku(id = 50)]
PharmacieDOfficine, // Pharmacie dofficine
#[deku(id = 51)]
PharmacieMutualiste, // Pharmacie Mutualiste
#[deku(id = 53)]
ChirurgienDentisteSpecialiteCO, // Chirurgien dentiste spécialité C.O.
#[deku(id = 54)]
ChirurgienDentisteSpecialiteMBD, // Chirurgien dentiste spécialité M.B.D.
#[deku(id = 60)]
PrestataireDeTypeSociete, // Prestataire de type société
#[deku(id = 61)]
PrestataireArtisan, // Prestataire artisan
#[deku(id = 62)]
PrestataireDeTypeAssociation, // Prestataire de type association
#[deku(id = 63)]
Orthesiste, // Orthésiste
#[deku(id = 64)]
Opticien, // Opticien
#[deku(id = 65)]
Audioprothesiste, // Audioprothésiste
#[deku(id = 66)]
EpithesisteOculariste, // Épithésiste Oculariste
#[deku(id = 67)]
PodoOrthesiste, // Podo-orthésiste
#[deku(id = 68)]
Orthoprothesiste, // Orthoprothésiste
#[deku(id = 69)]
ChirurgieOrale, // Chirurgie orale
#[deku(id = 70)]
GynecologieMedicale, // Gynécologie médicale
#[deku(id = 71)]
Hematologie, // Hématologie
#[deku(id = 72)]
MedecineNucleaire, // Médecine nucléaire
#[deku(id = 73)]
OncologieMedicale, // Oncologie médicale
#[deku(id = 74)]
OncologieRadiotherapique, // Oncologie radiothérapique
#[deku(id = 75)]
PsychiatrieEnfantAdolescent, // Psychiatrie de lenfant et de ladolescent
#[deku(id = 76)]
Radiotherapie, // Radiothérapie
#[deku(id = 77)]
Obstetrique, // Obstétrique
#[deku(id = 78)]
GenetiqueMedicale, // Génétique médicale
#[deku(id = 79)]
ObstetriqueGynecologieMedicale, // Obstétrique et Gynécologie médicale
#[deku(id = 80)]
SantePubliqueMedecineSociale, // Santé publique et médecine sociale
#[deku(id = 81)]
MaladiesInfectieusesTropicales, // Médecine des Maladies infectieuses et tropicales
#[deku(id = 82)]
MedecineLegaleExpertisesMedicales, // Médecine légale et expertises médicales
#[deku(id = 83)]
MedecineDurgence, // Médecine durgence
#[deku(id = 84)]
MedecineVasculaire, // Médecine vasculaire
#[deku(id = 85)]
Allergologie, // Allergologie
#[deku(id = 86)]
IPA, // Infirmier exerçant en Pratiques Avancées (IPA)
}
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
#[deku(ctx = "id: u8", id = "id")]
/// Code zone IK - Indemnité kilométrique
/// Dictionnaire des données FSV, p44
pub enum IkZoneCode {
#[deku(id = 0)]
PasDIndemniteKilometrique, // Pas d'indemnité kilométrique
#[deku(id = 1)]
IndemniteKilometriquePlaine, // Indemnité kilométrique plaine
#[deku(id = 2)]
IndemniteKilometriqueMontagne, // Indemnité kilométrique montagne
}
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
#[deku(ctx = "id: u8", id = "id")]
/// Code agrément
/// Dictionnaire des données FSV, p44
pub enum ApprovalCode {
#[deku(id = 0)]
PasAgrementRadio, // Pas d'agrément radio
#[deku(id = 1)]
AgrementDOuDDASS, // Agrément D ou DDASS
#[deku(id = 2)]
AgrementABCEF, // Agrément A, B, C, E, F
#[deku(id = 3)]
AgrementGHJ, // Agrément G, H, J
#[deku(id = 4)]
AgrementK, // Agrément K
#[deku(id = 5)]
AgrementL, // Agrément L
#[deku(id = 6)]
AgrementM, // Agrément M
}
}
#[cfg(test)]
mod tests {
use deku::DekuContainerRead as _;
use group_1_holder::{CardPSType, CategoryCard, CivilityCode, NationalIDType};
use group_2_situation::{ActivitySector, ApprovalCode, ConventionCode, IkZoneCode, PracticeMode, SpecialtyCode, StructureIDType};
use crate::fsv_parsing::blocks::BlockHeader;
use super::*;
mod data {
pub const BUFFER: &[u8] = &[
0, 1, // Block ID
53, // Block size
1, // Type de carte PS, 2 CN
48, // 0
1, // Type d'identification nationale, 1 CN
56, // 8
11, // N° d'identification nationale, 8-30 CE
57, 57, 55, 48, 48, 53, 57, 51, 54, 56, 54,
1, // Clé du N° d'identification nationale, 1 CN
54, // 6
2, // Code civilité, 2 CN
51, 49, // 31
23, // Nom du PS, 27 CE
80, 72, 65, 82, 77, 79, 70, 70, 73, 67,
69, 32, 82, 80, 80, 83, 48, 48, 53, 57,
51, 54, 56,
7, // Prénom du PS, 27 CE
71, 73, 76, 66, 69, 82, 84,
// ??? Missing ??? Catégorie Carte, 1 CA
0, 2, // Block ID
93, // Block size
1, // N° logique de la situation de facturation du PS, 1 CB
1,
1, // Mode d'exercice, 2 CN
48,
1, // Statut d'exercice, 3 CN
49,
2, // Secteur d'activité, 3 CN
56, 54,
1, // Type d'identification structure, 1 CN
49,
9, // N° d'identification structure, 14 CA
48, 66, 48, 50, 52, 54, 50, 56, 54, // 0B0246286
1, // Clé du N° d'identification structure, 1 CN
54,
34, // Raison sociale structure, 40 CE
80, 72, 65, 82, 77, 65, 67, 73, 69, 32,
68, 69, 32, 76, 65, 32, 71, 65, 82, 69,
32, 82, 79, 85, 84, 73, 69, 82, 69, 50,
52, 54, 50, 56,
8, // N° d'identification de facturation du PS, 8 CN
48, 48, 50, 48, 57, 51, 54, 56, // 00209368
1, // Clé du N° d'identification de facturation du PS, 1 CN
48,
0, // N° d'identification du PS remplaçant, 30 CA
1, // Clé du N° d'identification du PS remplaçant, 1 CN
48,
1, // Code conventionnel, 1 CN
49,
2, // Code spécialité, 2 CN
53, 48,
2, // Code zone tarifaire, 2 CN
49, 48,
2, // Code zone IK
48, 48,
1, // Code agrément 1, 1 CN
48,
1, // Code agrément 2, 1 CN
48,
1, // Code agrément 3, 1 CN
48,
1, // Habilitation à signer une Facture // 1 CN
49,
1, // Habilitation à signer un lot // 1 CN
49,
];
}
#[test]
fn test_lire_carte_ps_first_header() {
// env_logger::init(); // Uncomment and run with RUST_LOG=trace for deku debugging
let ((_rest, _offset), block_header) = BlockHeader::from_bytes((data::BUFFER, 0)).unwrap();
assert_eq!(block_header.group_id.0, 1, "Header ID");
assert_eq!(block_header.data_size, 53, "Header Size");
}
#[test]
fn test_group_1_holder() {
// env_logger::init(); // Uncomment and run with RUST_LOG=trace for deku debugging
let offset = 3*8;
let (_rest, holder) = group_1_holder::Holder::from_bytes((data::BUFFER, offset)).unwrap();
assert_eq!(holder.card_type, CardPSType::CPS, "Card type");
assert_eq!(holder.national_id_type, NationalIDType::RPPS, "National ID type");
assert_eq!(holder.national_id.0, "99700593686", "National Id");
assert_eq!(holder.national_id_key.0, "6", "National ID Key");
assert_eq!(holder.civility_code, CivilityCode::Monsieur, "Civility Code");
assert_eq!(holder.holder_lastname.0, "PHARMOFFICE RPPS0059368", "Holder Lastname");
assert_eq!(holder.holder_firstname.0, "GILBERT", "Holder Firstname");
assert_eq!(holder.category_card, CategoryCard::Unknown, "Category card");
}
#[test]
fn test_group_2_situation() {
// env_logger::init(); // Uncomment and run with RUST_LOG=trace for deku debugging
let offset = 3*8 + 53*8 + 3*8;
let (_rest, situation) = group_2_situation::Situation::from_bytes((data::BUFFER, offset)).unwrap();
assert_eq!(situation.id.0, 1, "ID");
assert_eq!(situation.practice_mode, PracticeMode::Liberal, "Practice mode");
assert_eq!(situation.practice_status_raw.0, "1", "Practice status raw");
assert_eq!(situation.activity_sector, ActivitySector::PharmacieDOfficine, "Activity sector");
assert_eq!(situation.structure_id_type, StructureIDType::FINESS, "Structure ID type");
assert_eq!(situation.structure_id.0, "0B0246286", "Structure ID");
assert_eq!(situation.structure_id_key.0, "6", "Structure ID key");
assert_eq!(situation.structure_name.0, "PHARMACIE DE LA GARE ROUTIERE24628", "Structure name");
assert_eq!(situation.ps_billing_number.0, "00209368", "PS billing number");
assert_eq!(situation.ps_billing_number_key.0, "0", "PS billing number key");
assert_eq!(situation.ps_replacement_number.0, "", "PS replacement number");
assert_eq!(situation.ps_replacement_number_key.0, "0", "PS replacement number key");
assert_eq!(situation.convention_code, ConventionCode::Conventionne, "Convention code");
assert_eq!(situation.specialty_code, SpecialtyCode::PharmacieDOfficine, "Specialty code");
assert_eq!(situation.rate_zone_code_raw.0, "10", "Rate zone code raw");
assert_eq!(situation.ik_zone_code, IkZoneCode::PasDIndemniteKilometrique, "IK zone code");
assert_eq!(situation.approval_code_1, ApprovalCode::PasAgrementRadio, "Approval code 1");
assert_eq!(situation.approval_code_2_raw.0, "0", "Approval code 2 raw");
assert_eq!(situation.approval_code_3_raw.0, "0", "Approval code 3 raw");
assert_eq!(situation.invoice_signature_permission.0, "1", "Invoice signature permission");
assert_eq!(situation.lot_signature_permission.0, "1", "Lot signature permission");
}
}

View File

@ -0,0 +1,296 @@
//! # Structures de parsing des données de la fonction SSV_LireConfig
//! Le groupe `ReaderConfig61` décrit ci-dessous est renseigné en cas dutilisation dun
//! lecteur homologué sesam-vitale uniquement et non en cas
//! dutilisation de lecteur(s) PC/SC. dans le cas dun TL ou TLA
//! configuré en mode PC/SC, un groupe `ReaderConfig61` est restitué pour chaque
//! lecteur exposé par le gestionnaire de ressources PC/SC. les
//! informations sont alors dupliquées dans chacun des groupes `ReaderConfig61`.
//! les informations sur les lecteurs PC/SC sont disponibles
//! dans les groupes `PCSCReaderConfig67`.
use deku::deku_derive;
use super::{AlphaNumericString, NumericString, SoftwareVersion};
/// # En-tête de configuration
/// 1 occurence
pub mod group_60_header_config {
use super::*;
/// Groupe 60 - En-tête de configuration
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
pub struct ConfigHeader {
pub ssv_version: SSVVersionNumber,
pub galss_version: GALSSVersionNumber,
pub pss_version: PSSVersionNumber,
}
// Fields
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
pub struct SSVVersionNumber(pub SoftwareVersion);
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
pub struct GALSSVersionNumber(pub SoftwareVersion);
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
pub struct PSSVersionNumber(pub SoftwareVersion);
}
/// # Configuration du lecteur
/// 0 à 15 occurences
pub mod group_61_reader_config {
use super::*;
/// Groupe 61 - Configuration du lecteur
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
pub struct ReaderConfig {
pub manufacturer_name: AlphaNumericString, // 15 CA
pub reader_type: AlphaNumericString, // 30 CA
pub serial_number: AlphaNumericString, // 20 CA
pub os: NumericString, // 2 CN
pub software_count: NumericString, // 2 CN
pub software_name: AlphaNumericString, // 30 CA
pub software_version: ReaderSoftwareVersion, // 4 CA
pub reader_datetime: ReaderSoftwareDate, // 12 CN
pub software_checksum: AlphaNumericString, // 4 CA
}
// Fields
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
pub struct ReaderSoftwareVersion(pub SoftwareVersion);
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
/// Format « AAAAMMJJhhmm »
/// TODO: Build a generic date-time structure
/// TODO: Implement a date parsing, like chrono crate
pub struct ReaderSoftwareDate(pub AlphaNumericString);
}
/// # Configuration SESAM-Vitale
/// N occurences
pub mod group_64_sv_config {
use super::*;
/// Groupe 64 - Configuration SESAM-Vitale
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
pub struct SVComponentsConfig {
pub id: ComponentID,
pub description: ComponentDescription,
pub version: ComponentVersion,
}
// Fields
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
pub struct ComponentID(pub NumericString);
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
pub struct ComponentDescription(pub AlphaNumericString);
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
pub struct ComponentVersion(pub AlphaNumericString);
}
/// # Configuration du lecteur PC/SC
/// N occurences
pub mod group_67_pcsc_config {
use super::*;
/// Groupe 67 - Configuration du lecteur PC/SC
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
pub struct PCSCReaderConfig {
pub name: ReaderName,
pub card_type: CardType,
}
// Fields
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
pub struct ReaderName(pub AlphaNumericString);
#[deku_derive(DekuRead)]
#[derive(Debug, PartialEq)]
pub struct CardType(pub NumericString);
}
#[cfg(test)]
mod tests {
use deku::DekuContainerRead as _;
use crate::fsv_parsing::blocks::{BlockHeader, Data, DataBlock, DataGroup};
mod data {
pub const BUFFER: &[u8] = &[
0, 60, // Block ID
15, // Block Size
4, // SSV Version
48, 55, 50, 48, // 0720
4, // GALSS Version
48, 48, 48, 48, // 0000
4, // PSS Version
48, 48, 48, 48, // 0000
0, 67, // Block ID
42, // Block Size
39, // PCSC Reader Name
71, 101, 109, 97, 108, 116, 111, 32, 80, 67,
32, 84, 119, 105, 110, 32, 82, 101, 97, 100,
101, 114, 32, 40, 54, 52, 53, 68, 57, 52,
67, 51, 41, 32, 48, 48, 32, 48, 48,
1, // Card type
50,
0, 64, // Block ID
44, // Block Size
2, // Component ID
49, 49,
35, // Component label
86, 69, 82, 83, 73, 79, 78, 32, 68, 69,
32, 76, 65, 32, 66, 73, 66, 76, 73, 79,
84, 72, 69, 81, 85, 69, 32, 68, 85, 32,
71, 65, 76, 83, 83,
4, // Component version
48, 48, 48, 48,
0, 64, // Block ID
69, // Block Size
3, // Component ID
49, 53, 49,
27, // Component label
73, 68, 69, 78, 84, 73, 70, 73, 65, 78,
84, 32, 85, 78, 73, 81, 85, 69, 32, 68,
85, 32, 80, 79, 83, 84, 69,
36, // Component version
50, 54, 57, 102, 99, 55, 101, 98, 45, 49,
100, 56, 53, 45, 52, 55, 57, 51, 45, 98,
55, 48, 101, 45, 51, 55, 49, 99, 51, 56,
102, 57, 49, 54, 51, 52,
0, 61, // Block ID
62, // Block Size
17, // Manufacturer Name
84, 69, 83, 84, 32, 77, 65, 78, 85, 70,
65, 67, 84, 85, 82, 69, 82,
4, // Reader Type
84, 69, 83, 84,
4, // Serial Number
84, 69, 83, 84,
2, // OS
79, 83,
2, // Software Count
48, 49,
4, // Software Name
84, 69, 83, 84,
4, // Software Version
48, 49, 53, 53,
12, // Reader Datetime
50, 48, 50, 52, // 2024
48, 54, 50, 53, // 06-25
49, 50, 52, 53, // 12:45
4, // Software Checksum
49, 50, 51, 52,
];
}
#[test]
fn test_lire_config_first_header() {
// env_logger::init(); // Uncomment and run with RUST_LOG=trace for deku debugging
let buffer = data::BUFFER;
let offset: usize = 0;
let ((_rest, _offset), block_header) = BlockHeader::from_bytes((buffer, offset)).unwrap();
assert_eq!(block_header.group_id.0, 60, "Header ID");
assert_eq!(block_header.data_size, 15, "Header Size");
}
#[test]
fn test_lire_config_first_block() {
// env_logger::init(); // Uncomment and run with RUST_LOG=trace for deku debugging
let buffer = data::BUFFER;
let offset: usize = 0;
let ((_rest, _offset), block) = DataBlock::from_bytes((buffer, offset)).unwrap();
let header = block.header;
let content = match block.content {
DataGroup::LireConfig_Group60_ConfigHeader(content) => content,
_ => panic!("Unexpected data block type"),
};
assert_eq!(header.group_id.0, 60, "Header ID");
assert_eq!(header.data_size, 15, "Header Size");
assert_eq!(content.ssv_version.0.version, "07", "SSV Version");
assert_eq!(content.ssv_version.0.revision, "20", "SSV Revision");
assert_eq!(content.galss_version.0.to_string(), "00.00", "GALSS Version");
assert_eq!(content.pss_version.0.to_string(), "00.00", "PSS Version");
}
#[test]
fn test_lire_config_all() {
// env_logger::init(); // Uncomment and run with RUST_LOG=trace for deku debugging
let buffer = data::BUFFER;
let offset: usize = 0;
let ((_rest, _offset), data) = Data::from_bytes((buffer, offset)).unwrap();
let blocks = data.blocks;
assert_eq!(blocks.len(), 5, "Number of blocks");
for block in blocks {
match block.content {
DataGroup::LireConfig_Group60_ConfigHeader(content) => {
assert_eq!(block.header.group_id.0, 60, "Header ID");
assert_eq!(block.header.data_size, 15, "Header Size");
assert_eq!(content.ssv_version.0.version, "07", "SSV Version");
assert_eq!(content.ssv_version.0.revision, "20", "SSV Revision");
assert_eq!(content.galss_version.0.to_string(), "00.00", "GALSS Version");
assert_eq!(content.pss_version.0.to_string(), "00.00", "PSS Version");
},
DataGroup::LireConfig_Group61_ReaderConfig(content) => {
assert_eq!(block.header.group_id.0, 61, "Header ID");
assert_eq!(block.header.data_size, 62, "Header Size");
assert_eq!(content.manufacturer_name.0, "TEST MANUFACTURER", "Manufacturer Name");
assert_eq!(content.reader_type.0, "TEST", "Reader Type");
assert_eq!(content.serial_number.0, "TEST", "Serial Number");
assert_eq!(content.os.0, "OS", "OS");
assert_eq!(content.software_count.0, "01", "Software Count");
assert_eq!(content.software_name.0, "TEST", "Software Name");
assert_eq!(content.software_version.0.version, "01", "Software Version");
assert_eq!(content.software_version.0.revision, "55", "Software Revision");
assert_eq!(content.reader_datetime.0.0, "202406251245", "Reader Datetime");
assert_eq!(content.software_checksum.0, "1234", "Software Checksum");
},
DataGroup::LireConfig_Group64_SVComponentsConfig(content) => {
assert_eq!(block.header.group_id.0, 64, "Header ID");
match content.id.0.0.as_str() {
"11" => {
assert_eq!(block.header.data_size, 44, "Header Size");
assert_eq!(content.id.0.0, "11", "G64 - 11 : Component ID");
assert_eq!(content.description.0.0, "VERSION DE LA BIBLIOTHEQUE DU GALSS", "G64 - 11 : Component Description");
assert_eq!(content.version.0.0, "0000", "G64 - 11 : Component Version");
},
"151" => {
assert_eq!(block.header.data_size, 69, "Header Size");
assert_eq!(content.id.0.0, "151", "G64 - 151 : Component ID");
assert_eq!(content.description.0.0, "IDENTIFIANT UNIQUE DU POSTE", "G64 - 151 : Component Description");
assert_eq!(content.version.0.0, "269fc7eb-1d85-4793-b70e-371c38f91634", "G64 - 151 : Component Version");
},
_ => panic!("Unexpected Component ID"),
}
},
DataGroup::LireConfig_Group67_PCSCReaderConfig(content) => {
assert_eq!(block.header.group_id.0, 67, "Header ID");
assert_eq!(block.header.data_size, 42, "Header Size");
assert_eq!(content.name.0.0, "Gemalto PC Twin Reader (645D94C3) 00 00", "Reader Name");
assert_eq!(content.card_type.0.0, "2", "Card Type");
},
_ => panic!("Unexpected data block type"),
}
}
}
}

View File

@ -0,0 +1,132 @@
use deku::ctx::BitSize;
use deku::prelude::*;
use deku::reader::ReaderRet;
use deku::{reader::Reader, DekuError};
pub mod blocks;
pub mod groups;
pub mod prelude;
pub use blocks::Data;
/// # Read the size of a FSV block / field
/// Documentation: SSV Documentation, page 29
fn size_read<R: std::io::Read + std::io::Seek>(reader: &mut Reader<R>) -> Result<u64, DekuError> {
let size_bytes = u8::from_reader_with_ctx(reader, BitSize(8))?;
let size: u64 = if size_bytes & 0b1000_0000 == 0 {
// If the Most Significant Bit is 0, the size is encoded on 7 bits
size_bytes.into()
} else {
// Else, the 7 following bits indicate the number of bytes of the block containing the size
let size_block_len: usize = (size_bytes & 0b0111_1111).into();
if size_block_len > 4 {
return Err(DekuError::Parse(format!("Unexpected size block length: {}", size_block_len).into()));
};
// The block containing the size is encoded on 1 to 4 bytes
let buffer: &mut [u8; 4] = &mut [0; 4];
let write_offset = 4 - size_block_len;
match reader.read_bytes(size_block_len, &mut buffer[write_offset..])? {
ReaderRet::Bits(_bit_vec) => return Err(DekuError::Parse("Unexpected result reading size bytes: got bits".into())),
ReaderRet::Bytes => u32::from_be_bytes(*buffer).into(),
}
};
Ok(size)
}
/// Deku Reader taking an expected size into account
/// This function limit the reading to the size given in input
fn read_with_size<T, R: std::io::Read + std::io::Seek>(
reader: &mut Reader<R>,
size: usize
) -> Result<T, DekuError>
where T: for<'a> DekuContainerRead<'a>
{
let max_size = core::mem::size_of::<T>();
let mut buf = vec![0; max_size];
let buf: &mut [u8] = &mut buf;
let ret = reader.read_bytes(size, buf)?;
let (_rest, block) = match ret {
ReaderRet::Bytes => {
T::from_bytes((buf, 0))?
},
_ => return Err(DekuError::Parse("Unexpected result reading size bytes: got bits".into())),
};
Ok(block)
}
/// # Map bytes to a lossy string
/// This function is used to map bytes to a string, ignoring invalid UTF-8 characters
/// Example: [0x41, 0x42] -> "AB"
/// Example: [48, 49, 50, 51] -> "0123"
fn map_bytes_to_lossy_string(data: &[u8]) -> Result<String, DekuError> {
// let data = data.to_vec();
let version: String = String::from_utf8_lossy(data).to_string();
Ok(version)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_read_with_size_reader() {
#[derive(Debug, PartialEq)]
#[deku_derive(DekuRead)]
struct Data {
#[deku(read_all)]
pub blocks: Vec<Block>,
}
#[derive(Debug, PartialEq)]
#[deku_derive(DekuRead)]
struct Block {
pub size: u8,
pub id: u8,
#[deku(ctx = "*id,*size-1")] // size-1 to remove the ID size
pub data: BlockType,
}
#[derive(Debug, PartialEq)]
#[deku_derive(DekuRead)]
#[deku(ctx = "id: u8, size: u8", id = "id")]
enum BlockType {
#[deku(id = 1)]
Block1(
#[deku(reader = "read_with_size(deku::reader, size as usize)")]
Block1
),
#[deku(id = 2)]
Block2(
#[deku(reader = "read_with_size(deku::reader, size as usize)")]
Block2
),
}
#[derive(Debug, PartialEq)]
#[deku_derive(DekuRead)]
struct Block1 {
pub field1_size: u8,
pub field1: u16,
pub field2_size: u8,
pub field2: u64,
}
#[derive(Debug, PartialEq)]
#[deku_derive(DekuRead)]
struct Block2;
let buffer = &[
// 1st Block, type 1
4, // Size: 4
1, // ID: 1
2, 0x12, 0x34, // Field 1, size 2
// No Field 2
// 2nd Block, type 1
6, // Size: Y
1, // ID: 2
1, 0x56, // Field 1, size 1 (casted into u16)
2, 0x78, 0x9A // Field 2, size 2
];
let (_rest, val) = Data::from_bytes((buffer, 0)).unwrap();
assert_eq!(val.blocks.len(), 2);
assert_eq!(val.blocks[0].size, 4);
assert_eq!(val.blocks[1].size, 6);
}
}

View File

@ -0,0 +1,6 @@
/*! Crate prelude
[What is a prelude?](std::prelude)
*/
pub use deku::DekuContainerRead as _;
pub use super::Data;

2
crates/fsv/src/lib.rs Normal file
View File

@ -0,0 +1,2 @@
pub mod fsv_parsing;
pub mod ssv;

View File

@ -0,0 +1,183 @@
use num_enum::FromPrimitive;
use thiserror::Error;
#[derive(Error, Debug, Eq, PartialEq, FromPrimitive)]
#[repr(u16)]
/// Liste des codes d'erreur retournés par la librairie C SSV
/// Documentation: Manuel de programmation SSV - Annexe A (p. 215)
pub enum SSVErrorCodes {
#[error("La Carte du Professionnel de Santé est absente du lecteur.")]
CPSMissing = 0xF001,
#[error("La Carte du Professionnel de Santé bloquée après trois codes porteur erronés.")]
CPSBlocked = 0xF002,
#[error("Le code porteur présenté est erroné.")]
CPSPinWrong = 0xF003,
#[error("Carte du Professionnel de Santé non valide ou inexploitable par le Logiciel Lecteur. Vérifier la présence d'un Domaine d'Assurance Maladie (DAM).")]
CPSInvalid = 0xF004,
#[error("La Carte du Professionnel de Santé est retirée du lecteur.")]
CPSRemoved = 0xF005,
/// - Sécurisation d'une série de lots en cours.
/// - Pour les fonctions TLA (sauf Identifier TLA) : Cette erreur survient lorsque le simulateur TLA est en mode 1.50.
/// - Lire Date Lecteur, Mettre à jour Date Lecteur, Lire Droits Vitale : Cette erreur peut survenir lorsque le Logiciel Lecteur ne connaît pas la fonction sollicitée, c'est-à-dire si la version du Logiciel Lecteur est antérieure à 2.00.
/// - Décharger Données Bénéficiaires : cette erreur peut survenir pour signaler que le format des données issues du lecteur est incompatible avec cette version de SSV.
#[error("F022: Erreur commune à plusieurs fonctions.")]
F022 = 0xF022,
#[error("Message du lecteur incohérent. Débrancher et rebrancher le lecteur.")]
PCSCInconsistentMessage = 0xF0FF,
#[error("Le nom de lecteur fourni ne correspond à aucun lecteur reconnu.")]
PCSCReaderNotFound = 0xF101,
#[error("La fonction InitLIB2 n'est pas encore appelée ou la fonction TermLIB a déjà été appelée.")]
FunctionInitLib2NotCalled = 0xF600,
#[error("La bibliothèque SSV nest pas chargée en mémoire. Vérifier que la fonction InitLIB2 a bien été appelée.")]
LibraryNotLoaded = 0xF690, // Warning
#[error("Carte vitale en opposition.")]
VitaleOpposition = 0xF6A1,
#[error("Zone de mémoire non allouée en sortie.")]
MemoryNotAllocated = 0xF800,
#[error("Erreur d'allocation de la zone de mémoire en sortie.")]
MemoryAllocationError = 0xF801,
#[error("Un des paramètres obligatoires d'entrée est non alloué ou invalide.")]
InputParameterNotAllocatedOrInvalid = 0xF802,
#[error("Zone de mémoire spécifiée en entrée non valide. Vérifier que la zone allouée ne dépasse pas la taille maximale autorisée (MAXBLOC).")]
InputMemoryInvalid = 0xF803,
#[error("Le format de la zone de mémoire d'entrée ou le nombre de zones mémoire est incorrect.")]
InputMemoryFormatIncorrect = 0xF810,
#[error("Problème lors de linitialisation du protocole. Erreur du Ressource Manager PC/SC. Vérifiez le lecteur.")]
PCSCProtocolInitError = 0xFF01,
#[error("Time-out au niveau protocolaire ou transmission déjà en cours avec le lecteur. Vérifiez le lecteur et l'insertion de la carte.")]
PCSCProtocolTimeout = 0xFF02,
#[error("Taille insuffisante allouée en entrée dune fonction du Resource Manager.")]
PCSCProtocolInputMemoryTooSmall = 0xFF03,
#[error("Erreur de transmission du protocole. Vérifiez le lecteur et l'insertion de la carte.")]
PCSCProtocolTransmissionError = 0xFF04,
#[error("Lecteur absent ou indisponible.")]
PCSCReaderMissingOrUnavailable = 0xFF05,
#[error("Le nom du lecteur transmis est inconnu du Resource Manager PC/SC.")]
PCSCReaderUnknown = 0xFF06,
#[error("Erreur inconnue remontée par le Resource Manager PC/SC.")]
PCSCUnknownError = 0xFF07,
#[error("Erreur interne Resource Manager PC/SC.")]
PCSCInternalError = 0xFF08,
#[error("Ressource PC/SC déjà prise en exclusivité. Vérifiez qu'une autre application n'utilise pas le lecteur.")]
PCSCResourceAlreadyExclusive = 0xFF09,
#[error("Protocole incompatible avec la carte à puce. Vérifiez l'insertion de la carte et son état.")]
PCSCProtocolIncompatible = 0xFF0A,
#[error("Paramètre incorrect. Erreur interne à la librairie SSV.")]
PCSCIncorrectParameter = 0xFF0B,
#[error("Carte absente. Insérez une carte dans le lecteur.")]
PCSCCardMissing = 0xFF0C,
#[error("L'état de la carte a été modifié (RAZ ou mise hors tension). Vérifiez si la carte n'a pas été retirée ou si une autre application n'utilise pas la carte.")]
PCSCCardStateChanged = 0xFF0D,
#[error("Carte muette ou non supportée. Vérifiez l'insertion de la carte.")]
PCSCCardUnsupported = 0xFF0E,
#[error("Code porteur CPS non renseigné.")]
CPSPinMissing = 0xFF21,
#[error("Ressource PC/SC déjà prise en exclusivité. Vérifiez que le processus en cours n'utilise pas déjà le lecteur.")]
PCSCReaderAlreadyExclusiveForCurrentProcess = 0xFF24,
#[error("Plusieurs lecteurs ou cartes de même type identifiés lors de la détection automatique.")]
PCSCDuplicatedReadersOrCardsDetected = 0xFF29,
#[error("Problème de chargement de la librairie cryptographique ou erreur retournée par la librairie cryptographique.")]
CryptoLibraryError = 0xFF30,
#[error("Erreurs internes aux Services SESAM-Vitale. Vérifiez les traces.")]
#[num_enum(alternatives = [0xFFF1..=0xFFFF])]
SSVInternalError = 0xFFF0,
#[error("Le fichier `tablebin.smc` est inaccessible en lecture (inexistant ou pas de droits d'accès).")]
FileMissingTablebinMsc = 0xF610, // tablebin.smc
#[error("Le fichier `scripts.sms` est inaccessible en lecture (inexistant ou pas de droits d'accès).")]
FileMissingScriptsSms = 0xF611, // scripts.sms
#[error("Le fichier `tablebin.ssv` est inaccessible en lecture (inexistant ou pas de droits d'accès).")]
FileMissingTablebinSsv = 0xF612, // tablebin.ssv
#[error("Le fichier `script.ssv` est inaccessible en lecture (inexistant ou pas de droits d'accès).")]
FileMissingScriptSsv = 0xF613, // script.ssv
#[error("La version du fichier `tablebin.smc` est incompatible avec la bibliothèque des SSV.")]
FileVersionIncompatibleTablebinMsc = 0xF620, // tablebin.smc
#[error("La version du fichier `scripts.sms` est incompatible avec la bibliothèque des SSV.")]
FileVersionIncompatibleScriptsSms = 0xF621, // scripts.sms
#[error("La version du fichier `tablebin.ssv` est incompatible avec la bibliothèque des SSV.")]
FileVersionIncompatibleTablebinSsv = 0xF622, // tablebin.ssv
#[error("La version du fichier `script.ssv` est incompatible avec la bibliothèque des SSV.")]
FileVersionIncompatibleScriptSsv = 0xF623, // script.ssv
#[error("L'intégrité du fichier `tablebin.smc` est incorrecte.")]
FileIntegrityIncorrectTablebinMsc = 0xF630, // tablebin.smc
#[error("L'intégrité du fichier `scripts.sms` est incorrecte.")]
FileIntegrityIncorrectScriptsSms = 0xF631, // scripts.sms
#[error("L'intégrité du fichier `tablebin.ssv` est incorrecte.")]
FileIntegrityIncorrectTablebinSsv = 0xF632, // tablebin.ssv
#[error("L'intégrité du fichier `script.ssv` est incorrecte.")]
FileIntegrityIncorrectScriptSsv = 0xF633, // script.ssv
#[error("La structure interne du fichier `tablebin.smc` est invalide.")]
FileStructureInvalidTablebinMsc = 0xF640, // tablebin.smc
#[error("La structure interne du fichier `scripts.sms` est invalide.")]
FileStructureInvalidScriptsSms = 0xF641, // scripts.sms
#[error("La structure interne du fichier `tablebin.ssv` est invalide.")]
FileStructureInvalidTablebinSsv = 0xF642, // tablebin.ssv
#[error("La structure interne du fichier `script.ssv` est invalide.")]
FileStructureInvalidScriptSsv = 0xF643, // script.ssv
#[error("Le fichier `tablebin.smc` n'a pas pu être chargé en mémoire. Essayez de libérer de la mémoire.")]
FileLoadFailedTablebinMsc = 0xF650, // tablebin.smc
#[error("Le fichier `scripts.sms` n'a pas pu être chargé en mémoire. Essayez de libérer de la mémoire.")]
FileLoadFailedScriptsSms = 0xF651, // scripts.sms
#[error("Le fichier `tablebin.ssv` n'a pas pu être chargé en mémoire. Essayez de libérer de la mémoire.")]
FileLoadFailedTablebinSsv = 0xF652, // tablebin.ssv
#[error("Le fichier `script.ssv` n'a pas pu être chargé en mémoire. Essayez de libérer de la mémoire.")]
FileLoadFailedScriptSsv = 0xF653, // script.ssv
#[error("Le nom du fichier `tablebin.smc` est invalide.")]
FileNameInvalidTablebinMsc = 0xF660, // tablebin.smc
#[error("Le nom du fichier `scripts.sms` est invalide.")]
FileNameInvalidScriptsSms = 0xF661, // scripts.sms
#[error("Le nom du fichier `tablebin.ssv` est invalide.")]
FileNameInvalidTablebinSsv = 0xF662, // tablebin.ssv
#[error("Le nom du fichier `script.ssv` est invalide.")]
FileNameInvalidScriptSsv = 0xF663, // script.ssv
#[error("La fonction Initialiser Librairie est déjà appelée.")]
FunctionInitLib2AlreadyCalled = 0xF670, // Warning
#[error("Le fichier SESAM.INI est inaccessible en lecture (fichier ou droit daccès manquant) ou ne contient pas le chemin des tables binaires des SSV.")]
SesamIniMissingFileOrTablebinPath = 0xF680,
#[error("Le chemin du répertoire de travail est absent du fichier SESAM.INI.")]
SesamIniMissingWorkDir = 0xF6F1,
#[error("Les fichiers dextension adm ne sont pas accessibles en écriture.")]
AdmFilesNotWritable = 0xF6F2, // Warning
#[error("Aucune version de FSV du socle technique trouvé. Vérifier que la version du fichier script.sms est bonne.")]
NoFsvVersionFound = 0xF6F4,
#[error("Librairie SGD absente ou incomplète.")]
LibraryMissingOrIncompleteSGD = 0xF6F5,
#[error("Librairie SMC absente ou incomplète.")]
LibraryMissingOrIncompleteSMC = 0xF6F6,
#[error("Librairie SJS absente ou incomplète.")]
LibraryMissingOrIncompleteSJS = 0xF6F7,
#[error("Librairie SMS absente ou incomplète.")]
LibraryMissingOrIncompleteSMS = 0xF6F8,
#[error("Section MGC absente / clé RepertoireConfigTrace absente / fichier log4crc.xml non trouvé à lemplacement indiqué par la clé RepertoireConfigTrace du fichier SESAM.INI.")]
SesamIniTracingConfigMissing = 0xFF22, // Warning
#[error("Interface Full PC/SC : problème de chargement de la librairie cryptographique ou erreur retournée par la librairie cryptographique.")]
PCSCInterfaceCryptoLibraryError = 0xFF25,
#[error("Valorisation incorrecte des paramètres de gestion de l'accès aux ressources dans le SESAM.INI. Vérifier les valeurs des clés tempoexclusivite, repetitionexclusivite, tempoexclusivitePCSC, repetitionexclusivitePCSC")]
SesamIniResourceAccessParamsIncorrect = 0xFF2A,
#[num_enum(catch_all)]
#[error("Erreur inattendue de la librairie SSV (code d'erreur: {0}).")]
Unexpected(u16),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_code_ranges() {
let error_code = 0xFFF1;
let error = SSVErrorCodes::from(error_code);
assert_eq!(error, SSVErrorCodes::SSVInternalError);
let error_code = 0xFFF8;
let error = SSVErrorCodes::from(error_code);
assert_eq!(error, SSVErrorCodes::SSVInternalError);
}
#[test]
fn test_catch_all() {
let error_code = 0xFBFF; // Not a valid error code
let error = SSVErrorCodes::from(error_code);
assert_eq!(error, SSVErrorCodes::Unexpected(0xFBFF));
}
}

249
crates/fsv/src/ssv/mod.rs Normal file
View File

@ -0,0 +1,249 @@
use std::{ffi::CString, ptr};
use thiserror::Error;
use fsv_sys::{
get_library_path,
Error as FsvError,
SSVLibrary,
SSVLibraryCommon,
SupportedFsvVersion,
V1_40_13,
V1_40_14
};
mod errors_ssv;
pub use errors_ssv::SSVErrorCodes;
use crate::fsv_parsing::prelude::*;
#[derive(Error, Debug)]
pub enum Error {
#[error(transparent)]
FSVSysLibrary(#[from] FsvError),
#[error(transparent)]
SSVError(#[from] SSVErrorCodes),
}
/// Enum to hold the different versions of the SSV library
pub enum SsvLibraryVersion {
V1_40_13(SSVLibrary<V1_40_13>),
V1_40_14(SSVLibrary<V1_40_14>),
}
/// Struct to hold the SSV library and access its functions
pub struct SSV {
library: SsvLibraryVersion,
}
impl SSV {
pub fn new(version: SupportedFsvVersion) -> Result<Self, Error> {
let library = match version {
SupportedFsvVersion::V1_40_13 => {
let lib_path = get_library_path(&version);
let library = SSVLibrary::<V1_40_13>::new(&lib_path)?;
SsvLibraryVersion::V1_40_13(library)
},
SupportedFsvVersion::V1_40_14 => {
let lib_path = get_library_path(&version);
let library = SSVLibrary::<V1_40_14>::new(&lib_path)?;
SsvLibraryVersion::V1_40_14(library)
},
};
Ok(Self {
library,
})
}
/// # Initialize the SSV library
/// Implement: SSV_InitLIB2
pub fn init_library(&self, sesam_ini_path: &str) -> Result<(), Error> {
let sesam_ini_path = CString::new(sesam_ini_path).expect("CString::new failed");
let result = match &self.library {
SsvLibraryVersion::V1_40_13(library) => {
unsafe { library.ssv_init_lib2(sesam_ini_path.as_ptr()) }?
},
SsvLibraryVersion::V1_40_14(library) => {
unsafe { library.ssv_init_lib2(sesam_ini_path.as_ptr()) }?
},
};
if result != 0 {
let error = SSVErrorCodes::from(result);
return Err(Error::SSVError(error));
}
Ok(())
}
/// # Read the CPS card
/// Implement: SSV_LireCartePS
pub fn read_professional_card(&self, pin_code: &str) -> Result<Data, Error> {
let pcsc_reader_name = "Gemalto PC Twin Reader (645D94C3) 00 00";
let pin_code = CString::new(pin_code).expect("CString::new failed");
let pcsc_reader_name = CString::new(pcsc_reader_name).expect("CString::new failed");
let mut out_buffer_ptr: *mut libc::c_void = ptr::null_mut();
let mut out_buffer_size: libc::size_t = 0;
let result = match &self.library {
SsvLibraryVersion::V1_40_13(library) => {
unsafe { library.ssv_lire_carte_ps(
pcsc_reader_name.as_ptr(),
pcsc_reader_name.as_ptr(),
pin_code.as_ptr(),
&mut out_buffer_ptr,
&mut out_buffer_size)
}?
},
SsvLibraryVersion::V1_40_14(library) => {
unsafe { library.ssv_lire_carte_ps(
pcsc_reader_name.as_ptr(),
pcsc_reader_name.as_ptr(),
pin_code.as_ptr(),
&mut out_buffer_ptr,
&mut out_buffer_size)
}?
},
};
if result != 0 {
// Free memory
unsafe { libc::free(out_buffer_ptr) };
let error = SSVErrorCodes::from(result);
return Err(Error::SSVError(error));
}
// Parse the buffer into a Data struct
let buffer = unsafe { std::slice::from_raw_parts(out_buffer_ptr as *const u8, out_buffer_size) };
let (_rest, cps_blocks) = Data::from_bytes((buffer, 0)).unwrap();
// Free memory
unsafe { libc::free(out_buffer_ptr) };
Ok(cps_blocks)
}
/// # Get the configuration of the SSV library
/// Implement: SSV_LireConfig
pub fn get_config(&self) -> Result<Data, Error> {
let mut out_buffer_ptr: *mut libc::c_void = ptr::null_mut();
let mut out_buffer_size: libc::size_t = 0;
let result = match &self.library {
SsvLibraryVersion::V1_40_13(library) => {
unsafe { library.ssv_lire_config(&mut out_buffer_ptr, &mut out_buffer_size) }?
},
SsvLibraryVersion::V1_40_14(library) => {
unsafe { library.ssv_lire_config(&mut out_buffer_ptr, &mut out_buffer_size) }?
},
};
if result != 0 {
// Free memory
unsafe { libc::free(out_buffer_ptr) };
let error = SSVErrorCodes::from(result);
return Err(Error::SSVError(error));
}
// Parse the buffer into a Data struct
let buffer = unsafe { std::slice::from_raw_parts(out_buffer_ptr as *const u8, out_buffer_size) };
let (_rest, config_blocks) = Data::from_bytes((buffer, 0)).unwrap();
// Free memory
unsafe { libc::free(out_buffer_ptr) };
Ok(config_blocks)
}
}
#[cfg(test)]
mod tests {
use std::env;
use utils::config::load_config;
use anyhow::{bail, Result};
use crate::fsv_parsing::{blocks::DataGroup, groups::ssv_lire_carte_ps::{group_1_holder::CardPSType, group_2_situation::{PracticeMode, SpecialtyCode}}};
use super::*;
mod setup {
use super::*;
pub fn init() -> Result<SSV> {
load_config(None)?;
let sesam_ini_path = env::var("SESAM_INI_PATH").expect("SESAM_INI_PATH must be set");
let lib = SSV::new(SupportedFsvVersion::V1_40_13)?;
lib.init_library(&sesam_ini_path)?;
Ok(lib)
}
}
#[test]
#[ignore="Not working with other tests using SSV library in parallel - Need to fix"]
// We should implement a way to initialize the library only once
// Or implement them sequentially with [serial_test crate](https://docs.rs/serial_test/latest/serial_test)
fn test_init_library() -> Result<()> {
setup::init()?;
Ok(())
}
#[test]
#[ignore="
WARNING: Read the card with PIN 1234 - Risk of blocking the card
WARNING: This test will only work with GILBERT's PHARMOFFICE card (titulaire kit pharmacie)
"]
fn test_read_professional_card_good_pin() -> Result<()> {
let lib = setup::init()?;
let pin_code = "1234";
let cps_blocks = lib.read_professional_card(pin_code)?;
// Check the first group is the holder group
let holder_group = cps_blocks.blocks.first().unwrap();
assert_eq!(holder_group.header.group_id.0, 1);
let holder_content = match &holder_group.content {
DataGroup::LireCartePS_Group1_Holder(content) => { content },
_ => bail!("Wrong group type"),
};
assert_eq!(holder_content.card_type, CardPSType::CPS, "Card type");
assert_eq!(holder_content.holder_firstname.0, "GILBERT", "Holder firstname");
// Check the second group is a situation group
let situation_group = cps_blocks.blocks.get(1).unwrap();
assert_eq!(situation_group.header.group_id.0, 2);
let situation_content = match &situation_group.content {
DataGroup::LireCartePS_Group2_Situation(content) => { content },
_ => bail!("Wrong group type"),
};
assert_eq!(situation_content.practice_mode, PracticeMode::Liberal, "Practice mode");
assert_eq!(situation_content.specialty_code, SpecialtyCode::PharmacieDOfficine, "Specialty code");
Ok(())
}
#[test]
#[ignore="WARNING: Read the card with PIN 0000 - Risk of blocking the card"]
fn test_read_professional_card_bad_pin() -> Result<()> {
let lib = setup::init()?;
let pin_code = "0000";
// Should return an error
let err = lib.read_professional_card(pin_code).unwrap_err();
assert_eq!(err.to_string(), "Le code porteur présenté est erroné.");
match err {
Error::SSVError(err) => {
assert_eq!(err as SSVErrorCodes, SSVErrorCodes::CPSPinWrong);
},
_ => bail!("Error type is not SSVError"),
}
Ok(())
}
#[test]
// #[ignore="Needs a valid FSV installation"]
fn test_get_config() -> Result<()> {
let lib = setup::init()?;
let data = lib.get_config()?;
// I don't know what to assert here ...
let header_group = data.blocks.first().unwrap();
assert_eq!(header_group.header.group_id.0, 60);
let header_content = match &header_group.content {
DataGroup::LireConfig_Group60_ConfigHeader(content) => { content },
_ => bail!("Wrong group type"),
};
assert_eq!(header_content.ssv_version.0.version, "07");
assert_eq!(header_content.ssv_version.0.revision, "20");
Ok(())
}
}

View File

@ -0,0 +1,97 @@
---
source: crates/fsv/tests/test_ssv.rs
expression: cps_blocks
---
Data {
blocks: [
DataBlock {
header: BlockHeader {
group_id: GroupId(
1,
),
data_size: 36,
},
content: LireCartePS_Group1_Holder(
Holder {
card_type: CPS,
national_id_type: RPPS,
national_id: AlphaNumericString(
"99700619010",
),
national_id_key: AlphaNumericString(
"0",
),
civility_code: Monsieur,
holder_lastname: AlphaNumericString(
"DOC0061901",
),
holder_firstname: AlphaNumericString(
"KIT",
),
category_card: Unknown,
},
),
},
DataBlock {
header: BlockHeader {
group_id: GroupId(
2,
),
data_size: 84,
},
content: LireCartePS_Group2_Situation(
Situation {
id: RawByte(
2,
),
practice_mode: Liberal,
practice_status_raw: NumericString(
"1",
),
activity_sector: CabinetIndividuel,
structure_id_type: RPPSCabinet,
structure_id: AlphaNumericString(
"99700619010009",
),
structure_id_key: NumericString(
"0",
),
structure_name: AlphaNumericString(
"CABINET M DOC0061901",
),
ps_billing_number: NumericString(
"00102901",
),
ps_billing_number_key: NumericString(
"6",
),
ps_replacement_number: AlphaNumericString(
"",
),
ps_replacement_number_key: NumericString(
"0",
),
convention_code: Conventionne,
specialty_code: MedecineGenerale,
rate_zone_code_raw: NumericString(
"24",
),
ik_zone_code: IndemniteKilometriquePlaine,
approval_code_1: PasAgrementRadio,
approval_code_2_raw: NumericString(
"0",
),
approval_code_3_raw: NumericString(
"0",
),
invoice_signature_permission: NumericString(
"1",
),
lot_signature_permission: NumericString(
"1",
),
},
),
},
],
}

View File

@ -0,0 +1,97 @@
---
source: crates/fsv/tests/test_ssv.rs
expression: cps_blocks
---
Data {
blocks: [
DataBlock {
header: BlockHeader {
group_id: GroupId(
1,
),
data_size: 55,
},
content: LireCartePS_Group1_Holder(
Holder {
card_type: CPS,
national_id_type: RPPS,
national_id: AlphaNumericString(
"99700593694",
),
national_id_key: AlphaNumericString(
"4",
),
civility_code: Madame,
holder_lastname: AlphaNumericString(
"ADJOINTPHARM RPPS0059369",
),
holder_firstname: AlphaNumericString(
"PATRICIA",
),
category_card: Unknown,
},
),
},
DataBlock {
header: BlockHeader {
group_id: GroupId(
2,
),
data_size: 93,
},
content: LireCartePS_Group2_Situation(
Situation {
id: RawByte(
1,
),
practice_mode: Salarie,
practice_status_raw: NumericString(
"2",
),
activity_sector: PharmacieDOfficine,
structure_id_type: FINESS,
structure_id: AlphaNumericString(
"0B0246286",
),
structure_id_key: NumericString(
"6",
),
structure_name: AlphaNumericString(
"PHARMACIE DE LA GARE ROUTIERE24628",
),
ps_billing_number: NumericString(
"00209368",
),
ps_billing_number_key: NumericString(
"0",
),
ps_replacement_number: AlphaNumericString(
"",
),
ps_replacement_number_key: NumericString(
"0",
),
convention_code: Conventionne,
specialty_code: PharmacieDOfficine,
rate_zone_code_raw: NumericString(
"10",
),
ik_zone_code: PasDIndemniteKilometrique,
approval_code_1: PasAgrementRadio,
approval_code_2_raw: NumericString(
"0",
),
approval_code_3_raw: NumericString(
"0",
),
invoice_signature_permission: NumericString(
"1",
),
lot_signature_permission: NumericString(
"1",
),
},
),
},
],
}

View File

@ -0,0 +1,97 @@
---
source: crates/fsv/tests/test_ssv.rs
expression: cps_blocks
---
Data {
blocks: [
DataBlock {
header: BlockHeader {
group_id: GroupId(
1,
),
data_size: 49,
},
content: LireCartePS_Group1_Holder(
Holder {
card_type: CPE,
national_id_type: FINESS,
national_id: AlphaNumericString(
"0B0246286/CPET00001",
),
national_id_key: AlphaNumericString(
"6",
),
civility_code: Monsieur,
holder_lastname: AlphaNumericString(
"EMPLOYE246280001",
),
holder_firstname: AlphaNumericString(
"AA",
),
category_card: Unknown,
},
),
},
DataBlock {
header: BlockHeader {
group_id: GroupId(
2,
),
data_size: 93,
},
content: LireCartePS_Group2_Situation(
Situation {
id: RawByte(
1,
),
practice_mode: Salarie,
practice_status_raw: NumericString(
"0",
),
activity_sector: PharmacieDOfficine,
structure_id_type: FINESS,
structure_id: AlphaNumericString(
"0B0246286",
),
structure_id_key: NumericString(
"6",
),
structure_name: AlphaNumericString(
"PHARMACIE DE LA GARE ROUTIERE24628",
),
ps_billing_number: NumericString(
"00209368",
),
ps_billing_number_key: NumericString(
"0",
),
ps_replacement_number: AlphaNumericString(
"",
),
ps_replacement_number_key: NumericString(
"0",
),
convention_code: Conventionne,
specialty_code: PharmacieDOfficine,
rate_zone_code_raw: NumericString(
"10",
),
ik_zone_code: PasDIndemniteKilometrique,
approval_code_1: PasAgrementRadio,
approval_code_2_raw: NumericString(
"0",
),
approval_code_3_raw: NumericString(
"0",
),
invoice_signature_permission: NumericString(
"1",
),
lot_signature_permission: NumericString(
"0",
),
},
),
},
],
}

View File

@ -0,0 +1,97 @@
---
source: crates/fsv/tests/test_ssv.rs
expression: cps_blocks
---
Data {
blocks: [
DataBlock {
header: BlockHeader {
group_id: GroupId(
1,
),
data_size: 50,
},
content: LireCartePS_Group1_Holder(
Holder {
card_type: CPS,
national_id_type: RPPS,
national_id: AlphaNumericString(
"99700520499",
),
national_id_key: AlphaNumericString(
"9",
),
civility_code: Madame,
holder_lastname: AlphaNumericString(
"INFIRMIERE RPPS0052049",
),
holder_firstname: AlphaNumericString(
"ALINE",
),
category_card: Unknown,
},
),
},
DataBlock {
header: BlockHeader {
group_id: GroupId(
2,
),
data_size: 93,
},
content: LireCartePS_Group2_Situation(
Situation {
id: RawByte(
1,
),
practice_mode: Liberal,
practice_status_raw: NumericString(
"1",
),
activity_sector: CabinetIndividuel,
structure_id_type: RPPSCabinet,
structure_id: AlphaNumericString(
"99700520499002",
),
structure_id_key: NumericString(
"0",
),
structure_name: AlphaNumericString(
"CABINET MME INFIRMIERE0052049",
),
ps_billing_number: NumericString(
"00602049",
),
ps_billing_number_key: NumericString(
"9",
),
ps_replacement_number: AlphaNumericString(
"",
),
ps_replacement_number_key: NumericString(
"0",
),
convention_code: Conventionne,
specialty_code: Infirmier,
rate_zone_code_raw: NumericString(
"20",
),
ik_zone_code: IndemniteKilometriqueMontagne,
approval_code_1: PasAgrementRadio,
approval_code_2_raw: NumericString(
"0",
),
approval_code_3_raw: NumericString(
"0",
),
invoice_signature_permission: NumericString(
"1",
),
lot_signature_permission: NumericString(
"1",
),
},
),
},
],
}

View File

@ -0,0 +1,97 @@
---
source: crates/fsv/tests/test_ssv.rs
expression: cps_blocks
---
Data {
blocks: [
DataBlock {
header: BlockHeader {
group_id: GroupId(
1,
),
data_size: 53,
},
content: LireCartePS_Group1_Holder(
Holder {
card_type: CPS,
national_id_type: RPPS,
national_id: AlphaNumericString(
"99700593686",
),
national_id_key: AlphaNumericString(
"6",
),
civility_code: Monsieur,
holder_lastname: AlphaNumericString(
"PHARMOFFICE RPPS0059368",
),
holder_firstname: AlphaNumericString(
"GILBERT",
),
category_card: Unknown,
},
),
},
DataBlock {
header: BlockHeader {
group_id: GroupId(
2,
),
data_size: 93,
},
content: LireCartePS_Group2_Situation(
Situation {
id: RawByte(
1,
),
practice_mode: Liberal,
practice_status_raw: NumericString(
"1",
),
activity_sector: PharmacieDOfficine,
structure_id_type: FINESS,
structure_id: AlphaNumericString(
"0B0246286",
),
structure_id_key: NumericString(
"6",
),
structure_name: AlphaNumericString(
"PHARMACIE DE LA GARE ROUTIERE24628",
),
ps_billing_number: NumericString(
"00209368",
),
ps_billing_number_key: NumericString(
"0",
),
ps_replacement_number: AlphaNumericString(
"",
),
ps_replacement_number_key: NumericString(
"0",
),
convention_code: Conventionne,
specialty_code: PharmacieDOfficine,
rate_zone_code_raw: NumericString(
"10",
),
ik_zone_code: PasDIndemniteKilometrique,
approval_code_1: PasAgrementRadio,
approval_code_2_raw: NumericString(
"0",
),
approval_code_3_raw: NumericString(
"0",
),
invoice_signature_permission: NumericString(
"1",
),
lot_signature_permission: NumericString(
"1",
),
},
),
},
],
}

View File

@ -0,0 +1,174 @@
use anyhow::Result;
use common::read_cps;
use fsv::ssv::{Error, SSVErrorCodes, SSV};
use insta::assert_debug_snapshot;
mod common {
use super::*;
use std::env;
use fsv::fsv_parsing::Data;
use fsv_sys::SupportedFsvVersion;
use utils::config::load_config;
pub fn init() -> Result<SSV> {
load_config(None)?;
let sesam_ini_path = env::var("SESAM_INI_PATH").expect("SESAM_INI_PATH must be set");
let lib = SSV::new(SupportedFsvVersion::V1_40_13)?;
lib.init_library(&sesam_ini_path)?;
Ok(lib)
}
pub fn read_cps() -> Result<Data> {
let lib = init()?;
Ok(lib.read_professional_card("1234")?)
}
}
// ---------------- PHARMA KIT ----------------
#[test]
#[ignore]
fn test_read_cps_pharma_kit_titulaire() -> Result<()> {
let cps_blocks = read_cps()?;
assert_debug_snapshot!(cps_blocks);
Ok(())
}
#[test]
#[ignore]
fn test_read_cps_pharma_kit_adjointe() -> Result<()> {
let cps_blocks = read_cps()?;
assert_debug_snapshot!(cps_blocks);
Ok(())
}
#[test]
#[ignore]
fn test_read_cps_pharma_kit_employe_aa() -> Result<()> {
let cps_blocks = read_cps()?;
assert_debug_snapshot!(cps_blocks);
Ok(())
}
#[test]
#[ignore]
fn test_read_cps_pharma_kit_infirmiere() -> Result<()> {
let cps_blocks = read_cps()?;
assert_debug_snapshot!(cps_blocks);
Ok(())
}
// ---------------- DEFAULT KIT ----------------
#[test]
#[ignore]
fn test_read_cps_default_kit_doc() -> Result<()> {
let cps_blocks = read_cps()?;
assert_debug_snapshot!(cps_blocks);
Ok(())
}
#[test]
#[ignore]
fn test_read_cps_default_kit_directeur() -> Result<()> {
let error = read_cps().expect_err("This card should be opposed and not be readable");
match error.downcast_ref::<Error>() {
Some(Error::SSVError(e)) => {
match e {
SSVErrorCodes::CPSInvalid => { Ok(()) },
_ => panic!("Expected SSVErrorCodes::CPSInvalid, got {:?}", e),
}
},
_ => panic!("Expected Error::SSVError got {:?}", error),
}
}
#[test]
#[ignore]
fn test_read_cps_default_kit_employee_opposee() -> Result<()> {
let error = read_cps().expect_err("This card should be opposed and not be readable");
match error.downcast_ref::<Error>() {
Some(Error::SSVError(e)) => {
match e {
SSVErrorCodes::SSVInternalError => { Ok(()) },
_ => panic!("Expected SSVErrorCodes::SSVInternalError, got {:?}", e),
}
},
_ => panic!("Expected Error::SSVError got {:?}", error),
}
}
#[test]
#[ignore]
fn test_read_cps_default_kit_doc_maximaxima() -> Result<()> {
// TODO : debug this card (ConventionCode value is 9)
let cps_blocks = read_cps()?;
assert_debug_snapshot!(cps_blocks);
Ok(())
}
#[test]
#[ignore]
fn test_read_cps_default_kit_orthophoniste() -> Result<()> {
let error = read_cps().expect_err("This card should be opposed and not be readable");
match error.downcast_ref::<Error>() {
Some(Error::SSVError(e)) => {
match e {
SSVErrorCodes::SSVInternalError => { Ok(()) },
_ => panic!("Expected SSVErrorCodes::SSVInternalError, got {:?}", e),
}
},
_ => panic!("Expected Error::SSVError got {:?}", error),
}
}
// ---------------- CENTRE SANTÉ ----------------
#[test]
#[ignore]
fn test_read_cps_centre_sante_kit_directeur() -> Result<()> {
// TODO : debug this card (ConventionCode value is 9)
let cps_blocks = read_cps()?;
assert_debug_snapshot!(cps_blocks);
Ok(())
}
#[test]
#[ignore]
fn test_read_cps_centre_sante_kit_doc() -> Result<()> {
// TODO : debug this card (ConventionCode value is 9)
let cps_blocks = read_cps()?;
assert_debug_snapshot!(cps_blocks);
Ok(())
}
#[test]
#[ignore]
fn test_read_cps_centre_sante_kit_dentiste() -> Result<()> {
// TODO : debug this card (ConventionCode value is 9)
let cps_blocks = read_cps()?;
assert_debug_snapshot!(cps_blocks);
Ok(())
}
#[test]
#[ignore]
fn test_read_cps_centre_sante_kit_assist_vladimir() -> Result<()> {
// TODO : debug this card (ConventionCode value is 9)
let cps_blocks = read_cps()?;
assert_debug_snapshot!(cps_blocks);
Ok(())
}
#[test]
#[ignore]
fn test_read_cps_centre_sante_kit_assist_marie() -> Result<()> {
// TODO : debug this card (ConventionCode value is 9)
let cps_blocks = read_cps()?;
assert_debug_snapshot!(cps_blocks);
Ok(())
}