Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
GameTec-live authored Oct 2, 2023
2 parents 5697b9b + 42b7155 commit 100b4b9
Show file tree
Hide file tree
Showing 15 changed files with 185 additions and 25 deletions.
23 changes: 19 additions & 4 deletions .github/workflows/build_client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,47 @@ jobs:
pre_command: |
? .
bundle_command: |
Compress-Archive -Path software\* -DestinationPath client-windows.zip
Compress-Archive -Path software\dist\* -DestinationPath client-windows.zip
- name: linux
os: ubuntu-latest
pre_command: |
true
bundle_command: |
(cd software && zip -r "$OLDPWD/client-linux.zip" .)
(cd software/dist && zip -r "$OLDPWD/client-linux.zip" .)
- name: macos
os: macos-latest
pre_command: |
true
bundle_command: |
(cd software && zip -r "$OLDPWD/client-macos.zip" .)
(cd software/dist && zip -r "$OLDPWD/client-macos.zip" .)
runs-on: ${{ matrix.os }}
steps:
- name: Check out the repo
uses: actions/checkout@v3
with:
ref: ${{ inputs.checkout-sha == null && github.sha || inputs.checkout-sha }}
- name: Install PyInstaller and client dependencies
run: |
pip3 install pyinstaller
pip3 install -r software/script/requirements.txt
- name: Run OS specific setup
run: ${{ matrix.pre_command }}
- name: Compile native code
run: |
cd software/src
mkdir out
cd out
cmake ..
cmake --build . --config Release
- name: Run PyInstaller
run: |
cd software
pyinstaller pyinstaller.spec
- name: Upload built client
uses: actions/upload-artifact@v3
with:
name: client-${{ matrix.name }}
path: software/*
path: software/dist/*
- name: Zip up client for release
run: ${{ matrix.bundle_command }}
- name: Upload release artifacts
Expand Down
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...

## [unreleased][unreleased]
- Added GUI Page docs (@GameTec-live)
- Added GUI Page docs (@GameTec-live)
- Changed CLI threads polling into blocking reads, to reduce CPU usage (@doegox)
- Added support for timestamped comments in CLI via `rem`, `;`, `%` or `#` (@doegox)
- Fixed watchdog trigger during `hw factory_reset` (@doegox)
- Added PyInstaller support for CLI client (@augustozanellato)

## [v2.0.0][2023-09-26]
- Added `hw slot nick delete` and DELETE_SLOT_TAG_NICK (@doegox)
- Changed APP_FW_VER now deduced from git tag vx.y.z (@doegox)
- Changed initial button wakeup from 4 to 8 seconds (@aramova)
- Added MIFARE Ultralight reading features (@FlUxIuS & @doegox)
Expand Down
31 changes: 22 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,32 @@ Anywhere else: [Sneaktechnology](https://sneaktechnology.com) / [Aliexpress by R

Read the [available documentation](docs/README.md).

# Public Roadmap with reference to [Here](https://github.com/RfidResearchGroup/ChameleonUltra/wiki/Public-Roadmap)

Table for future functionality progress
---------------------------------

|No.|Functionality to achieve| Date | In Progress / Achieved ? | Contributors | RRG will reward |
|:--------------:|:--------------:|:--------:|:------------:|:------------:|:------------:|
|1| Adding DESfire Support|28/09/2023|:--------------:|:--------------:|:------------:|
|2| Adding Indala Emulation|28/09/2023|:--------------:|:--------------:|:------------:|
|3| Adding HID Prox 26 bit Emulation|28/09/2023|:--------------:|:--------------:|:------------:|
|4| Adding custom keys for t5577 read|28/09/2023|:------------:|:------------:|:------------:|
|5|:--------------:|:--------------:|:------------:|:------------:|:------------:|
|6|:--------------:|:--------------:|:------------:|:------------:|:------------:|
|7|:--------------:|:--------------:|:------------:|:------------:|:------------:|
|8|:--------------:|:--------------:|:------------:|:------------:|:------------:|
|9|:--------------:|:--------------:|:------------:|:------------:|:------------:|
|10|:--------------:|:--------------:|:------------:|:------------:|:------------:|
|11|:--------------:|:--------------:|:------------:|:------------:|:------------:|
|12|:--------------:|:--------------:|:------------:|:------------:|:------------:|
|13|:--------------:|:--------------:|:------------:|:------------:|:------------:|
|14|:--------------:|:--------------:|:------------:|:------------:|:------------:|

# Compatible applications

* [ChameleonUltraGUI](https://github.com/GameTec-live/ChameleonUltraGUI)

# Software Roadmap

|No.|Functionality to achieve| Date | Achieved ? | Contributors |
|:--------------:|:--------------:|:--------:|:------------:|:------------:|
|1| :--------------:|:--------------:|:--------------:|:--------------:|
|2| :--------------:|:--------------:|:--------------:|:--------------:|
|3| :--------------:|:--------------:|:--------------:|:--------------:|


# Videos

*Beware some of the instructions might have changed since recording, check the current documentation when in doubt!*
Expand Down
4 changes: 4 additions & 0 deletions docs/protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ Notes: the returned string is the output of `git describe --abbrev=7 --dirty --a
* Command: no data
* Response: no data. Status is `STATUS_DEVICE_SUCCESS` or `STATUS_FLASH_WRITE_FAIL`. The device will reboot shortly after this command.
* CLI: cf `hw factory_reset`
### 1021: DELETE_SLOT_TAG_NICK
* Command: 2 bytes. `slot_number|sense_type` with `slot_number` between 0 and 7 and `sense_type` according to `tag_sense_type_t` enum.
* Response: no data
* CLI: cf `hw slot nick delete`
### 1023: GET_ENABLED_SLOTS
* Command: no data
* Response: 16 bytes, 8*2 bool = `0x00` or `0x01`, 2 bytes for each slot from 0 to 7, as `enabled_hf|enabled_lf`
Expand Down
20 changes: 20 additions & 0 deletions firmware/application/src/app_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,25 @@ static data_frame_tx_t *cmd_processor_get_slot_tag_nick(uint16_t cmd, uint16_t s
return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, buffer[0], &buffer[1]);
}

static data_frame_tx_t *cmd_processor_delete_slot_tag_nick(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
if (length != 2) {
return data_frame_make(cmd, STATUS_PAR_ERR, 0, NULL);
}
uint8_t slot = data[0];
uint8_t sense_type = data[1];
fds_slot_record_map_t map_info;

if (slot >= TAG_MAX_SLOT_NUM || (sense_type != TAG_SENSE_HF && sense_type != TAG_SENSE_LF)) {
return data_frame_make(cmd, STATUS_PAR_ERR, 0, NULL);
}
get_fds_map_by_slot_sense_type_for_nick(slot, sense_type, &map_info);
bool ret = fds_delete_sync(map_info.id, map_info.key);
if (!ret) {
return data_frame_make(cmd, STATUS_FLASH_WRITE_FAIL, 0, NULL);
}
return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, 0, NULL);
}

static data_frame_tx_t *cmd_processor_mf1_get_emulator_config(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
uint8_t mf1_info[5] = {};
mf1_info[0] = nfc_tag_mf1_is_detection_enable();
Expand Down Expand Up @@ -965,6 +984,7 @@ static cmd_data_map_t m_data_cmd_map[] = {
{ DATA_CMD_GET_ACTIVE_SLOT, NULL, cmd_processor_get_active_slot, NULL },
{ DATA_CMD_GET_SLOT_INFO, NULL, cmd_processor_get_slot_info, NULL },
{ DATA_CMD_WIPE_FDS, NULL, cmd_processor_wipe_fds, NULL },
{ DATA_CMD_DELETE_SLOT_TAG_NICK, NULL, cmd_processor_delete_slot_tag_nick, NULL },
{ DATA_CMD_GET_ENABLED_SLOTS, NULL, cmd_processor_get_enabled_slots, NULL },
{ DATA_CMD_DELETE_SLOT_SENSE_TYPE, NULL, cmd_processor_delete_slot_sense_type, NULL },
{ DATA_CMD_GET_BATTERY_INFO, NULL, cmd_processor_get_battery_info, NULL },
Expand Down
1 change: 1 addition & 0 deletions firmware/application/src/data_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#define DATA_CMD_GET_ACTIVE_SLOT (1018)
#define DATA_CMD_GET_SLOT_INFO (1019)
#define DATA_CMD_WIPE_FDS (1020)
#define DATA_CMD_DELETE_SLOT_TAG_NICK (1021)

#define DATA_CMD_GET_ENABLED_SLOTS (1023)
#define DATA_CMD_DELETE_SLOT_SENSE_TYPE (1024)
Expand Down
2 changes: 1 addition & 1 deletion firmware/application/src/rfid/nfctag/tag_emulation.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ static tag_slot_config_t slotConfig ALIGN_U32 = {
.slots = {
{ .enabled_hf = true, .enabled_lf = true, .tag_hf = TAG_TYPE_MIFARE_1024, .tag_lf = TAG_TYPE_EM410X, }, // 1
{ .enabled_hf = true, .enabled_lf = false, .tag_hf = TAG_TYPE_MIFARE_1024, .tag_lf = TAG_TYPE_UNDEFINED, }, // 2
{ .enabled_hf = true, .enabled_lf = true, .tag_hf = TAG_TYPE_UNDEFINED, .tag_lf = TAG_TYPE_EM410X, }, // 3
{ .enabled_hf = false, .enabled_lf = true, .tag_hf = TAG_TYPE_UNDEFINED, .tag_lf = TAG_TYPE_EM410X, }, // 3
{ .enabled_hf = false, .enabled_lf = false, .tag_hf = TAG_TYPE_UNDEFINED, .tag_lf = TAG_TYPE_UNDEFINED, }, // 4
{ .enabled_hf = false, .enabled_lf = false, .tag_hf = TAG_TYPE_UNDEFINED, .tag_lf = TAG_TYPE_UNDEFINED, }, // 5
{ .enabled_hf = false, .enabled_lf = false, .tag_hf = TAG_TYPE_UNDEFINED, .tag_lf = TAG_TYPE_UNDEFINED, }, // 6
Expand Down
6 changes: 4 additions & 2 deletions firmware/application/src/utils/fds_util.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "fds_util.h"

#include "bsp_wdt.h"

#define NRF_LOG_MODULE_NAME fds_sync
#include "nrf_log.h"
Expand Down Expand Up @@ -306,7 +306,9 @@ static bool fds_next_record_delete_sync() {

bool fds_wipe(void) {
NRF_LOG_INFO("Full fds wipe requested");
while (fds_next_record_delete_sync()) {}
while (fds_next_record_delete_sync()) {
bsp_wdt_feed();
}
fds_gc_sync();
return true;
}
3 changes: 3 additions & 0 deletions software/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ script/__pycache__
src/out
# Ignore the compiled scripts
script/*.pyc
# Ignore pyinstaller folders
build/
dist/
46 changes: 46 additions & 0 deletions software/pyinstaller.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# -*- mode: python ; coding: utf-8 -*-


block_cipher = None


a = Analysis(
['script/chameleon_cli_main.py'],
pathex=[],
binaries=[
("bin/*", "bin/"),
],
datas=[],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='chameleon_cli_main',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
13 changes: 13 additions & 0 deletions software/script/chameleon_cli_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import os
import pathlib
import prompt_toolkit
from datetime import datetime
from prompt_toolkit.formatted_text import ANSI
from prompt_toolkit.history import FileHistory

Expand Down Expand Up @@ -127,6 +128,18 @@ def startCLI(self):
# parse cmd
argv = cmd_str.split()
root_cmd = argv[0]
# look for comments
if root_cmd == "rem" or root_cmd[0] in ";#%":
# precision: second
# iso_timestamp = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
# precision: nanosecond (note that the comment will take some time too, ~75ns, check your system)
iso_timestamp = datetime.utcnow().isoformat() + 'Z'
if root_cmd[0] in ";#%":
comment = ' '.join([root_cmd[1:]]+argv[1:]).strip()
else:
comment = ' '.join(argv[1:]).strip()
print(f"{iso_timestamp} remark: {comment}")
continue
if root_cmd not in chameleon_cli_unit.root_commands:
# No matching command group
print("".ljust(18, "-") + "".ljust(10) + "".ljust(30, "-"))
Expand Down
25 changes: 24 additions & 1 deletion software/script/chameleon_cli_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import serial.tools.list_ports
import threading
import struct
from pathlib import Path
from platform import uname

import chameleon_com
Expand Down Expand Up @@ -38,6 +39,12 @@
0x38: "SmartMX with MIFARE Classic 4K",
}

if getattr(sys, 'frozen', False):
# in pyinstaller
default_cwd = str(Path(sys._MEIPASS) / "bin")
else:
# from source
default_cwd = str(Path(__file__).parent.parent / "bin")

class BaseCLIUnit:

Expand Down Expand Up @@ -81,7 +88,7 @@ def on_exec(self, args: argparse.Namespace):
raise NotImplementedError("Please implement this")

@staticmethod
def sub_process(cmd, cwd=os.path.abspath("bin/")):
def sub_process(cmd, cwd=default_cwd):
class ShadowProcess:
def __init__(self):
self.output = ""
Expand Down Expand Up @@ -1385,6 +1392,22 @@ def on_exec(self, args: argparse.Namespace):
print(f' - Get tag nick name for slot {slot_num}: {res.decode(encoding="utf8")}')


@hw_slot_nick.command('delete', 'Delete tag nick name for slot')
class HWSlotNickGet(SlotIndexRequireUnit, SenseTypeRequireUnit):
def args_parser(self) -> ArgumentParserNoExit or None:
parser = ArgumentParserNoExit()
self.add_slot_args(parser)
self.add_sense_type_args(parser)
return parser

# hw slot nick delete -s 1 -st 1
def on_exec(self, args: argparse.Namespace):
slot_num = args.slot
sense_type = args.sense_type
res = self.cmd.delete_slot_tag_nick(slot_num, sense_type)
print(f' - Delete tag nick name for slot {slot_num}: {res.decode(encoding="utf8")}')


@hw_slot.command('update', 'Update config & data to device flash')
class HWSlotUpdate(DeviceRequiredUnit):
def args_parser(self) -> ArgumentParserNoExit or None:
Expand Down
14 changes: 14 additions & 0 deletions software/script/chameleon_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@

DATA_CMD_WIPE_FDS = 1020

DATA_CMD_DELETE_SLOT_TAG_NICK = 1021

DATA_CMD_GET_ENABLED_SLOTS = 1023
DATA_CMD_DELETE_SLOT_SENSE_TYPE = 1024

Expand Down Expand Up @@ -912,6 +914,18 @@ def get_slot_tag_nick(self, slot: SlotNumber, sense_type: TagSenseType):
data = struct.pack('!BB', SlotNumber.to_fw(slot), sense_type)
return self.device.send_cmd_sync(DATA_CMD_GET_SLOT_TAG_NICK, data)

@expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS)
def delete_slot_tag_nick(self, slot: SlotNumber, sense_type: TagSenseType):
"""
Delete the nick name of the slot
:param slot: Card slot number
:param sense_type: field type
:return:
"""
# SlotNumber() will raise error for us if slot not in slot range
data = struct.pack('!BB', SlotNumber.to_fw(slot), sense_type)
return self.device.send_cmd_sync(DATA_CMD_DELETE_SLOT_TAG_NICK, data)

@expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS)
def mf1_get_emulator_config(self):
"""
Expand Down
Loading

0 comments on commit 100b4b9

Please sign in to comment.