SharpOdinClient is a .NET library that lets C# applications talk to Samsung Android devices in download mode (ODIN / LOKE). Use it to flash firmware (image, tar, tar.md5, lz4), read device info, read/write PIT, and build your own Odin-style tools — without wrapping the official closed SS_DL.dll.
USB communication uses the Windows serial COM port (Samsung CDC driver). No UsbDk dependency.
We now offer a commercial, production-grade successor built on the Odin3 v3.14.4 protocol:
SharpOdinClient Pro — C# Odin Source Code (product page)
| SharpOdinClient (this repo) | SharpOdinClient Pro | |
|---|---|---|
| License | GPL-3.0 (open source) | Commercial — ship inside closed-source products |
| Protocol | Earlier Odin generation | Reverse-engineered from Odin3 v3.14.4 |
| Framework | .NET Framework 4.5.1 | .NET Framework 4.7.2 |
Android 15 / 16 super.img |
Known failures (#18) | Fixed |
| Secure-download auth (0x69) | Not included | Full implementation |
Mass D/L, Home Binary, .ock |
Not included | Included |
| GUI | Library only | WinForms Odin3 clone + CLI |
| Support | Community | Private licensing & support |
Choose this open-source library if you need basic flash / info / PIT on older targets and you are fine with GPL-3.0.
Choose SharpOdinClient Pro if you flash modern devices (Android 15/16), need secure-download authentication, Mass D/L, One Click / Home Binary workflows, or a commercial license for your own tool.
Contact for Pro licensing: Telegram @GsmCoder
- Requirements
- Features
- Quick start
- Find devices in download mode
- Read device info
- Read PIT from device
- Write PIT to device
- Flash firmware (tar / tar.md5)
- Flash a single file
- Events (Log & Progress)
- How it works
- Known limitations
- Related projects
- License
- Disclaimer
- Windows with the official Samsung USB driver installed.
- .NET Framework 4.5.1 or newer.
- Device connected in Download mode (Odin mode).
- Auto-detect Samsung devices in download mode (VID/PID / COM port).
- Read device information (
DVIF— model, CSC, firmware version, unique id, etc.). - Read PIT from the device.
- Write PIT (from
.pitor from atar/tar.md5that contains a PIT member). - Flash
tar,tar.md5packages (includinglz4,img,binmembers inside TAR). - Flash a single file to a named partition (e.g.
boot.img,sboot.bin). - Async API with
LogandProgressChangedevents. - Pure managed C# — no dependency on
SS_DL.dll.
using SharpOdinClient.structs;
using SharpOdinClient.util;private readonly Odin _odin = new Odin();
public MainWindow()
{
InitializeComponent();
_odin.Log += OnOdinLog;
_odin.ProgressChanged += OnOdinProgress;
}
private void OnOdinProgress(string filename, long max, long value, long writtenSize)
{
// filename: partition/file being flashed
// max: total size
// value / writtenSize: bytes written
}
private void OnOdinLog(string text, utils.MsgType color)
{
// text: log line
// color: message type for UI coloring
}var device = await _odin.FindDownloadModePort();
Console.WriteLine(device.Name); // device name
Console.WriteLine(device.COM); // COM port number
Console.WriteLine(device.VID); // USB VID
Console.WriteLine(device.PID); // USB PIDTo open the session on the found port:
if (await _odin.FindAndSetDownloadMode())
{
// ready for LOKE_Initialize / flash operations
}After FindAndSetDownloadMode():
var info = await _odin.DVIF();
await _odin.PrintInfo();Common keys in the info dictionary:
| Key | Meaning |
|---|---|
capa |
Capa number |
product |
Product id |
model |
Model number |
fwver |
Firmware version |
vendor |
Vendor |
sales |
Sales code |
ver |
Build number |
did |
DID number |
un |
Unique id |
tmu_temp |
TMU number |
prov |
Provision |
Most download-mode operations require IsOdin() and LOKE_Initialize first. Use totalfilesize = 0 when you are not flashing.
if (await _odin.FindAndSetDownloadMode())
{
await _odin.PrintInfo();
if (await _odin.IsOdin())
{
if (await _odin.LOKE_Initialize(0))
{
var pit = await _odin.Read_Pit();
if (pit.Result)
{
byte[] pitBytes = pit.data; // raw PIT file bytes
var entries = pit.Pit; // partition table entries
}
}
}
}Parameter pit can be:
- A standalone
.pitfile path, or - A
tar/tar.md5path that contains a PIT member (e.g. CSC package).
if (await _odin.FindAndSetDownloadMode())
{
await _odin.PrintInfo();
if (await _odin.IsOdin())
{
if (await _odin.LOKE_Initialize(0))
{
bool ok = (await _odin.Write_Pit("path\\to\\device.pit")).status;
}
}
}Build a List<FileFlash> from your BL / AP / CP / CSC (and optional) packages, then flash:
public async Task<bool> FlashFirmware(List<string> tarPaths)
{
var flashFiles = new List<FileFlash>();
foreach (var tarPath in tarPaths)
{
var members = _odin.tar.TarInformation(tarPath);
foreach (var member in members)
{
if (AlreadyAdded(member, flashFiles)) continue;
var ext = Path.GetExtension(member.Filename);
var file = new FileFlash
{
Enable = true,
FileName = member.Filename,
FilePath = tarPath
};
if (ext == ".pit")
{
// PIT inside package — handle repartition separately if needed
}
else if (ext == ".lz4")
{
file.RawSize = _odin.CalculateLz4SizeFromTar(tarPath, member.Filename);
}
else
{
file.RawSize = member.Filesize;
}
flashFiles.Add(file);
}
}
if (flashFiles.Count == 0) return false;
long totalSize = flashFiles.Sum(f => f.RawSize);
if (!await _odin.FindAndSetDownloadMode()) return false;
await _odin.PrintInfo();
if (!await _odin.IsOdin()) return false;
if (!await _odin.LOKE_Initialize(totalSize)) return false;
// Optional: repartition if PIT is inside the package
var pitInTar = flashFiles.Find(x => x.FileName.EndsWith(".pit", StringComparison.OrdinalIgnoreCase));
if (pitInTar != null)
{
// await _odin.Write_Pit(pitInTar.FilePath);
}
var readPit = await _odin.Read_Pit();
if (!readPit.Result) return false;
const int efsClear = 0;
const int bootUpdate = 1;
if (!await _odin.FlashFirmware(flashFiles, readPit.Pit, efsClear, bootUpdate, autoReboot: true))
return false;
return await _odin.PDAToNormal();
}Set FileFlash.Enable = false to skip a member without removing it from the list.
public async Task<bool> FlashSingleFile(string filePath, string partitionFileName)
{
var flashFile = new FileFlash
{
Enable = true,
FileName = partitionFileName, // e.g. "boot.img"
FilePath = filePath,
RawSize = new FileInfo(filePath).Length
};
if (!await _odin.FindAndSetDownloadMode()) return false;
await _odin.PrintInfo();
if (!await _odin.IsOdin()) return false;
if (!await _odin.LOKE_Initialize(flashFile.RawSize)) return false;
var readPit = await _odin.Read_Pit();
if (!readPit.Result) return false;
const int efsClear = 0;
const int bootUpdate = 0;
if (!await _odin.FlashSingleFile(flashFile, readPit.Pit, efsClear, bootUpdate, autoReboot: true))
return false;
return await _odin.PDAToNormal();
}| Event | Purpose |
|---|---|
Log |
Text log lines with MsgType for UI coloring |
ProgressChanged |
filename, max, value, writtenSize during flash |
- Install the Samsung USB driver.
- Boot the phone into Download mode and connect via USB.
- SharpOdinClient finds the COM port (
FindDownloadModePort/FindAndSetDownloadMode). - Handshake with the bootloader (
IsOdin,LOKE_Initialize). - Read PIT, then stream firmware over the serial protocol.
- Optionally reboot to normal mode (
PDAToNormal).
Communication is SerialPort-based — the same transport class used by the official Odin ecosystem on Windows.
This open-source library targets an earlier Odin protocol generation. On newer Samsung devices you may hit:
super.imgflash failures on Android 15 / 16 — see issue #18 (e.g. Galaxy A55, Galaxy S25).- No secure-download authentication (command 0x69) for protocol v4+ devices.
- No Mass D/L, Home Binary /
download-list.txt, or One Click (.ock) workflows. - No built-in GUI — you integrate the library into your own app.
For production use on modern devices, see SharpOdinClient Pro.
| Project | Description |
|---|---|
| SharpOdinClient Pro | Commercial Odin 3.14.4 C# source code (this library’s successor) |
| Freya | .NET Samsung flash tool built on SharpOdinClient |
| GSM Alphabet | Source code & protocol research |
GNU General Public License v3.0 — see License in this repository.
If you integrate SharpOdinClient into your project, GPL-3.0 obligations apply (including share-alike for distributed derivatives). For a commercial, closed-source license, use SharpOdinClient Pro instead.
- SharpOdinClient Pro / licensing: Telegram @GsmCoder
- Product page: alephgsm.com/2026/06/11/sharpodinclient-pro/
- Website: alephgsm.com
SharpOdinClient is intended for lawful development, research, maintenance and authorized service only. Flashing firmware can brick devices. Behavior depends on chipset, bootloader, firmware package, and security state. Use only on devices you own or are authorized to service, at your own risk.
Author: Alephgsm / GSM Alphabet