Skip to content

Commit 9c5341e

Browse files
committed
Merge remote-tracking branch 'OFW/dev' into dev
2 parents bd348cf + 519b896 commit 9c5341e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+217
-50
lines changed

applications/debug/unit_tests/tests/flipper_format/flipper_format_test.c

+1
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ static bool test_write(const char* file_name) {
265265
if(!flipper_format_file_open_always(file, file_name)) break;
266266
if(!flipper_format_write_header_cstr(file, test_filetype, test_version)) break;
267267
if(!flipper_format_write_comment_cstr(file, "This is comment")) break;
268+
if(!flipper_format_write_empty_line(file)) break;
268269
if(!flipper_format_write_string_cstr(file, test_string_key, test_string_data)) break;
269270
if(!flipper_format_write_int32(file, test_int_key, test_int_data, COUNT_OF(test_int_data)))
270271
break;

applications/main/nfc/plugins/supported_cards/skylanders.c

+43-6
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,36 @@
77
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
88
#include <flipper_format/flipper_format.h>
99

10-
#define TAG "Skylanders"
10+
#define TAG "Skylanders"
11+
#define POLY UINT64_C(0x42f0e1eba9ea3693)
12+
#define TOP UINT64_C(0x800000000000)
13+
#define UID_LEN 4
14+
#define KEY_MASK 0xFFFFFFFFFFFF
1115

1216
static const uint64_t skylanders_key = 0x4b0b20107ccb;
1317

1418
static const char* nfc_resources_header = "Flipper NFC resources";
1519
static const uint32_t nfc_resources_file_version = 1;
1620

21+
uint64_t crc64_like(uint64_t result, uint8_t sector) {
22+
result ^= (uint64_t)sector << 40;
23+
for(int i = 0; i < 8; i++) {
24+
result = (result & TOP) ? (result << 1) ^ POLY : result << 1;
25+
}
26+
return result;
27+
}
28+
29+
uint64_t taghash(uint32_t uid) {
30+
uint64_t result = 0x9AE903260CC4;
31+
uint8_t uidBytes[UID_LEN] = {0};
32+
memcpy(uidBytes, &uid, UID_LEN);
33+
34+
for(int i = 0; i < UID_LEN; i++) {
35+
result = crc64_like(result, uidBytes[i]);
36+
}
37+
return result;
38+
}
39+
1740
static bool skylanders_search_data(
1841
Storage* storage,
1942
const char* file_name,
@@ -88,6 +111,12 @@ static bool skylanders_read(Nfc* nfc, NfcDevice* device) {
88111
MfClassicData* data = mf_classic_alloc();
89112
nfc_device_copy_data(device, NfcProtocolMfClassic, data);
90113

114+
size_t* uid_len = 0;
115+
const uint8_t* uid_bytes = mf_classic_get_uid(data, uid_len);
116+
uint32_t uid = 0;
117+
memcpy(&uid, uid_bytes, sizeof(uid));
118+
uint64_t hash = taghash(uid);
119+
91120
do {
92121
MfClassicType type = MfClassicType1k;
93122
MfClassicError error = mf_classic_poller_sync_detect_type(nfc, &type);
@@ -96,10 +125,18 @@ static bool skylanders_read(Nfc* nfc, NfcDevice* device) {
96125
data->type = type;
97126
MfClassicDeviceKeys keys = {};
98127
for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) {
99-
bit_lib_num_to_bytes_be(skylanders_key, sizeof(MfClassicKey), keys.key_a[i].data);
100-
FURI_BIT_SET(keys.key_a_mask, i);
101-
bit_lib_num_to_bytes_be(skylanders_key, sizeof(MfClassicKey), keys.key_b[i].data);
102-
FURI_BIT_SET(keys.key_b_mask, i);
128+
if(i == 0) {
129+
bit_lib_num_to_bytes_be(skylanders_key, sizeof(MfClassicKey), keys.key_a[i].data);
130+
FURI_BIT_SET(keys.key_a_mask, i);
131+
} else {
132+
uint64_t sectorhash = crc64_like(hash, i);
133+
uint64_t key = sectorhash & KEY_MASK;
134+
uint8_t* keyBytes = (uint8_t*)&key;
135+
memcpy(keys.key_a[i].data, keyBytes, sizeof(MfClassicKey));
136+
FURI_BIT_SET(keys.key_a_mask, i);
137+
memset(keys.key_b[i].data, 0, sizeof(MfClassicKey));
138+
FURI_BIT_SET(keys.key_b_mask, i);
139+
}
103140
}
104141

105142
error = mf_classic_poller_sync_read(nfc, &keys, data);
@@ -134,7 +171,7 @@ static bool skylanders_parse(const NfcDevice* device, FuriString* parsed_data) {
134171
uint64_t key = bit_lib_bytes_to_num_be(sec_tr->key_a.data, 6);
135172
if(key != skylanders_key) break;
136173

137-
const uint16_t id = (uint16_t)*data->block[1].data;
174+
const uint16_t id = data->block[1].data[1] << 8 | data->block[1].data[0];
138175
if(id == 0) break;
139176

140177
Storage* storage = furi_record_open(RECORD_STORAGE);

applications/system/js_app/packages/fz-sdk/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@darkflippers/fz-sdk-ul",
3-
"version": "0.1.2",
3+
"version": "0.1.3",
44
"description": "Type declarations and documentation for native JS modules available on Unleashed Custom Firmware for Flipper Zero",
55
"keywords": [
66
"unleashed",

applications/system/js_app/packages/fz-sdk/pnpm-lock.yaml

+6-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

applications/system/js_app/packages/fz-sdk/sdk.js

+14-2
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,21 @@ async function build(config) {
9191

9292
async function upload(config) {
9393
const appFile = fs.readFileSync(config.input, "utf8");
94-
const flippers = (await SerialPort.list()).filter(x => x.serialNumber?.startsWith("flip_"));
94+
const serialPorts = await SerialPort.list();
95+
96+
let flippers = serialPorts
97+
.filter(x => x.serialNumber?.startsWith("flip_"))
98+
.map(x => ({ path: x.path, name: x.serialNumber.replace("flip_", "") }));
99+
100+
if (!flippers.length) {
101+
// some Windows installations don't report the serial number correctly;
102+
// filter by STM VCP VID:PID instead
103+
flippers = serialPorts
104+
.filter(x => x?.vendorId === "0483" && x?.productId === "5740")
105+
.map(x => ({ path: x.path, name: x.path }));
106+
}
95107

96-
if (!flippers) {
108+
if (!flippers.length) {
97109
console.error("No Flippers found");
98110
process.exit(1);
99111
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Filetype: Flipper Animation
2+
Version: 1
3+
4+
Width: 128
5+
Height: 64
6+
Passive frames: 10
7+
Active frames: 18
8+
Frames order: 0 1 2 1 0 1 2 1 0 1 2 3 4 5 6 5 4 7 2 8 9 10 11 10 9 10 11 12
9+
Active cycles: 1
10+
Frame rate: 2
11+
Duration: 3600
12+
Active cooldown: 7
13+
14+
Bubble slots: 1
15+
16+
Slot: 0
17+
X: 11
18+
Y: 19
19+
Text: HAPPY\nHOLIDAYS!
20+
AlignH: Right
21+
AlignV: Center
22+
StartFrame: 22
23+
EndFrame: 27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Filetype: Flipper Animation
2+
Version: 1
3+
4+
Width: 128
5+
Height: 64
6+
Passive frames: 18
7+
Active frames: 19
8+
Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
9+
Active cycles: 1
10+
Frame rate: 2
11+
Duration: 3600
12+
Active cooldown: 7
13+
14+
Bubble slots: 1
15+
16+
Slot: 0
17+
X: 21
18+
Y: 25
19+
Text: AAAAaAAAAHHh!!
20+
AlignH: Right
21+
AlignV: Bottom
22+
StartFrame: 30
23+
EndFrame: 32

assets/dolphin/external/manifest.txt

+17-3
Original file line numberDiff line numberDiff line change
@@ -195,21 +195,35 @@ Min butthurt: 0
195195
Max butthurt: 8
196196
Min level: 1
197197
Max level: 3
198-
Weight: 4
198+
Weight: 3
199199

200200
Name: L3_Intruder_alert_128x64
201201
Min butthurt: 0
202202
Max butthurt: 12
203203
Min level: 3
204204
Max level: 3
205-
Weight: 4
205+
Weight: 3
206206

207207
Name: L1_Procrastinating_128x64
208208
Min butthurt: 0
209209
Max butthurt: 8
210210
Min level: 1
211211
Max level: 3
212-
Weight: 6
212+
Weight: 3
213+
214+
Name: L1_Happy_holidays_128x64
215+
Min butthurt: 0
216+
Max butthurt: 14
217+
Min level: 1
218+
Max level: 3
219+
Weight: 4
220+
221+
Name: L1_Sleigh_ride_128x64
222+
Min butthurt: 0
223+
Max butthurt: 14
224+
Min level: 1
225+
Max level: 3
226+
Weight: 4
213227

214228
Name: L3_Fireplace_128x64
215229
Min butthurt: 0

firmware.scons

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ env = ENV.Clone(
2929
TARGETS_ROOT=Dir("#/targets"),
3030
LINT_SOURCES=[
3131
Dir("applications"),
32+
# Not C code
33+
Dir("!applications/system/js_app/packages"),
3234
],
3335
LIBPATH=[
3436
"${LIB_DIST_DIR}",

lib/ble_profile/extra_services/hid_service.c

+8-6
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010
#define TAG "BleHid"
1111

1212
#define BLE_SVC_HID_REPORT_MAP_MAX_LEN (255)
13-
#define BLE_SVC_HID_REPORT_MAX_LEN (255)
14-
#define BLE_SVC_HID_REPORT_REF_LEN (2)
15-
#define BLE_SVC_HID_INFO_LEN (4)
16-
#define BLE_SVC_HID_CONTROL_POINT_LEN (1)
13+
#define BLE_SVC_HID_REPORT_MAX_LEN (255)
14+
#define BLE_SVC_HID_REPORT_REF_LEN (2)
15+
#define BLE_SVC_HID_INFO_LEN (4)
16+
#define BLE_SVC_HID_CONTROL_POINT_LEN (1)
1717

18-
#define BLE_SVC_HID_INPUT_REPORT_COUNT (3)
19-
#define BLE_SVC_HID_OUTPUT_REPORT_COUNT (0)
18+
#define BLE_SVC_HID_INPUT_REPORT_COUNT (3)
19+
#define BLE_SVC_HID_OUTPUT_REPORT_COUNT (0)
2020
#define BLE_SVC_HID_FEATURE_REPORT_COUNT (0)
2121
#define BLE_SVC_HID_REPORT_COUNT \
2222
(BLE_SVC_HID_INPUT_REPORT_COUNT + BLE_SVC_HID_OUTPUT_REPORT_COUNT + \
@@ -157,6 +157,7 @@ static BleEventAckStatus ble_svc_hid_event_handler(void* event, void* context) {
157157
hci_event_pckt* event_pckt = (hci_event_pckt*)(((hci_uart_pckt*)event)->data);
158158
evt_blecore_aci* blecore_evt = (evt_blecore_aci*)event_pckt->data;
159159
// aci_gatt_attribute_modified_event_rp0* attribute_modified;
160+
160161
if(event_pckt->evt == HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE) {
161162
if(blecore_evt->ecode == ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE) {
162163
// Process modification events
@@ -274,6 +275,7 @@ bool ble_svc_hid_update_input_report(
274275
.data_ptr = data,
275276
.data_len = len,
276277
};
278+
277279
return ble_gatt_characteristic_update(
278280
hid_svc->svc_handle, &hid_svc->input_report_chars[input_report_num], &report_data);
279281
}

lib/flipper_format/flipper_format.c

+5
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,11 @@ bool flipper_format_write_comment_cstr(FlipperFormat* flipper_format, const char
403403
return flipper_format_stream_write_comment_cstr(flipper_format->stream, data);
404404
}
405405

406+
bool flipper_format_write_empty_line(FlipperFormat* flipper_format) {
407+
furi_check(flipper_format);
408+
return flipper_format_stream_write_eol(flipper_format->stream);
409+
}
410+
406411
bool flipper_format_delete_key(FlipperFormat* flipper_format, const char* key) {
407412
furi_check(flipper_format);
408413
FlipperStreamWriteData write_data = {

lib/flipper_format/flipper_format.h

+8
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,14 @@ bool flipper_format_write_comment(FlipperFormat* flipper_format, FuriString* dat
518518
*/
519519
bool flipper_format_write_comment_cstr(FlipperFormat* flipper_format, const char* data);
520520

521+
/** Write empty line (Improves readability for human based parsing)
522+
*
523+
* @param flipper_format Pointer to a FlipperFormat instance
524+
*
525+
* @return True on success
526+
*/
527+
bool flipper_format_write_empty_line(FlipperFormat* flipper_format);
528+
521529
/** Removes the first matching key and its value. Sets the RW pointer to a
522530
* position of deleted data.
523531
*

lib/nfc/protocols/mf_plus/mf_plus_poller.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ static void mf_plus_poller_set_callback(
146146

147147
static NfcCommand mf_plus_poller_run(NfcGenericEvent event, void* context) {
148148
furi_assert(context);
149-
furi_assert(event.protocol = NfcProtocolIso14443_4a);
149+
furi_assert(event.protocol == NfcProtocolIso14443_4a);
150150
furi_assert(event.event_data);
151151

152152
MfPlusPoller* instance = context;
@@ -178,7 +178,7 @@ void mf_plus_poller_free(MfPlusPoller* instance) {
178178

179179
static bool mf_plus_poller_detect(NfcGenericEvent event, void* context) {
180180
furi_assert(context);
181-
furi_assert(event.protocol = NfcProtocolIso14443_4a);
181+
furi_assert(event.protocol == NfcProtocolIso14443_4a);
182182
furi_assert(event.event_data);
183183

184184
MfPlusPoller* instance = context;

lib/subghz/protocols/bin_raw.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,8 @@ SubGhzProtocolStatus
314314
flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
315315

316316
if(!subghz_protocol_encoder_bin_raw_get_upload(instance)) {
317-
break;
318317
res = SubGhzProtocolStatusErrorEncoderGetUpload;
318+
break;
319319
}
320320
instance->encoder.is_running = true;
321321

scripts/get_env.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ def get_commit_json(event):
3434
commit_url = event["pull_request"]["base"]["repo"]["commits_url"].replace(
3535
"{/sha}", f"/{event['pull_request']['head']['sha']}"
3636
)
37-
with urllib.request.urlopen(commit_url, context=context) as commit_file:
37+
request = urllib.request.Request(commit_url)
38+
if "GH_TOKEN" in os.environ:
39+
request.add_header("Authorization", "Bearer %s" % (os.environ["GH_TOKEN"]))
40+
41+
with urllib.request.urlopen(request, context=context) as commit_file:
3842
commit_json = json.loads(commit_file.read().decode("utf-8"))
3943
return commit_json
4044

0 commit comments

Comments
 (0)