Add files via upload
This commit is contained in:
parent
01b48f921b
commit
9810b51c13
119
Arduino-Chunithm-Reader.ino
Normal file
119
Arduino-Chunithm-Reader.ino
Normal file
@ -0,0 +1,119 @@
|
||||
#include "cmd.h"
|
||||
|
||||
void SerialCheck() {
|
||||
switch (packet_read()) {
|
||||
case SG_NFC_CMD_RESET:
|
||||
sg_nfc_cmd_reset();
|
||||
break;
|
||||
case SG_NFC_CMD_GET_FW_VERSION:
|
||||
sg_nfc_cmd_get_fw_version();
|
||||
break;
|
||||
case SG_NFC_CMD_GET_HW_VERSION:
|
||||
sg_nfc_cmd_get_hw_version();
|
||||
break;
|
||||
case SG_NFC_CMD_POLL:
|
||||
sg_nfc_cmd_poll();
|
||||
break;
|
||||
case SG_NFC_CMD_MIFARE_READ_BLOCK:
|
||||
sg_nfc_cmd_mifare_read_block();
|
||||
break;
|
||||
case SG_NFC_CMD_FELICA_ENCAP:
|
||||
sg_nfc_cmd_felica_encap();
|
||||
break;
|
||||
case SG_NFC_CMD_MIFARE_AUTHENTICATE:
|
||||
sg_res_init();
|
||||
break;
|
||||
case SG_NFC_CMD_MIFARE_SELECT_TAG:
|
||||
sg_res_init();
|
||||
break;
|
||||
case SG_NFC_CMD_MIFARE_SET_KEY_AIME:
|
||||
sg_nfc_cmd_mifare_set_key_aime();
|
||||
break;
|
||||
case SG_NFC_CMD_MIFARE_SET_KEY_BANA:
|
||||
sg_res_init();
|
||||
break;
|
||||
case SG_NFC_CMD_RADIO_ON:
|
||||
sg_nfc_cmd_radio_on();
|
||||
break;
|
||||
case SG_NFC_CMD_RADIO_OFF:
|
||||
sg_nfc_cmd_radio_off();
|
||||
break;
|
||||
case SG_RGB_CMD_RESET:
|
||||
sg_led_cmd_reset();
|
||||
break;
|
||||
case SG_RGB_CMD_GET_INFO:
|
||||
sg_led_cmd_get_info();
|
||||
break;
|
||||
case SG_RGB_CMD_SET_COLOR:
|
||||
sg_led_cmd_set_color();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
SerialUSB.begin(38400);
|
||||
SerialUSB.setTimeout(0);
|
||||
FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
|
||||
nfc.begin();
|
||||
nfc.SAMConfig();
|
||||
memset(&req, 0, sizeof(req.bytes));
|
||||
memset(&res, 0, sizeof(res.bytes));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
SerialCheck();
|
||||
packet_write();
|
||||
}
|
||||
|
||||
static uint8_t packet_read() {
|
||||
uint8_t len, r, checksum;
|
||||
bool escape = false;
|
||||
while (SerialUSB.available()) {
|
||||
r = SerialUSB.read();
|
||||
if (r == 0xE0) {
|
||||
req.frame_len = 0xFF;
|
||||
continue;
|
||||
}
|
||||
if (req.frame_len == 0xFF) {
|
||||
req.frame_len = r;
|
||||
len = 1;
|
||||
checksum = r;
|
||||
continue;
|
||||
}
|
||||
if (r == 0xD0) {
|
||||
escape = true;
|
||||
continue;
|
||||
}
|
||||
if (escape) {
|
||||
r++;
|
||||
escape = false;
|
||||
}
|
||||
if (len == req.frame_len && checksum == r) {
|
||||
return req.cmd;
|
||||
}
|
||||
req.bytes[len++] = r;
|
||||
checksum += r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void packet_write() {
|
||||
if (res.cmd == 0)
|
||||
return;
|
||||
uint8_t checksum = 0;
|
||||
SerialUSB.write(0xE0);
|
||||
for (uint8_t i = 0; i < res.frame_len; i++) {
|
||||
uint8_t w = res.bytes[i];
|
||||
checksum += w;
|
||||
if (SerialUSB.availableForWrite() < 2)
|
||||
return;
|
||||
if (w == 0xE0 || w == 0xD0) {
|
||||
SerialUSB.write(0xD0);
|
||||
SerialUSB.write(--w);
|
||||
} else {
|
||||
SerialUSB.write(w);
|
||||
}
|
||||
}
|
||||
SerialUSB.write(checksum);
|
||||
res.cmd = 0;
|
||||
}
|
14
card.txt
Normal file
14
card.txt
Normal file
@ -0,0 +1,14 @@
|
||||
E0 [05] 00 [7D] [42] 00 [C4] //读卡
|
||||
E0 [19] 00 [7D] [42] 00 13 01 20 10 [ 8 byte IDm ] [ 8 byte PMm ] [ ]
|
||||
|
||||
|
||||
E0 [13] 00 [80] [71] 0E [ 8 byte IDm ] 06 [00] FF FF 01 0F [ ]
|
||||
E0 [1A] 00 [80] [71] 00 [14] 14 01 [ 8 byte IDm ] [ 8 byte PMm ] 00 00 [ ]
|
||||
|
||||
|
||||
E0 [17] 00 [81] [71] 12 [ 8 byte IDm ] 0A [0C] [ 8 byte IDm ] [ ]
|
||||
E0 [13] 00 [81] [71] 00 [0D] 0D 0D [ 8 byte IDm ] 01 00 00 [ ]
|
||||
|
||||
|
||||
E0 [18] 00 [82] [71] 13 [ 8 byte IDm ] 0B [A4] [ 8 byte IDm ] 00 [ ]
|
||||
E0 [11] 00 [82] [71] 00 [0B] 0B A5 [ 8 byte IDm ] 00 [ ]
|
BIN
chunihook.dll
Normal file
BIN
chunihook.dll
Normal file
Binary file not shown.
239
cmd.h
Normal file
239
cmd.h
Normal file
@ -0,0 +1,239 @@
|
||||
#include "FastLED.h"
|
||||
#define NUM_LEDS 6
|
||||
#define DATA_PIN A3
|
||||
#define BRI 50
|
||||
CRGB leds[NUM_LEDS];
|
||||
|
||||
#include "Adafruit_PN532.h"
|
||||
#define PN532_IRQ (4)
|
||||
Adafruit_PN532 nfc(PN532_IRQ, 16);
|
||||
boolean readerDisabled = false;
|
||||
|
||||
uint8_t AimeKey[6];
|
||||
uint8_t MifareKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
|
||||
enum {
|
||||
SG_NFC_CMD_GET_FW_VERSION = 0x30,//获取FW版本
|
||||
SG_NFC_CMD_GET_HW_VERSION = 0x32,//获取HW版本
|
||||
SG_NFC_CMD_RADIO_ON = 0x40,//打开读卡器天线
|
||||
SG_NFC_CMD_RADIO_OFF = 0x41,//关闭读卡器天线
|
||||
SG_NFC_CMD_POLL = 0x42,//发送卡号
|
||||
SG_NFC_CMD_MIFARE_SELECT_TAG = 0x43,
|
||||
SG_NFC_CMD_MIFARE_SET_KEY_BANA = 0x50,
|
||||
SG_NFC_CMD_MIFARE_READ_BLOCK = 0x52,
|
||||
SG_NFC_CMD_MIFARE_SET_KEY_AIME = 0x54,
|
||||
SG_NFC_CMD_MIFARE_AUTHENTICATE = 0x55,
|
||||
SG_NFC_CMD_RESET = 0x62,//重置读卡器
|
||||
SG_NFC_CMD_FELICA_ENCAP = 0x71,
|
||||
SG_RGB_CMD_SET_COLOR = 0x81,//LED颜色设置
|
||||
SG_RGB_CMD_RESET = 0xF5,//LED重置
|
||||
SG_RGB_CMD_GET_INFO = 0xF0,//LED信息获取
|
||||
FELICA_CMD_POLL = 0x00,//ENCAP用
|
||||
FELICA_CMD_GET_SYSTEM_CODE = 0x0c,
|
||||
FELICA_CMD_NDA_A4 = 0xa4,
|
||||
};
|
||||
|
||||
typedef union packet_req {
|
||||
uint8_t bytes[256];
|
||||
struct {
|
||||
uint8_t frame_len;
|
||||
uint8_t addr;
|
||||
uint8_t seq_no;
|
||||
uint8_t cmd;
|
||||
uint8_t payload_len;
|
||||
union {
|
||||
uint8_t key[6];// sg_nfc_req_mifare_set_key
|
||||
struct {// sg_nfc_cmd_mifare_read_block
|
||||
uint8_t uid[4];
|
||||
uint8_t block_no;
|
||||
};
|
||||
struct {// sg_nfc_req_felica_encap
|
||||
uint8_t IDm[8];
|
||||
uint8_t encap_len;
|
||||
uint8_t code;
|
||||
uint8_t felica_payload[241];
|
||||
};
|
||||
uint8_t color_payload[3];//sg_led_req_set_color
|
||||
};
|
||||
};
|
||||
|
||||
} packet_req_t;
|
||||
|
||||
typedef union packet_res {
|
||||
uint8_t bytes[256];
|
||||
struct {
|
||||
uint8_t frame_len;
|
||||
uint8_t addr;
|
||||
uint8_t seq_no;
|
||||
uint8_t cmd;
|
||||
uint8_t status;
|
||||
uint8_t payload_len;
|
||||
union {
|
||||
char version[23];// sg_nfc_res_get_fw_version,sg_nfc_res_get_hw_version
|
||||
struct {// sg_nfc_res_poll
|
||||
uint8_t count;
|
||||
uint8_t type;
|
||||
uint8_t id_len;
|
||||
union {
|
||||
uint8_t uid[4];
|
||||
uint8_t IDPM[16];
|
||||
};
|
||||
};
|
||||
uint8_t block[16];// sg_nfc_res_mifare_read_block
|
||||
struct {// sg_nfc_res_felica_encap
|
||||
uint8_t encap_len;
|
||||
uint8_t code;
|
||||
uint8_t IDm[8];
|
||||
union {
|
||||
struct {
|
||||
uint8_t PMm[8];
|
||||
uint8_t system_code[2];
|
||||
};
|
||||
uint8_t felica_payload[241];
|
||||
};
|
||||
};
|
||||
uint8_t reset_payload; //sg_led_res_reset
|
||||
uint8_t info_payload[9]; //sg_led_res_get_info
|
||||
};
|
||||
};
|
||||
} packet_res_t;
|
||||
|
||||
static packet_req_t req;
|
||||
static packet_res_t res;
|
||||
|
||||
static void sg_res_init(uint8_t payload_len = 0) { //初始化模板
|
||||
res.frame_len = 6 + payload_len;
|
||||
res.addr = req.addr;
|
||||
res.seq_no = req.seq_no;
|
||||
res.cmd = req.cmd;
|
||||
res.status = 0;
|
||||
res.payload_len = payload_len;
|
||||
}
|
||||
|
||||
static void sg_nfc_cmd_reset() {//重置读卡器
|
||||
sg_res_init();
|
||||
res.status = 3;
|
||||
readerDisabled = true;
|
||||
}
|
||||
|
||||
static void sg_nfc_cmd_get_fw_version() {
|
||||
sg_res_init(sizeof(res.version));
|
||||
memcpy(res.version, "TN32MSEC003S F/W Ver1.2E", sizeof(res.version));
|
||||
}
|
||||
|
||||
static void sg_nfc_cmd_get_hw_version() {
|
||||
sg_res_init(sizeof(res.version));
|
||||
memcpy(res.version, "TN32MSEC003S H/W Ver3.0J", sizeof(res.version));
|
||||
}
|
||||
|
||||
static void sg_nfc_cmd_mifare_set_key_aime() {
|
||||
sg_res_init();
|
||||
memcpy(req.key, AimeKey, sizeof(AimeKey));
|
||||
}
|
||||
|
||||
static void sg_led_cmd_reset() {
|
||||
sg_res_init(sizeof(res.reset_payload));
|
||||
res.reset_payload = 0;
|
||||
fill_solid(leds, NUM_LEDS, 0x000000);
|
||||
FastLED[0].show(leds, NUM_LEDS, BRI);
|
||||
}
|
||||
|
||||
static void sg_led_cmd_get_info() {
|
||||
sg_res_init(sizeof(res.info_payload));
|
||||
static uint8_t info[] = {'1', '5', '0', '8', '4', 0xFF, 0x10, 0x00, 0x12};
|
||||
memcpy(res.info_payload, info, 9);
|
||||
}
|
||||
|
||||
static void sg_led_cmd_set_color() {
|
||||
uint8_t r = req.color_payload[0];
|
||||
uint8_t g = req.color_payload[1];
|
||||
uint8_t b = req.color_payload[2];
|
||||
fill_solid(leds, NUM_LEDS, CRGB(r, g, b));
|
||||
FastLED[0].show(leds, NUM_LEDS, BRI);
|
||||
}
|
||||
|
||||
static void sg_nfc_cmd_radio_on() {
|
||||
sg_res_init();
|
||||
if (!readerDisabled) {
|
||||
return;
|
||||
}
|
||||
nfc.startPassiveTargetIDDetection(PN532_MIFARE_ISO14443A);
|
||||
readerDisabled = false;
|
||||
}
|
||||
|
||||
static void sg_nfc_cmd_radio_off() {
|
||||
sg_res_init();
|
||||
readerDisabled = true;
|
||||
}
|
||||
|
||||
static void sg_nfc_cmd_poll() { //卡号发送
|
||||
uint8_t uid[4];
|
||||
uint8_t t;
|
||||
//读aime(实验性)
|
||||
nfc.startPassiveTargetIDDetection(PN532_MIFARE_ISO14443A);
|
||||
delay(10);
|
||||
if (!digitalRead(PN532_IRQ)) {
|
||||
nfc.readDetectedPassiveTargetID(uid, &t);
|
||||
if (nfc.mifareclassic_AuthenticateBlock(uid, t, 1, MIFARE_CMD_AUTH_B, AimeKey)) { //aime
|
||||
res.type = 0x10;
|
||||
res.id_len = t;
|
||||
memcpy(res.uid, uid, t);//默认ID为0x01020304
|
||||
sg_res_init(7);
|
||||
res.count = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
//读普通mifare当作felica
|
||||
nfc.startPassiveTargetIDDetection(PN532_MIFARE_ISO14443A);
|
||||
delay(10);
|
||||
if (!digitalRead(PN532_IRQ)) {
|
||||
nfc.readDetectedPassiveTargetID(uid, &t);
|
||||
if (nfc.mifareclassic_AuthenticateBlock(uid, t, 1, MIFARE_CMD_AUTH_A, MifareKey)) {
|
||||
if (nfc.mifareclassic_ReadDataBlock(1, res.IDPM)) {//此处略过了IDm和PMm的分别读取
|
||||
res.type = 0x20;
|
||||
res.id_len = sizeof(res.IDPM);
|
||||
sg_res_init(19);//count,type,id_len,IDm,PMm
|
||||
res.count = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
sg_res_init(1);
|
||||
res.count = 0;
|
||||
}
|
||||
|
||||
static void sg_nfc_cmd_mifare_read_block() {
|
||||
if (req.block_no > 3)
|
||||
return;
|
||||
sg_res_init(sizeof(res.block));
|
||||
if (nfc.mifareclassic_AuthenticateBlock(req.uid, 4, req.block_no, MIFARE_CMD_AUTH_B, AimeKey)) {
|
||||
if (nfc.mifareclassic_ReadDataBlock(req.block_no, res.block)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
sg_res_init();
|
||||
}
|
||||
|
||||
static void sg_nfc_cmd_felica_encap() {
|
||||
uint8_t code = req.code;
|
||||
res.code = code + 1;
|
||||
memcpy(res.IDm, req.IDm, sizeof(req.IDm));
|
||||
switch (code) {
|
||||
case FELICA_CMD_POLL:
|
||||
sg_res_init(0x14);
|
||||
res.system_code[0] = 0x00;
|
||||
res.system_code[1] = 0x00;
|
||||
break;
|
||||
case FELICA_CMD_GET_SYSTEM_CODE:
|
||||
sg_res_init(0x0D);
|
||||
res.felica_payload[0] = 0x01;
|
||||
res.felica_payload[1] = 0x00;
|
||||
res.felica_payload[2] = 0x00;
|
||||
break;
|
||||
case FELICA_CMD_NDA_A4:
|
||||
sg_res_init(0x0B);
|
||||
res.felica_payload[0] = 0x00;
|
||||
break;
|
||||
}
|
||||
res.encap_len = res.payload_len;
|
||||
}
|
244
nfc.txt
Normal file
244
nfc.txt
Normal file
@ -0,0 +1,244 @@
|
||||
N.B. Quoted strings are NOT NUL-terminated unless otherwise noted.
|
||||
Useful reading: https://www.nxp.com/docs/en/data-sheet/MF1S50YYX_V1.pdf
|
||||
|
||||
(AiMe branded cards are Mifare Classic cards. Other technologies exist though)
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
||||
Hardware:
|
||||
Assembly connector:
|
||||
5V Host in
|
||||
Tx;Rx;GND Host RS232 in
|
||||
Tx;Rx;GND Daisy-chain out
|
||||
Main board (probably LED controller):
|
||||
Silk "837-15084"
|
||||
CN1: Host 5V power in, ?V NFC-sub power out
|
||||
CN2: Host RS232 Tx;Rx;GND in, NFC-sub Tx;Rx out
|
||||
CN3: LED-Sub power and data(?) out
|
||||
DIPSW1: Set to hex nibble 8.
|
||||
Contains ADM3222 RS232 transceiver IC
|
||||
Contains ATMega32 MCU
|
||||
NFC subboard:
|
||||
Sticker: Model "TN32MSEC003S"
|
||||
CN1: ?V power and Tx;Rx;GND in, Tx;Rx;GND ass'y CN daisy out.
|
||||
DIPSW1: Set to hex nibble 0.
|
||||
Contains ATmega168 MCU
|
||||
Contains ADM3202A RS232 transceiver IC
|
||||
Contains shielded RF circuit
|
||||
Entire non-ground-plane PCB area is visible through the chassis
|
||||
torx screws lol
|
||||
LED subboard:
|
||||
Silk: "837-15120"
|
||||
CN1: ?V power and Tx;Rx;GND in.
|
||||
Five RGB LEDs and a bunch of resistors
|
||||
No visible logic ICs..?
|
||||
No DIPSW.
|
||||
|
||||
JVS framing:
|
||||
E0 sync
|
||||
D0 escape (+1 to unescape)
|
||||
Checksum is sum of bytes after unescaping
|
||||
|
||||
Frame header:
|
||||
Frame length (including length byte itself)
|
||||
Address
|
||||
Sequence no, hopefully loops before hitting esc byte...
|
||||
Command byte
|
||||
|
||||
Bus addressing:
|
||||
Low nibble set using DIPSWs
|
||||
High nibble ???
|
||||
Daisy chaining mechanism unknown (RS232 wires probably multi-tap)
|
||||
|
||||
Startup
|
||||
-------
|
||||
|
||||
Addr 00 Command 62:
|
||||
Req:
|
||||
00 Payload length
|
||||
Resp:
|
||||
00 Status byte
|
||||
00 Payload length
|
||||
Description:
|
||||
Unknown. Reset?
|
||||
|
||||
Addr 00 Command 30:
|
||||
Req:
|
||||
00 Payload length
|
||||
Resp:
|
||||
00 Status byte
|
||||
17 Payload length
|
||||
.. "TN32MSEC003S F/W Ver1.2E"
|
||||
Description:
|
||||
Get firmware version
|
||||
|
||||
Addr 00 Command 32:
|
||||
Req:
|
||||
00 Payload length
|
||||
Resp:
|
||||
00 Status byte
|
||||
17 Payload length
|
||||
.. "TN32MSEC003S H/W Ver3.0J"
|
||||
Description:
|
||||
Get hardware version
|
||||
|
||||
Addr 08 Command f5:
|
||||
Req:
|
||||
00 Payload length
|
||||
Resp:
|
||||
00 Status byte
|
||||
00 Payload length
|
||||
Description:
|
||||
LED sub-board reset.
|
||||
Won't accept LED commands until you do this.
|
||||
|
||||
Addr 08 Command f0:
|
||||
Req:
|
||||
00 Payload length
|
||||
Resp:
|
||||
00 Status byte
|
||||
09 Payload length
|
||||
.. "15084" (part nr for LED board)
|
||||
FF ??
|
||||
11 ??
|
||||
00 ??
|
||||
12 ??
|
||||
Description:
|
||||
Get board "info"
|
||||
|
||||
Addr 00 Command 54:
|
||||
Req:
|
||||
06 Payload length
|
||||
57 'W'
|
||||
43 'C'
|
||||
43 'C'
|
||||
46 'F'
|
||||
76 'v'
|
||||
32 '2'
|
||||
Resp:
|
||||
00 Status byte?
|
||||
00 ??
|
||||
Description:
|
||||
Set Mifare KeyA.
|
||||
"WCCF" might refer this this SEGA arcade game:
|
||||
https://en.wikipedia.org/wiki/World_Club_Champion_Football
|
||||
It's quite old and has AiMe readers, maybe where they first appeared?
|
||||
|
||||
Addr 00 Command 50:
|
||||
Req:
|
||||
06 Payload length
|
||||
60 ??
|
||||
90 ??
|
||||
D0 ?? (This is escaped of course)
|
||||
06 ??
|
||||
32 ??
|
||||
F5 ??
|
||||
Resp:
|
||||
00 Status byte
|
||||
00 Payload length
|
||||
Description:
|
||||
Possibly Mifare KeyB.
|
||||
|
||||
Polling
|
||||
-------
|
||||
|
||||
Addr 00 Command 40:
|
||||
Req:
|
||||
01 Payload length
|
||||
03 ??
|
||||
Resp:
|
||||
00 Status byte
|
||||
00 Payload length
|
||||
Description:
|
||||
Poll some other NFC technology?
|
||||
|
||||
Addr 00 Command 42:
|
||||
Req:
|
||||
00 Payload length
|
||||
Resp if no MiFare card:
|
||||
00 Status byte
|
||||
01 Payload length
|
||||
00 (represents nothing i guess)
|
||||
Resp if MiFare card:
|
||||
00 Status byte?
|
||||
07 Payload length
|
||||
01 Chunk length?
|
||||
10 ?? Block size maybe?
|
||||
04 Chunk length?
|
||||
.. Mifare UID, four bytes.
|
||||
Description:
|
||||
Check for Mifare card presence?
|
||||
|
||||
Addr 00 Command 41:
|
||||
Req:
|
||||
00 Payload length
|
||||
Resp:
|
||||
00 Status byte
|
||||
00 Payload length
|
||||
Description:
|
||||
Unknown. Poll some other NFC technology?
|
||||
|
||||
Card read
|
||||
---------
|
||||
|
||||
Addr 00 Command 43:
|
||||
Req:
|
||||
04 Payload length
|
||||
.. Mifare UID, four bytes.
|
||||
Resp:
|
||||
00 Status byte
|
||||
00 Payload length
|
||||
Description:
|
||||
Select MiFare by UID?
|
||||
|
||||
Addr 00 Command 55:
|
||||
Req:
|
||||
05 Payload length
|
||||
.. Mifare UID, four bytes.
|
||||
03 ??
|
||||
Resp:
|
||||
00 Status byte
|
||||
00 Payload length
|
||||
Description:
|
||||
Unknown.
|
||||
Block 3 on a Mifare sector contains keys and an access control list.
|
||||
It is generally not accessed directly (unless being provisioned?)
|
||||
|
||||
Addr 00 Command 52:
|
||||
Req:
|
||||
05 Payload length
|
||||
.. Mifare UID, four bytes.
|
||||
.. Block number, 1 or 2.
|
||||
Resp for Block 1:
|
||||
00 Status byte
|
||||
10 Payload length (1 block)
|
||||
.. "SBSD"
|
||||
00 00 00 00
|
||||
00 00 00 00
|
||||
00 4E C6 22
|
||||
Resp for Block 2:
|
||||
00 Status byte
|
||||
10 Payload length (1 block)
|
||||
.. 00 00 00 00 00 00 xx xx
|
||||
xx xx xx xx xx xx xx xx
|
||||
Description:
|
||||
Probably reads blocks 1 and 2 from Mifare sector 0.
|
||||
Block 0 contains the "vendor information" and UID.
|
||||
Block 1 contents are unknown, probably AiMe DB info.
|
||||
Block 2 last 10 bytes hex are printed on the card ("local unique id").
|
||||
(Block 3 contains encryption keys so is not allowed to be read)
|
||||
|
||||
LED
|
||||
---
|
||||
|
||||
Addr 08 Command 81:
|
||||
Req:
|
||||
03 Payload length
|
||||
ff Red intensity
|
||||
ff Green intensity
|
||||
ff Blue intensity
|
||||
Resp:
|
||||
None! Command is not acknowledged
|
||||
Description:
|
||||
Set LED color
|
144
sg-cmd.c
Normal file
144
sg-cmd.c
Normal file
@ -0,0 +1,144 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "board/sg-cmd.h"
|
||||
#include "board/sg-frame.h"
|
||||
|
||||
#include "hook/iobuf.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
union sg_req_any {
|
||||
struct sg_req_header req;
|
||||
uint8_t bytes[256];
|
||||
};
|
||||
|
||||
union sg_res_any {
|
||||
struct sg_res_header res;
|
||||
uint8_t bytes[256];
|
||||
};
|
||||
|
||||
static HRESULT sg_req_validate(const void *ptr, size_t nbytes);
|
||||
|
||||
static void sg_res_error(
|
||||
struct sg_res_header *res,
|
||||
const struct sg_req_header *req);
|
||||
|
||||
static HRESULT sg_req_validate(const void *ptr, size_t nbytes)
|
||||
{
|
||||
const struct sg_req_header *req;
|
||||
size_t payload_len;
|
||||
|
||||
assert(ptr != NULL);
|
||||
|
||||
if (nbytes < sizeof(*req)) {
|
||||
dprintf("SG Cmd: Request header truncated\n");
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
req = ptr;
|
||||
|
||||
if (req->hdr.frame_len != nbytes) {
|
||||
dprintf("SG Cmd: Frame length mismatch: got %i exp %i\n",
|
||||
req->hdr.frame_len,
|
||||
(int) nbytes);
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
payload_len = req->hdr.frame_len - sizeof(*req);
|
||||
|
||||
if (req->payload_len != payload_len) {
|
||||
dprintf("SG Cmd: Payload length mismatch: got %i exp %i\n",
|
||||
req->payload_len,
|
||||
(int) payload_len);
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void sg_req_transact(
|
||||
struct iobuf *res_frame,
|
||||
const uint8_t *req_bytes,
|
||||
size_t req_nbytes,
|
||||
sg_dispatch_fn_t dispatch,
|
||||
void *ctx)
|
||||
{
|
||||
printf("req: ");
|
||||
for (uint8_t i = 0; i < req_nbytes; i++)
|
||||
printf("%02X ", req_bytes[i]);
|
||||
printf("\n");
|
||||
|
||||
struct iobuf req_span;
|
||||
union sg_req_any req;
|
||||
union sg_res_any res;
|
||||
HRESULT hr;
|
||||
|
||||
assert(res_frame != NULL);
|
||||
assert(req_bytes != NULL);
|
||||
assert(dispatch != NULL);
|
||||
|
||||
req_span.bytes = req.bytes;
|
||||
req_span.nbytes = sizeof(req.bytes);
|
||||
req_span.pos = 0;
|
||||
|
||||
hr = sg_frame_decode(&req_span, req_bytes, req_nbytes);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
hr = sg_req_validate(req.bytes, req_span.pos);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
hr = dispatch(ctx, &req, &res);
|
||||
|
||||
if (hr != S_FALSE) {
|
||||
if (FAILED(hr)) {
|
||||
sg_res_error(&res.res, &req.req);
|
||||
}
|
||||
|
||||
sg_frame_encode(res_frame, res.bytes, res.res.hdr.frame_len);
|
||||
|
||||
printf("res: ");
|
||||
for (uint8_t i = 0; i < res_frame->pos; i++)
|
||||
printf("%02X ", res_frame->bytes[i]);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void sg_res_init(
|
||||
struct sg_res_header *res,
|
||||
const struct sg_req_header *req,
|
||||
size_t payload_len)
|
||||
{
|
||||
assert(res != NULL);
|
||||
assert(req != NULL);
|
||||
|
||||
res->hdr.frame_len = sizeof(*res) + payload_len;
|
||||
res->hdr.addr = req->hdr.addr;
|
||||
res->hdr.seq_no = req->hdr.seq_no;
|
||||
res->hdr.cmd = req->hdr.cmd;
|
||||
res->status = 0;
|
||||
res->payload_len = payload_len;
|
||||
}
|
||||
|
||||
static void sg_res_error(
|
||||
struct sg_res_header *res,
|
||||
const struct sg_req_header *req)
|
||||
{
|
||||
assert(res != NULL);
|
||||
assert(req != NULL);
|
||||
|
||||
res->hdr.frame_len = sizeof(*res);
|
||||
res->hdr.addr = req->hdr.addr;
|
||||
res->hdr.seq_no = req->hdr.seq_no;
|
||||
res->hdr.cmd = req->hdr.cmd;
|
||||
res->status = 1;
|
||||
res->payload_len = 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user