{"id":50864170,"url":"https://github.com/danusha2345/xgecu-t48-reverse","last_synced_at":"2026-06-14T23:34:10.171Z","repository":{"id":360905800,"uuid":"1252117319","full_name":"danusha2345/xgecu-t48-reverse","owner":"danusha2345","description":"Reverse-engineered USB protocol notes and Python prototype for the XGecu T48 universal programmer, focused on eMMC (ISP) operations.","archived":false,"fork":false,"pushed_at":"2026-06-06T18:01:50.000Z","size":595,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-14T23:34:06.265Z","etag":null,"topics":["chip-programmer","emmc","reverse-engineering","t48","tl866","usb-protocol","xgecu"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/danusha2345.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"custom":"https://boosty.to/danusha/donate"}},"created_at":"2026-05-28T07:51:40.000Z","updated_at":"2026-06-10T09:42:10.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/danusha2345/xgecu-t48-reverse","commit_stats":null,"previous_names":["danusha2345/xgecu-t48-reverse"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/danusha2345/xgecu-t48-reverse","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danusha2345%2Fxgecu-t48-reverse","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danusha2345%2Fxgecu-t48-reverse/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danusha2345%2Fxgecu-t48-reverse/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danusha2345%2Fxgecu-t48-reverse/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danusha2345","download_url":"https://codeload.github.com/danusha2345/xgecu-t48-reverse/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danusha2345%2Fxgecu-t48-reverse/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34342089,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-14T02:00:07.365Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chip-programmer","emmc","reverse-engineering","t48","tl866","usb-protocol","xgecu"],"created_at":"2026-06-14T23:34:09.097Z","updated_at":"2026-06-14T23:34:10.153Z","avatar_url":"https://github.com/danusha2345.png","language":"Python","funding_links":["https://boosty.to/danusha/donate"],"categories":[],"sub_categories":[],"readme":"[![Boosty](https://img.shields.io/badge/Boosty-Buy_me_a_coffee-FF7143?logo=boosty\u0026logoColor=white\u0026style=for-the-badge)](https://boosty.to/danusha/donate)\n\n\u003e 🇷🇺 На русском: [README.ru.md](README.ru.md)\n\n# xgecu-t48-reverse\n\nReverse-engineered USB protocol notes and a working Python tool for\ntalking to the **XGecu T48 (TL866-3G)** universal programmer, with a\nfocus on **eMMC** read/write operations (including in-circuit / ISP).\n\nThe XGecu T48 is a popular universal chip programmer; its first-party\nsoftware (`Xgpro`) is Windows-only and the device's USB protocol is\nundocumented. The open-source [`minipro`](https://gitlab.com/DavidGriffith/minipro)\nproject covers the classic-chip part of the protocol but explicitly does\n**not** implement eMMC. This repository documents the eMMC extension of\nthe protocol — what the wire-format actually looks like — and ships a\nworking Python tool that uses the same encoding to read and write an\neMMC in-circuit from Linux.\n\n\u003e **Status: working on real hardware.** The protocol was first extracted\n\u003e from static analysis of `Xgpro.exe` (PE32, WinUSB), then validated\n\u003e against live USB captures from an actual T48 + the XGecu eMMC-ISP\n\u003e adapter on a real eMMC. Arbitrary in-circuit **read and write are\n\u003e hardware-verified** (1-bit, 3.3 V): `examples/t48_emmc_isp.py` reads\n\u003e and writes arbitrary regions, switches partitions (USER / BOOT1 /\n\u003e BOOT2 / RPMB), parses the partition table, and round-trips boot\n\u003e sectors. VCCQ **1.8 V** is implemented from a static reverse of\n\u003e `Xgpro.exe` (`BEGIN[0x15]`) but is **not yet hardware-verified** —\n\u003e only use it on a chip you know is 1.8 V. A handful of rarely-used\n\u003e classic opcodes remain TBD (noted inline in `PROTOCOL.md`).\n\n## What's in here\n\n- [`docs/PROTOCOL.md`](docs/PROTOCOL.md) — the full reverse-engineering\n  write-up: USB identity (`a466:0a53`, WinUSB), endpoint roles\n  (EP1 OUT/IN command + EP2 OUT bulk), the top-opcode / sub-opcode\n  hierarchy, eMMC command table, init flow, RPMB frame layout, the\n  `.alg` algorithm-file format, and the bulk transfer formats.\n- [`docs/ISP_SETTINGS.md`](docs/ISP_SETTINGS.md) — a plain-language\n  reference for the Xgpro **eMMC ISP settings** (bus width, VCCQ,\n  `ICSP_VCC Enable`, CLK, `Vcc current Imax`, partitions, RST_n wiring):\n  what each does and what to enable / disable, cross-checked against the\n  wire captures. Russian: [`ISP_SETTINGS.ru.md`](docs/ISP_SETTINGS.ru.md).\n- [`examples/t48_emmc_isp.py`](examples/t48_emmc_isp.py) — **the working\n  in-circuit eMMC tool.** Reads and writes arbitrary regions over the\n  XGecu eMMC-ISP adapter by replaying the captured protocol parameterised\n  by block address. Hardware-verified at 1-bit / 3.3 V. Supports\n  partition selection (`USER` / `BOOT1` / `BOOT2` / `RPMB`), erase,\n  partition-table / filesystem-magic parsing, a boot-sector round-trip\n  self-test, and VCCQ `--voltage {3.3,1.8}`. Modes: read-only validation\n  (default, non-destructive), `--write-test`, `--partitions`,\n  `--boot-roundtrip`. Includes anti-wedge teardown/recovery so a timeout\n  no longer requires a physical replug.\n- [`examples/t48_emmc.py`](examples/t48_emmc.py) — the lower-level\n  transport the ISP tool builds on: connect to the T48 by VID:PID, build\n  the documented packets, and call them through high-level methods\n  (`switch_partition`, `read_ecsd`, `bulk_read`, RPMB frame builder,\n  etc.). Has an offline sanity test that verifies the three decoded\n  CMD6 SWITCH arguments match the bytes seen in `Xgpro.exe`. Every USB\n  transfer can be logged to a file (`T48Emmc(log_path=…)`) so a real\n  session becomes ground truth for the protocol doc.\n- [`examples/first_contact.py`](examples/first_contact.py) — a\n  **zero-risk** first-session probe to run the moment a T48 is plugged\n  in: `connect → identify → measure voltages → status → read pins`. It\n  applies **no programming voltage**, needs **no chip** and **no\n  eMMC-ISP adapter**, and logs every transfer. The safe way to validate\n  the transport and the classic opcodes before touching a chip.\n- [`tools/extract_alg.py`](tools/extract_alg.py) — standalone unpacker\n  for the proprietary `.alg` files that ship with `Xgpro`. Each `.alg`\n  contains a zero-RLE-compressed Xilinx Spartan-6 FPGA bitstream\n  (340 604 bytes uncompressed) with a 32-bit CRC. No `.alg` files\n  themselves are included — bring your own from a legitimate Xgpro\n  install.\n\n## Quick look at the protocol\n\nA `Xgpro` USB command on EP1 OUT starts with a 1-byte top-opcode. The\nones in the classic range (`0x02..0x3F`) are already implemented by\n`minipro`. The eMMC extension adds these top-opcodes:\n\n| Top-opcode | Purpose                                              |\n|------------|------------------------------------------------------|\n| `0x08`     | Long-recv envelope (e.g. sub-op `0x48` → read 512 B) |\n| `0x14`     | Bulk-write setup before N × 512 B on EP2 OUT         |\n| `0x21`     | eMMC init / algorithm select                         |\n| `0x27`     | eMMC sub-command dispatcher (sub-op in byte 1)       |\n\nFor `0x27`-class commands the layout is 8 bytes:\n`[0x27][sub-op][u16 = 0][u32 arg LE]`. Among the sub-ops the **CMD6\nSWITCH** encoding is the most informative: the 32-bit `arg` is exactly\nthe JEDEC eMMC CMD6 argument in big-endian, so e.g.\n\n```\nSWITCH PARTITION_CONFIG → RPMB     →  arg = 0x01B30300\nSWITCH HS_TIMING        → HS-200   →  arg = 0x01AF0100\nrestore PARTITION_ACCESS → USER    →  arg = 0x02B30700  (CLEAR_BITS of 0x07)\n```\n\nSee `docs/PROTOCOL.md` §7 for the full table.\n\n## Offline sanity test\n\n```bash\npip install pyusb\npython3 examples/t48_emmc.py\n```\n\nThis runs the byte-level sanity test without touching any hardware:\n\n```\n== Проверка структур пакетов (offline) ==\n  cmd_A(SWITCH→RPMB)        = 274600000003b301\n  cmd_A(SWITCH→USER restore)= 274600000007b302\n  cmd_A(SWITCH→HS200)       = 274600000001af01\n  ...\n[OK] Все три расшифрованные команды сходятся с реверсом Xgpro.exe.\n```\n\nWith a T48 plugged in, `python3 examples/t48_emmc.py --connect` will\nattempt to open the device via libusb. On Linux you may need a udev\nrule to grant your user access to the device interface; on Windows the\nofficial WinUSB driver from XGecu is fine.\n\nFor the **first** run on a fresh device, prefer the safe probe — it\napplies no voltage, needs no chip, and saves a full transfer trace:\n\n```bash\npython3 examples/first_contact.py          # → t48_first_contact.log\n```\n\n## Read/write an eMMC in-circuit\n\nWith the XGecu eMMC-ISP adapter wired to a target eMMC, the ISP tool\nreads and writes arbitrary regions. The default mode is non-destructive\n(handshake + init, print CID, read one 16 KB chunk and hexdump it):\n\n```bash\npython3 examples/t48_emmc_isp.py                  # read-only @ block 0x8000\npython3 examples/t48_emmc_isp.py --block 0x100000 # read-only @ another block\npython3 examples/t48_emmc_isp.py --partitions     # parse the partition table\npython3 examples/t48_emmc_isp.py --boot-roundtrip # read boot sectors, write them back, verify\npython3 examples/t48_emmc_isp.py --write-test 0x8000   # write marker + read-back verify (DESTRUCTIVE)\npython3 examples/t48_emmc_isp.py --voltage 1.8    # 1.8 V VCCQ (UNVERIFIED — use only on a known 1.8 V chip)\n```\n\nSee [`docs/ISP_SETTINGS.md`](docs/ISP_SETTINGS.md) for what the Xgpro\nsettings (bus width, VCCQ, CLK, partitions, RST_n wiring) mean and a\nstable starting point, and `docs/PROTOCOL.md` §33–§35 for the wire-level\nbreakdown of the ISP read/write flow.\n\n## Unpacking a `.alg` (optional)\n\nIf you want to look at the FPGA bitstream that ships with `Xgpro` for a\ngiven chip family, the unpacker writes the raw 340604-byte payload:\n\n```bash\npython3 tools/extract_alg.py path/to/Xgpro/algorithm/EMMC_41_18.alg\n# → EMMC_41_18.bit  (340604 bytes, with 16-byte 0xFF preamble + FPGA sync)\n```\n\n## What's *not* here\n\nPer the project's purpose this repository contains only original\nmaterial — the reverse-engineering write-up and our own code that\n*talks the documented protocol*. It deliberately does **not** ship:\n\n- any binary from XGecu (`Xgpro.exe`, drivers, firmware updates)\n- any `.alg` algorithm files\n- the chip database (`InfoIC2Plus.dll` dump)\n- decompressed FPGA bitstreams\n\nThose are XGecu's copyrighted material. The `Xgpro` software is\navailable for free from the manufacturer (https://www.xgecu.com/), and\nthe `dumpic` tool in `minipro` produces the chip-database dump locally\nfrom a legitimate install.\n\n## Why this exists\n\nThe intended consumer of this material is a separate eMMC-reader\napplication that already supports other USB-eMMC backends and wants to\nadd the T48 as one more backend on Windows and Linux. Documenting the\nprotocol publicly is also useful for anyone running the T48 from Linux\nwho wants something more programmable than running `Xgpro` under Wine.\n\nThis work piggybacks on the excellent [`minipro`](https://gitlab.com/DavidGriffith/minipro)\n(GPL-3.0) — it already implements the shared T48 transport (opcodes\n`0x02..0x3F`, USB handshake, voltage / clock control) — and on\n[`radiomanV/TL866`](https://github.com/radiomanV/TL866) for the firmware\nside of the device family.\n\n## License\n\n[MIT](LICENSE). Reverse engineering for the purpose of interoperability\nbetween independently-developed software and the hardware its owner\npurchased.\n\n---\n\n[![Boosty](https://img.shields.io/badge/Boosty-Buy_me_a_coffee-FF7143?logo=boosty\u0026logoColor=white\u0026style=for-the-badge)](https://boosty.to/danusha/donate)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanusha2345%2Fxgecu-t48-reverse","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanusha2345%2Fxgecu-t48-reverse","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanusha2345%2Fxgecu-t48-reverse/lists"}