picopass_scene_card_menu.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #include "../picopass_i.h"
  2. enum SubmenuIndex {
  3. SubmenuIndexParse,
  4. SubmenuIndexParseSIO,
  5. SubmenuIndexSave,
  6. SubmenuIndexSaveLegacy,
  7. SubmenuIndexSaveAsLF,
  8. SubmenuIndexSaveAsSeader,
  9. SubmenuIndexSavePartial,
  10. SubmenuIndexChangeKey,
  11. SubmenuIndexWrite,
  12. SubmenuIndexEmulate,
  13. SubmenuIndexMax,
  14. };
  15. void picopass_scene_card_menu_submenu_callback(void* context, uint32_t index) {
  16. Picopass* picopass = context;
  17. view_dispatcher_send_custom_event(picopass->view_dispatcher, index);
  18. }
  19. void picopass_scene_card_menu_add_items(void* context, bool included[]) {
  20. Picopass* picopass = context;
  21. Submenu* submenu = picopass->submenu;
  22. // Clear the menu
  23. submenu_reset(submenu);
  24. if(included[SubmenuIndexParse]) {
  25. submenu_add_item(
  26. submenu,
  27. "Parse",
  28. SubmenuIndexParse,
  29. picopass_scene_card_menu_submenu_callback,
  30. picopass);
  31. }
  32. if(included[SubmenuIndexParseSIO]) {
  33. submenu_add_item(
  34. submenu,
  35. "Parse SIO",
  36. SubmenuIndexParseSIO,
  37. picopass_scene_card_menu_submenu_callback,
  38. picopass);
  39. }
  40. if(included[SubmenuIndexSave]) {
  41. submenu_add_item(
  42. submenu, "Save", SubmenuIndexSave, picopass_scene_card_menu_submenu_callback, picopass);
  43. }
  44. if(included[SubmenuIndexSaveLegacy]) {
  45. submenu_add_item(
  46. submenu,
  47. "Save as Legacy",
  48. SubmenuIndexSaveLegacy,
  49. picopass_scene_card_menu_submenu_callback,
  50. picopass);
  51. }
  52. if(included[SubmenuIndexSaveAsLF]) {
  53. submenu_add_item(
  54. submenu,
  55. "Save as LFRFID",
  56. SubmenuIndexSaveAsLF,
  57. picopass_scene_card_menu_submenu_callback,
  58. picopass);
  59. }
  60. if(included[SubmenuIndexSaveAsSeader]) {
  61. submenu_add_item(
  62. submenu,
  63. "Save in Seader fmt",
  64. SubmenuIndexSaveAsSeader,
  65. picopass_scene_card_menu_submenu_callback,
  66. picopass);
  67. }
  68. if(included[SubmenuIndexSavePartial]) {
  69. submenu_add_item(
  70. submenu,
  71. "Save Partial",
  72. SubmenuIndexSavePartial,
  73. picopass_scene_card_menu_submenu_callback,
  74. picopass);
  75. }
  76. if(included[SubmenuIndexChangeKey]) {
  77. submenu_add_item(
  78. submenu,
  79. "Change Key",
  80. SubmenuIndexChangeKey,
  81. picopass_scene_card_menu_submenu_callback,
  82. picopass);
  83. }
  84. if(included[SubmenuIndexWrite]) {
  85. submenu_add_item(
  86. submenu,
  87. "Write",
  88. SubmenuIndexWrite,
  89. picopass_scene_card_menu_submenu_callback,
  90. picopass);
  91. }
  92. if(included[SubmenuIndexEmulate]) {
  93. submenu_add_item(
  94. submenu,
  95. "Emulate",
  96. SubmenuIndexEmulate,
  97. picopass_scene_card_menu_submenu_callback,
  98. picopass);
  99. }
  100. submenu_set_selected_item(
  101. picopass->submenu,
  102. scene_manager_get_scene_state(picopass->scene_manager, PicopassSceneCardMenu));
  103. }
  104. void picopass_scene_card_menu_on_enter(void* context) {
  105. Picopass* picopass = context;
  106. PicopassPacs* pacs = &picopass->dev->dev_data.pacs;
  107. PicopassBlock* card_data = picopass->dev->dev_data.card_data;
  108. PicopassDeviceAuthMethod auth = picopass->dev->dev_data.auth;
  109. PluginWiegand* plugin = picopass->plugin_wiegand;
  110. bool SE = card_data[PICOPASS_ICLASS_PACS_CFG_BLOCK_INDEX].valid &&
  111. 0x30 == card_data[PICOPASS_ICLASS_PACS_CFG_BLOCK_INDEX].data[0];
  112. bool SR = card_data[PICOPASS_ICLASS_PACS_CFG_BLOCK_INDEX].data[0] == 0xA3 &&
  113. card_data[10].valid && 0x30 == card_data[10].data[0];
  114. bool has_sio = SE || SR;
  115. bool secured = (card_data[PICOPASS_CONFIG_BLOCK_INDEX].data[7] & PICOPASS_FUSE_CRYPT10) !=
  116. PICOPASS_FUSE_CRYPT0;
  117. bool no_credential = picopass_is_memset(pacs->credential, 0x00, sizeof(pacs->credential));
  118. // To allow us to disconnect the order of the menu items from the order we determine what is valid
  119. bool included[SubmenuIndexMax];
  120. for(size_t i = 0; i < SubmenuIndexMax; i++) {
  121. included[i] = false;
  122. }
  123. if(auth == PicopassDeviceAuthMethodFailed) {
  124. included[SubmenuIndexSavePartial] = true;
  125. } else {
  126. included[SubmenuIndexSave] = true;
  127. }
  128. if(secured && has_sio) {
  129. included[SubmenuIndexParseSIO] = true;
  130. included[SubmenuIndexSaveAsSeader] = true;
  131. }
  132. if(secured && !no_credential) {
  133. included[SubmenuIndexSaveAsLF] = true;
  134. if(SR) {
  135. included[SubmenuIndexSaveLegacy] = true;
  136. }
  137. if(plugin) {
  138. // Convert from byte array to uint64_t
  139. uint64_t credential = 0;
  140. memcpy(&credential, pacs->credential, sizeof(uint64_t));
  141. credential = __builtin_bswap64(credential);
  142. size_t format_count = plugin->count(pacs->bitLength, credential);
  143. if(format_count > 0) {
  144. included[SubmenuIndexParse] = true;
  145. }
  146. }
  147. }
  148. if(auth == PicopassDeviceAuthMethodNone || auth == PicopassDeviceAuthMethodKey) {
  149. included[SubmenuIndexEmulate] = true;
  150. if(!has_sio) {
  151. included[SubmenuIndexWrite] = true;
  152. }
  153. if(secured) {
  154. included[SubmenuIndexChangeKey] = true;
  155. }
  156. }
  157. picopass_scene_card_menu_add_items(picopass, included);
  158. view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewMenu);
  159. }
  160. bool picopass_scene_card_menu_on_event(void* context, SceneManagerEvent event) {
  161. Picopass* picopass = context;
  162. bool consumed = false;
  163. if(event.type == SceneManagerEventTypeCustom) {
  164. if(event.event == SubmenuIndexSave) {
  165. scene_manager_set_scene_state(
  166. picopass->scene_manager, PicopassSceneCardMenu, SubmenuIndexSave);
  167. scene_manager_next_scene(picopass->scene_manager, PicopassSceneSaveName);
  168. picopass->dev->format = PicopassDeviceSaveFormatOriginal;
  169. consumed = true;
  170. } else if(event.event == SubmenuIndexSavePartial) {
  171. scene_manager_set_scene_state(
  172. picopass->scene_manager, PicopassSceneCardMenu, SubmenuIndexSave);
  173. scene_manager_next_scene(picopass->scene_manager, PicopassSceneSaveName);
  174. picopass->dev->format = PicopassDeviceSaveFormatPartial;
  175. consumed = true;
  176. } else if(event.event == SubmenuIndexParseSIO) {
  177. scene_manager_set_scene_state(
  178. picopass->scene_manager, PicopassSceneCardMenu, event.event);
  179. scene_manager_next_scene(picopass->scene_manager, PicopassSceneParseSIO);
  180. consumed = true;
  181. } else if(event.event == SubmenuIndexSaveAsSeader) {
  182. scene_manager_set_scene_state(
  183. picopass->scene_manager, PicopassSceneCardMenu, event.event);
  184. scene_manager_next_scene(picopass->scene_manager, PicopassSceneSaveName);
  185. picopass->dev->format = PicopassDeviceSaveFormatSeader;
  186. consumed = true;
  187. } else if(event.event == SubmenuIndexSaveAsLF) {
  188. scene_manager_set_scene_state(
  189. picopass->scene_manager, PicopassSceneCardMenu, SubmenuIndexSaveAsLF);
  190. picopass->dev->format = PicopassDeviceSaveFormatLF;
  191. scene_manager_next_scene(picopass->scene_manager, PicopassSceneSaveName);
  192. consumed = true;
  193. } else if(event.event == SubmenuIndexWrite) {
  194. scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteCard);
  195. consumed = true;
  196. } else if(event.event == SubmenuIndexEmulate) {
  197. scene_manager_next_scene(picopass->scene_manager, PicopassSceneEmulate);
  198. consumed = true;
  199. } else if(event.event == SubmenuIndexChangeKey) {
  200. scene_manager_set_scene_state(
  201. picopass->scene_manager, PicopassSceneCardMenu, SubmenuIndexChangeKey);
  202. scene_manager_next_scene(picopass->scene_manager, PicopassSceneKeyMenu);
  203. consumed = true;
  204. } else if(event.event == SubmenuIndexParse) {
  205. scene_manager_set_scene_state(
  206. picopass->scene_manager, PicopassSceneCardMenu, SubmenuIndexParse);
  207. scene_manager_next_scene(picopass->scene_manager, PicopassSceneFormats);
  208. consumed = true;
  209. } else if(event.event == SubmenuIndexSaveLegacy) {
  210. scene_manager_set_scene_state(
  211. picopass->scene_manager, PicopassSceneCardMenu, SubmenuIndexSaveLegacy);
  212. picopass->dev->format = PicopassDeviceSaveFormatLegacy;
  213. scene_manager_next_scene(picopass->scene_manager, PicopassSceneSaveName);
  214. consumed = true;
  215. }
  216. } else if(event.type == SceneManagerEventTypeBack) {
  217. consumed = scene_manager_search_and_switch_to_previous_scene(
  218. picopass->scene_manager, PicopassSceneStart);
  219. }
  220. return consumed;
  221. }
  222. void picopass_scene_card_menu_on_exit(void* context) {
  223. Picopass* picopass = context;
  224. submenu_reset(picopass->submenu);
  225. }