FC.SDK
1.6.611
See the version list below for details.
dotnet add package FC.SDK --version 1.6.611
NuGet\Install-Package FC.SDK -Version 1.6.611
<PackageReference Include="FC.SDK" Version="1.6.611" />
<PackageVersion Include="FC.SDK" Version="1.6.611" />
<PackageReference Include="FC.SDK" />
paket add FC.SDK --version 1.6.611
#r "nuget: FC.SDK, 1.6.611"
#:package FC.SDK@1.6.611
#addin nuget:?package=FC.SDK&version=1.6.611
#tool nuget:?package=FC.SDK&version=1.6.611
FC.SDK — Free Canon SDK
Canon EOS camera control via PTP over USB and WiFi — pure managed C#, no EDSDK binary required.
Why
Canon's EDSDK is closed-source, non-redistributable, and Windows-only. FC.SDK implements the same camera control capabilities using the PTP protocol (reverse-engineered by the libgphoto2 project), working over USB and WiFi on any platform.
Transports
| Transport | Platform | Driver swap? | Notes |
|---|---|---|---|
| WPD (Windows Portable Devices) | Windows | None — plug & play | Uses stock MTP driver, AOT compatible |
| USB (LibUsbDotNet) | Linux/macOS/Windows | WinUSB on Windows | Cross-platform, lowest latency |
| PTP/IP (WiFi) | All | None | TCP port 15740, no cable needed |
Usage
using FC.SDK;
using FC.SDK.Canon;
// Connect via WPD (Windows, zero-install)
await using var camera = CanonCamera.ConnectWpd(deviceId);
await camera.OpenSessionAsync();
Console.WriteLine($"{camera.Model} — serial {camera.SerialNumber}, battery {camera.BatteryLevelPercent}%");
// Typed settings — no magic uint32s
await camera.SetISOAsync(EdsISOSpeed.ISO_800);
await camera.SetShutterSpeedAsync(EdsTv.Tv_1_125);
await camera.SetApertureAsync(EdsAv.Av_2_8);
// Keep the event pump running for the whole session: on EOS bodies property values only ever
// arrive through GetEvent, and an undrained queue makes the camera reject property writes.
camera.StartEventPolling();
// Snap and download (auto-detects CR2, CR3, JPG)
await camera.SetSaveToAsync(EdsSaveTo.Host);
camera.ObjectAdded += async (s, e) =>
{
var (_, fileName) = await camera.GetObjectFileNameAsync(e.ObjectHandle);
await using var fs = File.Create(fileName ?? "capture.cr2");
await camera.DownloadAsync(e.ObjectHandle, fs);
await camera.TransferCompleteAsync(e.ObjectHandle);
};
await camera.TakePictureAsync();
// Bulb exposure (mode dial must be on B)
await camera.SetMirrorLockupAsync(EdsMirrorUpSetting.On);
await camera.BulbStartAsync();
await Task.Delay(TimeSpan.FromSeconds(120));
await camera.BulbEndAsync();
// Live view + manual focus
await camera.StartLiveViewAsync();
var (error, jpeg) = await camera.GetLiveViewFrameAsync();
await camera.DriveLensAsync(EdsDriveLensStep.NearSmall);
await camera.StopLiveViewAsync();
Architecture
CanonCamera (public async API)
CanonPtpSession (Canon vendor opcodes 0x9xxx)
CanonPropertyCache (property mirror fed by the GetEvent stream)
PtpSession (transaction management, half-duplex lock)
IPtpTransport (WPD / USB / PTP-IP)
How EOS properties are read
EOS bodies expose no property-read operation: standard PTP GetDevicePropValue (0x1015) is absent from
their supported-operations list, and Canon's 0x9127 is RequestDevicePropValue — it asks the camera to emit
a value, it does not return one. Values and their selectable-value lists arrive only as PropValueChanged /
AvailListChanged records in the GetEvent (0x9116) stream. CanonPropertyCache mirrors that stream and
GetPropertyAsync answers out of the mirror, requesting a push when a code has not been seen yet. Same design
as EDSDK and libgphoto2.
Two practical consequences: run StartEventPolling for the whole session, and expect DeviceBusy on property
writes if you don't (the SDK drains and retries, but the camera really does gate writes on an empty queue).
Diagnostic viewer
Prebuilt, self-contained binaries are attached to every release
— fc-viewer-<rid>.zip for Windows, .tar.gz for Linux and macOS. No .NET install needed. The archive
carries the SDL3 native; the Vulkan loader comes from the OS:
| Platform | Also needs |
|---|---|
Windows (win-x64, win-arm64) |
nothing — vulkan-1.dll ships with any modern GPU driver |
Linux (linux-x64, linux-arm64) |
libvulkan.so.1 + an ICD (mesa-vulkan-drivers), and a font package (fonts-dejavu-core) |
macOS (osx-arm64, osx-x64) |
MoltenVK (Vulkan-on-Metal) |
Or from source:
dotnet run --project src/FC.SDK.Viewer [output-directory]
An SDL3 + Vulkan GUI that exposes every control and action the SDK has, shows the raw event-stream property cache next to the typed values, previews live view and captures, and writes a full timestamped log of every PTP exchange (including which PTP operations your body advertises). If a body misbehaves, run this and attach the log from the output directory.
Shortcuts: F5 read all properties · Space capture · Ctrl+L live view · Ctrl+D dump properties ·
Ctrl+± text size.
Feature Matrix
| Feature | FC.SDK | Canon.EDSDK (.NET) | Canon EDSDK.dll (native) |
|---|---|---|---|
| Take picture | yes | yes | yes |
| Bulb exposure | yes | yes | yes |
| Download CR2/CR3/JPEG | yes | yes | yes |
| Live view (MJPEG) | yes | yes | yes |
| Manual focus (DriveLens) | yes | yes | yes |
| Read/write ISO, Tv, Av | yes | yes | yes |
| Event polling (GetEvent) | yes | yes | yes |
| Mirror lockup control | yes | yes | yes |
| WPD (zero-install, Windows) | yes | no (wraps EDSDK.dll) | internally, not exposed |
| USB (LibUsbDotNet, cross-plat) | yes | no | Windows only |
| WiFi (PTP/IP) | yes | no | yes |
| Linux / macOS | yes (USB, WiFi) | no | no |
| NativeAOT compatible | yes | yes | n/a |
| Redistributable | MIT | LGPL | no (Canon license) |
| Requires vendor binary | no | yes (EDSDK.dll) | yes (EDSDK.dll) |
| Requires driver swap (Zadig) | WPD: no, USB: yes | n/a | no |
Canon.EDSDK (SharpAstro/Canon.EDSDK) is a .NET binding around Canon's native EDSDK.dll. It requires the vendor binary and only runs on Windows. FC.SDK reimplements the PTP protocol directly and needs no vendor DLLs.
Supported Cameras
Tested with Canon EOS 6D. Should work with any Canon EOS body that supports PTP — the Canon vendor opcodes are shared across the EOS lineup. Reported on the EOS 200D II / 250D / Rebel SL3 (DIGIC 8) in issue #1; the protocol bugs behind that report are fixed but the fix is unverified on that body — please run the viewer and attach its log if anything still misbehaves.
AOT Compatible
The entire library including the WPD transport is NativeAOT compatible — no dynamic, no reflection, all COM interop via [GeneratedComInterface].
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- LibUsbDotNet (>= 2.2.75)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.5)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on FC.SDK:
| Package | Downloads |
|---|---|
|
TianWen.Lib
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.0.801 | 88 | 8/8/2026 |
| 3.0.771 | 184 | 8/3/2026 |
| 3.0.751 | 103 | 8/3/2026 |
| 2.0.671 | 119 | 8/2/2026 |
| 1.7.651 | 144 | 8/2/2026 |
| 1.7.631 | 124 | 8/1/2026 |
| 1.6.611 | 117 | 7/30/2026 |
| 1.5.601 | 113 | 7/30/2026 |
| 1.5.571 | 99 | 7/30/2026 |
| 1.5.531 | 95 | 7/29/2026 |
| 1.4.521 | 617 | 7/5/2026 |
| 1.4.511 | 104 | 7/5/2026 |
| 1.4.501 | 131 | 7/4/2026 |
| 1.4.491 | 104 | 7/4/2026 |
| 1.3.481 | 701 | 5/14/2026 |
| 1.3.471 | 119 | 5/13/2026 |
| 1.3.461 | 110 | 5/13/2026 |
| 1.3.451 | 112 | 5/13/2026 |
| 1.3.441 | 116 | 5/13/2026 |
| 1.3.431 | 112 | 5/13/2026 |