wiegand_data.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. #include "../wiegand.h"
  2. void wiegand_add_info_4bit_8bit(FuriString *buffer)
  3. {
  4. if (bit_count == 8)
  5. {
  6. for (int i = 0; i < 4; i++)
  7. {
  8. furi_string_cat_printf(
  9. buffer, "\nbit %d: %d %d (bit %d)", i, data[i], data[i + 4], i + 4);
  10. if (data[i] == data[i + 4])
  11. {
  12. furi_string_cat_printf(buffer, " - ERROR");
  13. }
  14. else
  15. {
  16. furi_string_cat_printf(buffer, " - OK");
  17. }
  18. }
  19. }
  20. if (bit_count == 4 || bit_count == 8)
  21. {
  22. int code = 0;
  23. int offset = bit_count == 4 ? 0 : 4;
  24. for (int i = 0; i < 4; i++)
  25. {
  26. code = code << 1;
  27. code += data[i + offset] ? 1 : 0;
  28. }
  29. if (code <= 9)
  30. {
  31. furi_string_cat_printf(buffer, "\nButton: %d", code);
  32. }
  33. else if (code == 10)
  34. {
  35. furi_string_cat_printf(buffer, "\nButton: Escape");
  36. }
  37. else if (code == 11)
  38. {
  39. furi_string_cat_printf(buffer, "\nButton: Enter");
  40. }
  41. }
  42. }
  43. void wiegand_add_info_26bit(FuriString *buffer)
  44. {
  45. // 26 bit wiegand, the first bit is the even parity bit, which is
  46. // based on the next 12 bits. The number of bits that are a 1 should
  47. // be even.
  48. // After the parity bit, the next 8 bits are the facility code.
  49. // Then the next 16 bits are the card id .
  50. furi_string_cat_printf(buffer, "\nFacility: ");
  51. int code = 0;
  52. int count = 0;
  53. uint32_t dec = 0;
  54. for (int i = 1; i < 25; i++)
  55. {
  56. code = code << 1;
  57. dec = dec << 1;
  58. code |= data[i] ? 1 : 0;
  59. dec |= data[i] ? 1 : 0;
  60. if (++count % 4 == 0)
  61. {
  62. furi_string_cat_printf(buffer, "%X", code);
  63. code = 0;
  64. }
  65. if (i == 8)
  66. {
  67. furi_string_cat_printf(buffer, " (%ld)", dec);
  68. dec = 0;
  69. }
  70. // Parity, then 8 bit facility code, then id.
  71. if (i == 9)
  72. {
  73. furi_string_cat_printf(buffer, "\nCard: ");
  74. }
  75. }
  76. furi_string_cat_printf(buffer, " (%ld)", dec);
  77. int parity = 0;
  78. if (data[0])
  79. {
  80. parity = 1;
  81. }
  82. for (int i = 1; i < 13; i++)
  83. {
  84. if (data[i])
  85. {
  86. parity++;
  87. }
  88. }
  89. if (parity % 2 == 0)
  90. {
  91. furi_string_cat_printf(buffer, "\nEven Parity (%d): OK", parity);
  92. }
  93. else
  94. {
  95. furi_string_cat_printf(buffer, "\nEven Parity (%d): ERROR", parity);
  96. }
  97. if (data[13])
  98. {
  99. parity = 1;
  100. }
  101. else
  102. {
  103. parity = 0;
  104. }
  105. for (int i = 14; i < 26; i++)
  106. {
  107. if (data[i])
  108. {
  109. parity++;
  110. }
  111. }
  112. if (parity % 2 == 0)
  113. {
  114. furi_string_cat_printf(buffer, "\nOdd Parity (%d): ERROR", parity);
  115. }
  116. else
  117. {
  118. furi_string_cat_printf(buffer, "\nOdd Parity (%d): OK", parity);
  119. }
  120. }
  121. void wiegand_add_info_24bit(FuriString *buffer)
  122. {
  123. // 24 bit wiegand (no parity info).
  124. // The First 8 bits are the facility code.
  125. // Then the next 16 bits are the card id.
  126. furi_string_cat_printf(buffer, "\nFacility: 0x");
  127. int code = 0;
  128. int count = 0;
  129. uint32_t dec = 0;
  130. for (int i = 0; i < 24; i++)
  131. {
  132. code = code << 1;
  133. dec = dec << 1;
  134. code |= data[i] ? 1 : 0;
  135. dec |= data[i] ? 1 : 0;
  136. if (++count % 4 == 0)
  137. {
  138. furi_string_cat_printf(buffer, "%X", code);
  139. code = 0;
  140. }
  141. // The first 8 bits are facility code, then comes id.
  142. if (i == 8)
  143. {
  144. furi_string_cat_printf(buffer, " (%ld)", dec);
  145. dec = 0;
  146. furi_string_cat_printf(buffer, "\nCard: 0x");
  147. }
  148. }
  149. furi_string_cat_printf(buffer, " (%ld)", dec);
  150. }
  151. void wiegand_add_info_48bit(FuriString *buffer)
  152. {
  153. // We assume this is HID 48 bit Corporate 1000 - H2004064 format.
  154. // The first bit is odd parity 2 (based on bits 2-48).
  155. // The next bit is even parity (based on 4-5,7-8,10-11,...,46-47).
  156. // Then 22 bit company code.
  157. // Then 23 bit card id.
  158. /// Then odd parity 1 (based on 3-4,6-7,9-10,...,45-46).
  159. // 22 bits company code (bits 3-24; data[2..23])
  160. uint32_t code = 0;
  161. for (int i = 2; i <= 23; i++)
  162. {
  163. code = code << 1;
  164. code |= data[i] ? 1 : 0;
  165. }
  166. furi_string_cat_printf(buffer, "\nFacility: %lX (%ld)", code, code);
  167. // 23 bit card id (bits 25-47; data[24..46]).
  168. code = 0;
  169. for (int i = 24; i <= 46; i++)
  170. {
  171. code = code << 1;
  172. code |= data[i] ? 1 : 0;
  173. }
  174. furi_string_cat_printf(buffer, "\nCard: %lX (%ld)", code, code);
  175. // TODO: Add the 3 parity checks.
  176. }
  177. void wiegand_add_info_35bit(FuriString *buffer)
  178. {
  179. // We assume this is HID 35 bit Corporate 1000 - C1k35s format.
  180. // 12 bits company code
  181. uint32_t code = 0;
  182. for (int i = 2; i <= 13; i++)
  183. {
  184. code = code << 1;
  185. code |= data[i] ? 1 : 0;
  186. }
  187. furi_string_cat_printf(buffer, "\nFacility: %lX (%ld)", code, code);
  188. // 20 bit card id
  189. code = 0;
  190. for (int i = 14; i <= 33; i++)
  191. {
  192. code = code << 1;
  193. code |= data[i] ? 1 : 0;
  194. }
  195. furi_string_cat_printf(buffer, "\nCard: %lX (%ld)", code, code);
  196. }
  197. void wiegand_add_info_36bit(FuriString *buffer)
  198. {
  199. // We assume this is HID 36 bit Keyscan - C15001 format.
  200. // 10 bits OEM
  201. uint32_t oem = 0;
  202. for (int i = 1; i <= 10; i++)
  203. {
  204. oem = (oem << 1) | (data[i] ? 1 : 0);
  205. }
  206. furi_string_cat_printf(buffer, "\nOEM: %lX (%ld)", oem, oem);
  207. // 8 bits facility code
  208. uint32_t facilityCode = 0;
  209. for (int i = 11; i <= 18; i++)
  210. {
  211. facilityCode = (facilityCode << 1) | (data[i] ? 1 : 0);
  212. }
  213. furi_string_cat_printf(buffer, "\nFacility: %lX (%ld)", facilityCode, facilityCode);
  214. // 16 bits card ID
  215. uint32_t cardID = 0;
  216. for (int i = 19; i <= 34; i++)
  217. {
  218. cardID = (cardID << 1) | (data[i] ? 1 : 0);
  219. }
  220. furi_string_cat_printf(buffer, "\nCard: %lX (%ld)", cardID, cardID);
  221. }
  222. void wiegand_add_info(FuriString *buffer)
  223. {
  224. furi_string_push_back(buffer, '\n');
  225. if (bit_count == 4 || bit_count == 8)
  226. {
  227. wiegand_add_info_4bit_8bit(buffer);
  228. }
  229. else if (bit_count == 26)
  230. {
  231. wiegand_add_info_26bit(buffer);
  232. }
  233. else if (bit_count == 24)
  234. {
  235. wiegand_add_info_24bit(buffer);
  236. }
  237. else if (bit_count == 35)
  238. {
  239. wiegand_add_info_35bit(buffer);
  240. }
  241. else if (bit_count == 36)
  242. {
  243. wiegand_add_info_36bit(buffer);
  244. }
  245. else if (bit_count == 48)
  246. {
  247. wiegand_add_info_48bit(buffer);
  248. }
  249. furi_string_push_back(buffer, '\n');
  250. }
  251. void wiegand_button_callback(GuiButtonType result, InputType type, void *context)
  252. {
  253. App *app = context;
  254. if (type == InputTypeShort && result == GuiButtonTypeLeft)
  255. {
  256. view_dispatcher_send_custom_event(app->view_dispatcher, WiegandDataSceneSaveButtonEvent);
  257. }
  258. else if (type == InputTypeShort && result == GuiButtonTypeCenter)
  259. {
  260. view_dispatcher_send_custom_event(app->view_dispatcher, WiegandDataScenePlayButtonEvent);
  261. }
  262. }
  263. void wiegand_data_scene_on_enter(void *context)
  264. {
  265. App *app = context;
  266. widget_reset(app->widget);
  267. widget_add_string_element(app->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Wiegand Data");
  268. FuriString *buffer = furi_string_alloc(1024);
  269. furi_string_printf(buffer, "Bits: %d\n", bit_count);
  270. for (int i = 0; i < bit_count; i++)
  271. {
  272. furi_string_push_back(buffer, data[i] ? '1' : '0');
  273. if ((bit_count - i - 1) % 22 == 21)
  274. {
  275. furi_string_push_back(buffer, '\n');
  276. }
  277. }
  278. // furi_string_cat_printf(buffer, "\nPulse: %ld us", (data_rise[0] - data_fall[0]) / 64);
  279. // furi_string_cat_printf(buffer, "\nPeriod: %ld us", (data_fall[1] - data_fall[0]) / 64);
  280. wiegand_add_info(buffer);
  281. for (int i = 0; i < bit_count;)
  282. {
  283. uint32_t pulse = (data_rise[i] - data_fall[i]) / 64;
  284. i++;
  285. uint32_t period = (i < bit_count) ? (data_fall[i] - data_fall[i - 1]) / 64 : 0;
  286. furi_string_cat_printf(
  287. buffer, "\n%c : %ld us, %ld us", data[i] ? '1' : '0', pulse, period);
  288. }
  289. widget_add_text_scroll_element(app->widget, 0, 12, 128, 34, furi_string_get_cstr(buffer));
  290. if (!data_saved)
  291. {
  292. widget_add_button_element(
  293. app->widget, GuiButtonTypeLeft, "Save", wiegand_button_callback, app);
  294. }
  295. widget_add_button_element(
  296. app->widget, GuiButtonTypeCenter, "Play", wiegand_button_callback, app);
  297. view_dispatcher_switch_to_view(app->view_dispatcher, WiegandWidgetView);
  298. }
  299. bool wiegand_data_scene_on_event(void *context, SceneManagerEvent event)
  300. {
  301. App *app = context;
  302. bool consumed = false;
  303. switch (event.type)
  304. {
  305. case SceneManagerEventTypeCustom:
  306. switch (event.event)
  307. {
  308. case WiegandDataScenePlayButtonEvent:
  309. wiegand_play();
  310. consumed = true;
  311. break;
  312. case WiegandDataSceneSaveButtonEvent:
  313. scene_manager_next_scene(app->scene_manager, WiegandSaveScene);
  314. consumed = true;
  315. break;
  316. default:
  317. consumed = false;
  318. break;
  319. }
  320. break;
  321. default:
  322. break;
  323. }
  324. return consumed;
  325. }