From 0109361fe96bb774ca61e599578eeba6071f9959 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Sat, 8 Jul 2023 19:52:04 +0300 Subject: [PATCH 01/14] nfc maker - add keyboard --- .../assets/KeyBackspaceSelected_16x9.png | Bin 0 -> 1812 bytes .../nfc_maker/assets/KeyBackspace_16x9.png | Bin 0 -> 1829 bytes .../assets/KeyKeyboardSelected_10x11.png | Bin 0 -> 7210 bytes .../nfc_maker/assets/KeyKeyboard_10x11.png | Bin 0 -> 7763 bytes .../assets/KeySaveSelected_24x11.png | Bin 0 -> 1853 bytes .../nfc_maker/assets/KeySave_24x11.png | Bin 0 -> 1863 bytes .../nfc_maker/assets/WarningDolphin_45x42.png | Bin 0 -> 1139 bytes applications/external/nfc_maker/nfc_maker.c | 8 +- applications/external/nfc_maker/nfc_maker.h | 4 +- .../external/nfc_maker/nfc_maker_text_input.c | 762 ++++++++++++++++++ .../external/nfc_maker/nfc_maker_text_input.h | 85 ++ .../external/nfc_maker/nfc_maker_validators.c | 57 ++ .../external/nfc_maker/nfc_maker_validators.h | 21 + .../nfc_maker/scenes/nfc_maker_scene_https.c | 8 +- .../nfc_maker/scenes/nfc_maker_scene_mail.c | 8 +- .../nfc_maker/scenes/nfc_maker_scene_menu.c | 2 +- .../nfc_maker/scenes/nfc_maker_scene_name.c | 10 +- .../nfc_maker/scenes/nfc_maker_scene_phone.c | 8 +- .../nfc_maker/scenes/nfc_maker_scene_text.c | 8 +- .../nfc_maker/scenes/nfc_maker_scene_url.c | 8 +- .../nfc_maker/scenes/nfc_maker_scene_wifi.c | 8 +- .../scenes/nfc_maker_scene_wifi_pass.c | 8 +- 22 files changed, 966 insertions(+), 39 deletions(-) create mode 100644 applications/external/nfc_maker/assets/KeyBackspaceSelected_16x9.png create mode 100644 applications/external/nfc_maker/assets/KeyBackspace_16x9.png create mode 100644 applications/external/nfc_maker/assets/KeyKeyboardSelected_10x11.png create mode 100644 applications/external/nfc_maker/assets/KeyKeyboard_10x11.png create mode 100644 applications/external/nfc_maker/assets/KeySaveSelected_24x11.png create mode 100644 applications/external/nfc_maker/assets/KeySave_24x11.png create mode 100644 applications/external/nfc_maker/assets/WarningDolphin_45x42.png create mode 100644 applications/external/nfc_maker/nfc_maker_text_input.c create mode 100644 applications/external/nfc_maker/nfc_maker_text_input.h create mode 100644 applications/external/nfc_maker/nfc_maker_validators.c create mode 100644 applications/external/nfc_maker/nfc_maker_validators.h diff --git a/applications/external/nfc_maker/assets/KeyBackspaceSelected_16x9.png b/applications/external/nfc_maker/assets/KeyBackspaceSelected_16x9.png new file mode 100644 index 0000000000000000000000000000000000000000..7cc0759a8ca6acdb9b9c2e3dc00edde2f0e93a67 GIT binary patch literal 1812 zcmcIl&x_()N{W z-JN@vFI~T+Y1-v}FWiIo6?k5J;aT|qw)dv2CwcE-scA1=t)FMK&%d~)Y0rO}4EC%2 z=aK4R$F?2(hE6fX7H(UFBH{$t4v4EaKLer_Vi@d&Z#A)C)-lFal?RqJo6XEw%T&e4 zBEIiim|Bz~ut4QeR$2KDgeVQ)Gl9#&Q7)}LS*mHl<@TY>s++4|`B+t|9IGdATYvr+ zL&4Vp^Jy_zlt*w&PGkz$CD@V$zdYy`l2xi0C^cC%YIhY;r^KZCtp`aa)U15HX4E*y zkX5o{K-UPu6k#$T&@w-;?b`$g7%xpD(1BnTyO^;O$?)hRrco61v$A3tm;JC~04Xy` zM9{K5&YYn{cI-;z+O~({*abcDHnS;pNXu(4c!7VY__VG>?Z1?*P#iGU)eM+zGa?B_ zvgI?>CU%T`*JH?wZ6SP@IW~7zXzvsW>>M^Zjasu3fJoi8ARJ`vf+uoa+eOUrBobcB zw>cJ!4w<1pj@wleRYXcabz7&```zwtp@zu>K9qa+w)FmX*CD>+AZijr7d#lMB4r@7 zBxNIM<=Lo~JFR)Z8qvz(k!=8Gk?gq@8g zfS#k0rCF(l)r=K#a|A8Qr4h!%R?w1c= z{pq*skHW8}pZxgsP>68$^3NZ9>0PQ& Cw>kg- literal 0 HcmV?d00001 diff --git a/applications/external/nfc_maker/assets/KeyBackspace_16x9.png b/applications/external/nfc_maker/assets/KeyBackspace_16x9.png new file mode 100644 index 0000000000000000000000000000000000000000..9946232d953ef1cbfbf0e6754be6645e5ea2747b GIT binary patch literal 1829 zcmcIl&u`pB6gEEvMG+BPN`-{wNT>+Lo*8@XwOcpZ?1t{5I;81J4Y!WR<6SFjkFlNX zCgRjnK|!3jpo$Y0E}Xb=;LeTzpnm{T)f-4i;dy_hpfu#tmAsxAzxTcGz4y(`m)l!6 zS1w(-q$tWtuiM#y_bNQEzxE>h|J=PM>Pg=HtW=aY-mae)lh*~S0I8^$I!Q-a=}mlXitE9+UN$s!YEtd_TB{DI?graxTNXmKb&NR1RCQdP z*p_AEk5q~&HgLlr6cO9QmPZ_Q{?i~@5yjq4=i_-SnEBeUs&daT#^bR*Hg#DH4C1=3 zfvG_$0t-|gW)+*DtXx|lbVSLEB(D;gsWl=C<$mRBz;u>EnlE9qa$Y7Vm@#3wL3CWF zv@i^U^G(xqX_e|ijf0zqnN0f5E;9~PYWYyXtSU!}MEQj(L+?JpJ#W3Q_ zfcbtgnwBTxh8T$yuuHHdQ+~PEE(EJ&(U)?xXw>#1qDqNQ)vI@tERy5$gPPIYL3CIp zd=0ur5T*!|K7p3G9x*>8*u!{c8h{QWRntB?yEl08lWCYa({L}SbyS-h=I2pl*a_8oT+S_c~#IXiq#zs}!z^4spCcOR_0+*o_q`N6;X{rjK1`QsBs`Gcx|z4v#k QTVG_o&8^N)8~5)21Ktij=l}o! literal 0 HcmV?d00001 diff --git a/applications/external/nfc_maker/assets/KeyKeyboardSelected_10x11.png b/applications/external/nfc_maker/assets/KeyKeyboardSelected_10x11.png new file mode 100644 index 0000000000000000000000000000000000000000..231880386a9d9e83911088c9fcd083f84a7f75bb GIT binary patch literal 7210 zcmeHMc{G&m`=?Ublaz#}DWMw1jBO@scCroG3eED&7|aYa!&oaSQQ1?BvQr3^B_u>D zRI(HaN!GGvr}BHKx3~9vzvukUd(Q9oUvtjPbKlo}U7!29KG${M=ef>=S(q8{^N8_q zaB%P&8R}xd=jxbu^9JyDl++f>!NK>$&)SZO!LlG8bQ+QD4nUZ`9smUJArm<`d^+pBC6Dvw@S z{-)=@qQ^b|b+J}=KD@%AUv=la?m*JB2h-;tO5d8_imCrneonb*>iaiOoi~|NgFw@_ z>-`^xAU-r*IlrN-```Pz{aJjIOYe6%&l?S#KG|D$Cg<#&2dHBbiv7Hj8*N; zvpssiU{m_6Dsp$aNSFHK(;jp`NzI2;_pfRP-p$Ih1Qswm1DPBQr;lPomFj({Au*WtuGPPB=1`JJ~?+kaqp}DZ~9^g`Gj^RetXd*K0SH zJ19>d_hxz4gfY4o0~P!|>%7uPfv>JPngvYNlF~X@9cNkQ$44tEW#w;Kja|NWA?QYe z&H9z@Ym4K8Z!j`;{@pL7VRsr)Udlw5{+SzC-N*UwvONzkOf40U z>Rp-(=l&{CL^|2;(~ASTgnOY>356$qP_4Gxk;-pPt_!<)6839}w2C0ZH+P73R~zoA zFn_%N@Ixg{p$8YrhfCc{1rmh9hGTc&tOBI$_UL{wII{nO>x{xZV%vvv9Gd= zx{Pyg%#5TyO)8)1GAXF#*X)gq4!Nw>aI4h}Lk`(VVk4#x70O{KzJ)ax55nwywR#plr`5U|#GaS+K)ep~wM#|o9F=~q!f|G)!`qK75Qg1vNZBX8DGrBe2k!xwX z8B1u3=g$?|8;o_>aV_xi%Ti&>@Gj@N7luANROW9+BgM*T`r}Va1Gg8a0=FhYCAQ^Q z$qO!tS~(8BA870=lvwJyG|^ZNKy+-SwRsn`(Ul~Jjs4jZ$SbmC&)D64$#vG5B_l;1 z6Gq7f(^ECck_j$KLHIjw&JR3@bTuk>{YbD=Q_Yu=+$iWKA`Nur?CliUD~Z;CZ_axwEAz6nXHiQ|V(3?+8UAD0poEjPNp z!=4qc+*xD0C(f9CuE+RU>&Is!iU}1;H!p|xdE`EA_152&_U7A!#0%R^F}jGL46$AH zvN_wVQx**-Ns@z5UW{xuK9(a%@<76{xaxVs#0U2#!jvjihd!`91^f#PV{Xfmd#WC~~ete1cf9 z+fj!7dz04|rn`8u$6klHW{xx~EZCu6o1cGPbJWqCUzB9NRq;ubLEU}+i?7e;1jRO# z+c{ru?F{Ov**2A$KZvV~MLjJYOzFJ>b+Gsv=Wq86Uv;tPMcyPSNYh|?cDLcfjI)e0 zEgRho44AL@mP}3v&FHAz33PG8oo?9Vb|vIkE!{HY(6E?&)p~USUztO-==j{D_fs6S z?pF_^Bdo5;urkh85bzqMmr}VJc)0?O`vj`7lLMz__ujs7DdzNS>!LP-??O_Dl|$$x z(M@70&Y@Mj7#E-J^wvy&+wR6r`^mm7(>;3~#7{quo|mn0V6+)CDFp+iWon z-**4Ih^W!fEm`Gp=WC&lQbJBBh;#ziZNeg^@P<1}R9Y)$&fPxouwzgtChxVH{2fbT z7-ML@+(Gz`+2evrWYre4V*q(DPP-|sg&1b{zTZPK?C?82<8e2u1J9z1O4TpDf8~|> zQr-TE=>9_QAhl1O%=OcsA;;egY%+@ebo;AaQD>RihkW?Hv6!1Sf>aUCvx2DFFku1t z8?)QiCr6ChZuLJ(G#k%VIv}&Cl8YK^T6bDx!*roc!1fJo`f{HIYNQY{K72ffUC-gI zHAJe!xZ-6L@8+3qu1J>^FSMW$Bzd>@SHWbX`NXDAH0sD0oW49iZ%}Biku~Bla&n?~ zyN3S}=Wh!_U(4MK+Y3^f6)nlt2<A+q)6|<9u^{Hh0X&}JX;5(Xg=2C>r zm*t^Z%&r-}cdW^qkgAfDef~9dQ+ya$#WWa%<4^$Wu2ukS9Z0liiAG0pbA$!)Z8Uq#Yfwh zqDg$_FNsX-I&Gz~l)6~`DniZiIAi=^*anaCQ?RJRpWoA+CNfYfFRrLmNlt#|dYDyV zpG^9Cyk=epmzRvzua??W$}-Q1qJ>r{2W{4p)|Ajyz7&26GjQgVThTD3T~A7+KtL>2 zGA&c-k)Y>0e|&?u1$Hv^ob>H&0m~O1Jcn$o$Jtkm5up`aa_ui!xZa~x)^6U4TW)b& zX{S5zW}TE8yk=8gKt-hCzq0#yOAc+e?UX9q{oOk>RHWdzN;=6VbEW&Sd7|gcLiwfn zCR}bkzxZUcpHA(1-qVnk7fqEe>m7Zy8`vEl55;N@yxOrZ*x8GaBeBg4zoGspsbc@_ z@w1(qvvS(hFkPFYCWyWUWbS#&-W7)O`^h#J^$DLDbs)c+t41)8f)SO@HUMj|=3!Nt-&#P)G@e3IF#4Ecrw~5{EoL=*TYvGGo1>S-guq# zgWPpb%Gi2x{V5fhZb=HwZ!WusFW8K<1vJBkgJ@Cqo~K$2z74umF0ZGT;1&wyOi*5L z9~bc=Bi_7zobDi!)F~xX>k@hAp_OAdUu;q!%Az#WC8MP>HfaZu+^NvNKzbEIwCCpwD-o3Xa;iXcb_; z1H+*~zx9!AEwVmQjWXJ4;wbsZu7|K>J}S{JtN8s8rP1r#%z-!4us4BM^Zko8sxMkU zfSmQZr@Q2XJL8gmI`Qrvp4(L5Lx*(o6=YGB=MTFMs-`QQZ z)5s~^@J?DzB1yE+X89hA86oig#t7bg$m2lwNH#R8LCztxS8s8YluL4}d3Yx^$o80w zacig)w3_dOwbHoGU}CG#>+rMDZ}9UYDO#T!-v+u0yEk7Q?Y^12BtAbat;d<&?M3TP z)Lkx2UliNBk`(o#U378&oO|VyXH}Z)2_*AUD7CxJz0)Z>Btb8yxiet~>!O{XDoRWc z=sZc5E3NSo-z3Rq0~NV;fTRZT{o@InNIke(DtO~jN$j~feLel zkx|b!@dQP>7#7{q2|r5CDt6HNbadaHo9#!J_sGqjFy&YnN^Sa2CWFu|=vnG8Db`}j_G%ze?xY__Z+*K=t$HMC|n%BrJ@v)+*XbjmpV zCV%2!dz0AQG)MHZua-;X5T}|Fd@u<86oI z^A*lpZr5T9ikrDOI5?qX9UTiJ9i6{A8nBPKek1CxajnI+kgBXS=z(A;RAA?c!=3ey za<=gB+_izDGgV;QV?|@G^zB;MzXX@q@W|G~)?==!`O%|8PO4vbUtoM+>EVsom6#EK z_{=^SqoAEz?(9L<2mT8%_U*f3Z0P5O@7%>h({UlMuU(zZNnW0QZctleNXls=_;QB_ zdipyMuO4&nn)5g4+jMuA6nWpNtrPl2gty~!F+R9cYGahE7e?yJ#&W$Uhv^q18_#g# zamEfU);I8-qeklVBjd90miSaZs~1|-VI!NC#6o;1?oh4_J?3o!6>vImn)qe50Ou{fF+QymHg z*CBuTNAWN<{RK~D{A2;-L*57LA+I0@m#0wVf45*T^}IolpAP+33x+k=M$2OW2F;6( z2lTuFDs%7e5Cr@$dk-(V`&u{zygc9zP(W1%xU0fHwlpv@wfJSRN&$&X@mRA0$^M5X zlT7@Ztbh2ny0R9|?~Z`xzi|Jd{a5U3%Al61DO#6?_gZz&NLL-Yx<8sg!;=ZpiDj{I11RM^A$K#X;D1d;66I6eLGNLk=SSlV^g#y9l$RG}YQc)x* zsUTrEWmQ#}B1)AA!x2?M2pmos1t%(kIQZWn%;{vXDzWard$kHh0HJUQ6dq3`sKQk7 z$|^8LMI{x`8w3DTLgL_n0u~ELsw%8O5%6ez8l8d#(@CaaNr1cum9)07N;q2E!bly8 zkc0m%v2e#SiJ*Zx^eCC?<@5J~HJJifF|n&`Dk!U{AmAt^MT81cMMVYqw~`G&XMmNs zim3pXLn78zR?~t8g8_-fuGT3CuqFp%LF>=~ER#mJrqSHhp{p)IRxN)mn}WxQfMsHJ zu}lC2g(Hw?I0B7Ow1y+mNN|8S2#2HLzvgv{X%EZh)foi4rr4=9zm|a@?7HzBD0n# z*?;=NasgJe01^g+BVhkYnEcOxo))aobWI($gGVt;O??U-sm*G#& zK!5)~KR~vOSwT8}y5Z6&x`A8PBTVZMP{#YRdS&a^gaPJ@ k(Oa(fF60b8WFS2`E^HCx5!~3>143{Z>6z)~A2}KPKg=ZgNB{r; literal 0 HcmV?d00001 diff --git a/applications/external/nfc_maker/assets/KeyKeyboard_10x11.png b/applications/external/nfc_maker/assets/KeyKeyboard_10x11.png new file mode 100644 index 0000000000000000000000000000000000000000..1f4c03478f68cb15c74ef99888ce4faf50e0a140 GIT binary patch literal 7763 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 GFa8a7)lmol literal 0 HcmV?d00001 diff --git a/applications/external/nfc_maker/assets/KeySave_24x11.png b/applications/external/nfc_maker/assets/KeySave_24x11.png new file mode 100644 index 0000000000000000000000000000000000000000..e7dba987a04dad7dd96001913c55566dbde96c8e GIT binary patch literal 1863 zcmcIlO^6&t6dpxnjjSF75f9pQJZy|LUDdzSZ6$n-*6-2D5s-9_fx~uK( zotfQBVDX?Q(UXLzXF6aX)%U*l z-d9y`w^q+Do_PF3p-@5qOL5h2N9RU z^i-~BIziNECdw*wjUcQeOxncsbnKa>(*%1MPoPck0jC)~9$50g-#!ks+4LGwn$d`f zMy;%ZsA3Rsk2!`#ELuW>2#g3fF>;CFBHMCo-El0(@X1&g%&$qdl~*F4Kd~*B3^?Z1 z^bEmDf}0)Wn??sYC6l9$X;6esLO7#_ZCmDy?ZqU3l|%anS#wn!7%f39-Qp(l9fyJ- z(?=x}n~2%2PcX9#VmYdECvH{tWzv)!s%sn^Z&a(TMEXG=KBQ~smzBm!)h4cOBfSV| zapw6l2`LyY2x(Vnan#Li4>BO#dXPeox2Fr~f_P*4)DM)gJ3Y$sMNw8+?gqit>2PpJ znU9yygm%~yKzf8rCa_fc*^nlp(uJ1%rwg^aiBIX^Xz9mu$p0vPT2|JhQCGkYtEqW1 zTD})enxg%?Uw4c#Ggk#{pLa8zmSLH8=LI=?xR>pc=yYsHAgcQUxz^arx`9fR>e$sw zj@}Uy75!kQXF{tT9e=F+z^*!*3|n>nI6oucWq!(t2og`=40-O!tAE1z^ID@;X)nEd zVK7xqj`wg%Ed2Op{k=a*YZpKHX787$ zzhKuN9(?M5ojmn%xcU1}OP>$^`ZD?cW@lIaTn=x3xBtP#z16o~{qVMZ>hecsD?jQQ ME3387mS5lf8`39Il>h($ literal 0 HcmV?d00001 diff --git a/applications/external/nfc_maker/assets/WarningDolphin_45x42.png b/applications/external/nfc_maker/assets/WarningDolphin_45x42.png new file mode 100644 index 0000000000000000000000000000000000000000..d766ffbb444db1739f2ccd030e506e8bada11ee8 GIT binary patch literal 1139 zcmaJ=TWAz#6rQ4%BpO*okt7zz3Bkm=bK9L=XV}qhW_HceY#KHzP4Z$UGyf(-b}pUy z<8ESW=_MtCk6tj|`k)VrCbo(SMH0n`eW+KIU`wG5O`$IeMg)Vzf7adDhv+af=lqBB zo%5Z`zqhqzdu2s+1%_dji6%LPq#u2o%9fzN?;7Dlq6)^^VVjkKImH23RI|DPo-mXi zkOGP}@Wrnnf?-SQ^>jOIPc{pxWsr*JL*@+|p)oA7EpIDoAAoo_=+RA)c=F3Qf$N$` ze9k55q%DD7y=l+^ZG$aob+Aw6HDcRVJdzhs00Te;&l_3O74jlch$|r7GgAa!aDjay z@rG1;vK5ys2jF3n@vAgV<6)izn!k6Qhd>D(EhD7l zcrhJ1i9|1iwm?z2T#n2INXzM=7@p@Tnx$CQk39VDfC-hn-*jtB5oF-1j&4KUGI1}W z(rxuakw9eMRAJc3%8 zlBq3$QTyJX$a6$&1ldyi4Pe5AEE32Sg@vDzY~7qR?1u@oXh zd9(fBtV<@eK%Tm=yy&p7{=h^#@1W)WFFSe!U5pP~o71uR`FW)7xc*=d5_b}EG@XBZ z@<7MRp-;+|o}SzJvMyfx>37Y4etBizf%0H*zaIF?2ObZt?$D;{o|esJ z*PgAOIO^*8tL%z2)|}k$DP5kN5}8qo*wNa8y?R2=%wO{gCD(`sHt}TzWQuK zMDIJap(nb2=7*ns*oDcRBbC23yy`kvKYV`ovU`a=EmxNv-90;;5r6+l8hQTp^u`Hn XX6*+%8gHC`h)Tl}u@-r>vFqE{F~5F& literal 0 HcmV?d00001 diff --git a/applications/external/nfc_maker/nfc_maker.c b/applications/external/nfc_maker/nfc_maker.c index 578054ade..0f27b145e 100644 --- a/applications/external/nfc_maker/nfc_maker.c +++ b/applications/external/nfc_maker/nfc_maker.c @@ -35,9 +35,11 @@ NfcMaker* nfc_maker_alloc() { view_dispatcher_add_view( app->view_dispatcher, NfcMakerViewSubmenu, submenu_get_view(app->submenu)); - app->text_input = text_input_alloc(); + app->text_input = nfc_maker_text_input_alloc(); view_dispatcher_add_view( - app->view_dispatcher, NfcMakerViewTextInput, text_input_get_view(app->text_input)); + app->view_dispatcher, + NfcMakerViewTextInput, + nfc_maker_text_input_get_view(app->text_input)); app->byte_input = byte_input_alloc(); view_dispatcher_add_view( @@ -56,7 +58,7 @@ void nfc_maker_free(NfcMaker* app) { view_dispatcher_remove_view(app->view_dispatcher, NfcMakerViewSubmenu); submenu_free(app->submenu); view_dispatcher_remove_view(app->view_dispatcher, NfcMakerViewTextInput); - text_input_free(app->text_input); + nfc_maker_text_input_free(app->text_input); view_dispatcher_remove_view(app->view_dispatcher, NfcMakerViewByteInput); byte_input_free(app->byte_input); view_dispatcher_remove_view(app->view_dispatcher, NfcMakerViewPopup); diff --git a/applications/external/nfc_maker/nfc_maker.h b/applications/external/nfc_maker/nfc_maker.h index 76a7a2538..f776d0fa0 100644 --- a/applications/external/nfc_maker/nfc_maker.h +++ b/applications/external/nfc_maker/nfc_maker.h @@ -8,7 +8,7 @@ #include #include "nfc_maker_icons.h" #include -#include +#include "nfc_maker_text_input.h" #include #include #include "scenes/nfc_maker_scene.h" @@ -42,7 +42,7 @@ typedef struct { SceneManager* scene_manager; ViewDispatcher* view_dispatcher; Submenu* submenu; - TextInput* text_input; + NFCMaker_TextInput* text_input; ByteInput* byte_input; Popup* popup; diff --git a/applications/external/nfc_maker/nfc_maker_text_input.c b/applications/external/nfc_maker/nfc_maker_text_input.c new file mode 100644 index 000000000..c5b2b27d6 --- /dev/null +++ b/applications/external/nfc_maker/nfc_maker_text_input.c @@ -0,0 +1,762 @@ +#include "nfc_maker_text_input.h" +#include +#include "nfc_maker.h" +#include + +struct NFCMaker_TextInput { + View* view; + FuriTimer* timer; +}; + +typedef struct { + const char text; + const uint8_t x; + const uint8_t y; +} NFCMaker_TextInputKey; + +typedef struct { + const NFCMaker_TextInputKey* rows[3]; + const uint8_t keyboard_index; +} Keyboard; + +typedef struct { + const char* header; + char* text_buffer; + size_t text_buffer_size; + size_t minimum_length; + bool clear_default_text; + + bool cursor_select; + size_t cursor_pos; + + NFCMaker_TextInputCallback callback; + void* callback_context; + + uint8_t selected_row; + uint8_t selected_column; + uint8_t selected_keyboard; + + NFCMaker_TextInputValidatorCallback validator_callback; + void* validator_callback_context; + FuriString* validator_text; + bool validator_message_visible; +} NFCMaker_TextInputModel; + +static const uint8_t keyboard_origin_x = 1; +static const uint8_t keyboard_origin_y = 29; +static const uint8_t keyboard_row_count = 3; +static const uint8_t keyboard_count = 2; + +#define ENTER_KEY '\r' +#define BACKSPACE_KEY '\b' +#define SWITCH_KEYBOARD_KEY 0xfe + +static const NFCMaker_TextInputKey keyboard_keys_row_1[] = { + {'q', 1, 8}, + {'w', 10, 8}, + {'e', 19, 8}, + {'r', 28, 8}, + {'t', 37, 8}, + {'y', 46, 8}, + {'u', 55, 8}, + {'i', 64, 8}, + {'o', 73, 8}, + {'p', 82, 8}, + {'0', 91, 8}, + {'1', 100, 8}, + {'2', 110, 8}, + {'3', 120, 8}, +}; + +static const NFCMaker_TextInputKey keyboard_keys_row_2[] = { + {'a', 1, 20}, + {'s', 10, 20}, + {'d', 19, 20}, + {'f', 28, 20}, + {'g', 37, 20}, + {'h', 46, 20}, + {'j', 55, 20}, + {'k', 64, 20}, + {'l', 73, 20}, + {BACKSPACE_KEY, 82, 12}, + {'4', 100, 20}, + {'5', 110, 20}, + {'6', 120, 20}, +}; + +static const NFCMaker_TextInputKey keyboard_keys_row_3[] = { + {SWITCH_KEYBOARD_KEY, 1, 23}, + {'z', 13, 32}, + {'x', 21, 32}, + {'c', 28, 32}, + {'v', 36, 32}, + {'b', 44, 32}, + {'n', 52, 32}, + {'m', 59, 32}, + {'_', 67, 32}, + {ENTER_KEY, 74, 23}, + {'7', 100, 32}, + {'8', 110, 32}, + {'9', 120, 32}, +}; + +static const NFCMaker_TextInputKey symbol_keyboard_keys_row_1[] = { + {'!', 2, 8}, + {'@', 12, 8}, + {'#', 22, 8}, + {'$', 32, 8}, + {'%', 42, 8}, + {'^', 52, 8}, + {'&', 62, 8}, + {'(', 71, 8}, + {')', 81, 8}, + {'0', 91, 8}, + {'1', 100, 8}, + {'2', 110, 8}, + {'3', 120, 8}, +}; + +static const NFCMaker_TextInputKey symbol_keyboard_keys_row_2[] = { + {'~', 2, 20}, + {'+', 12, 20}, + {'-', 22, 20}, + {'=', 32, 20}, + {'[', 42, 20}, + {']', 52, 20}, + {'{', 62, 20}, + {'}', 72, 20}, + {BACKSPACE_KEY, 82, 12}, + {'4', 100, 20}, + {'5', 110, 20}, + {'6', 120, 20}, +}; + +static const NFCMaker_TextInputKey symbol_keyboard_keys_row_3[] = { + {SWITCH_KEYBOARD_KEY, 1, 23}, + {'.', 15, 32}, + {',', 29, 32}, + {':', 41, 32}, + {'/', 53, 32}, + {'\\', 65, 32}, + {ENTER_KEY, 74, 23}, + {'7', 100, 32}, + {'8', 110, 32}, + {'9', 120, 32}, +}; + +static const Keyboard keyboard = { + .rows = + { + keyboard_keys_row_1, + keyboard_keys_row_2, + keyboard_keys_row_3, + }, + .keyboard_index = 0, +}; + +static const Keyboard symbol_keyboard = { + .rows = + { + symbol_keyboard_keys_row_1, + symbol_keyboard_keys_row_2, + symbol_keyboard_keys_row_3, + }, + .keyboard_index = 1, +}; + +static const Keyboard* keyboards[] = { + &keyboard, + &symbol_keyboard, +}; + +static void switch_keyboard(NFCMaker_TextInputModel* model) { + model->selected_keyboard = (model->selected_keyboard + 1) % keyboard_count; +} + +static uint8_t get_row_size(const Keyboard* keyboard, uint8_t row_index) { + uint8_t row_size = 0; + if(keyboard == &symbol_keyboard) { + switch(row_index + 1) { + case 1: + row_size = COUNT_OF(symbol_keyboard_keys_row_1); + break; + case 2: + row_size = COUNT_OF(symbol_keyboard_keys_row_2); + break; + case 3: + row_size = COUNT_OF(symbol_keyboard_keys_row_3); + break; + default: + furi_crash(NULL); + } + } else { + switch(row_index + 1) { + case 1: + row_size = COUNT_OF(keyboard_keys_row_1); + break; + case 2: + row_size = COUNT_OF(keyboard_keys_row_2); + break; + case 3: + row_size = COUNT_OF(keyboard_keys_row_3); + break; + default: + furi_crash(NULL); + } + } + + return row_size; +} + +static const NFCMaker_TextInputKey* get_row(const Keyboard* keyboard, uint8_t row_index) { + const NFCMaker_TextInputKey* row = NULL; + if(row_index < 3) { + row = keyboard->rows[row_index]; + } else { + furi_crash(NULL); + } + + return row; +} + +static char get_selected_char(NFCMaker_TextInputModel* model) { + return get_row( + keyboards[model->selected_keyboard], model->selected_row)[model->selected_column] + .text; +} + +static bool char_is_lowercase(char letter) { + return (letter >= 0x61 && letter <= 0x7A); +} + +static char char_to_uppercase(const char letter) { + if(letter == '_') { + return 0x20; + } else if(char_is_lowercase(letter)) { + return (letter - 0x20); + } else { + return letter; + } +} + +static void nfc_maker_text_input_backspace_cb(NFCMaker_TextInputModel* model) { + if(model->clear_default_text) { + model->text_buffer[0] = 0; + model->cursor_pos = 0; + } else if(model->cursor_pos > 0) { + char* move = model->text_buffer + model->cursor_pos; + memmove(move - 1, move, strlen(move) + 1); + model->cursor_pos--; + } +} + +static void nfc_maker_text_input_view_draw_callback(Canvas* canvas, void* _model) { + NFCMaker_TextInputModel* model = _model; + uint8_t text_length = model->text_buffer ? strlen(model->text_buffer) : 0; + uint8_t needed_string_width = canvas_width(canvas) - 8; + uint8_t start_pos = 4; + + model->cursor_pos = model->cursor_pos > text_length ? text_length : model->cursor_pos; + size_t cursor_pos = model->cursor_pos; + + canvas_clear(canvas); + canvas_set_color(canvas, ColorBlack); + + canvas_draw_str(canvas, 2, 8, model->header); + elements_slightly_rounded_frame(canvas, 1, 12, 126, 15); + + char buf[model->text_buffer_size + 1]; + if(model->text_buffer) { + strlcpy(buf, model->text_buffer, sizeof(buf)); + } + char* str = buf; + + if(model->clear_default_text) { + elements_slightly_rounded_box( + canvas, start_pos - 1, 14, canvas_string_width(canvas, str) + 2, 10); + canvas_set_color(canvas, ColorWhite); + } else { + char* move = str + cursor_pos; + memmove(move + 1, move, strlen(move) + 1); + str[cursor_pos] = '|'; + } + + if(cursor_pos > 0 && canvas_string_width(canvas, str) > needed_string_width) { + canvas_draw_str(canvas, start_pos, 22, "..."); + start_pos += 6; + needed_string_width -= 8; + for(uint32_t off = 0; + strlen(str) && canvas_string_width(canvas, str) > needed_string_width && + off < cursor_pos; + off++) { + str++; + } + } + + if(canvas_string_width(canvas, str) > needed_string_width) { + needed_string_width -= 4; + size_t len = strlen(str); + while(len && canvas_string_width(canvas, str) > needed_string_width) { + str[len--] = '\0'; + } + strcat(str, "..."); + } + + canvas_draw_str(canvas, start_pos, 22, str); + + canvas_set_font(canvas, FontKeyboard); + + for(uint8_t row = 0; row < keyboard_row_count; row++) { + const uint8_t column_count = get_row_size(keyboards[model->selected_keyboard], row); + const NFCMaker_TextInputKey* keys = get_row(keyboards[model->selected_keyboard], row); + + for(size_t column = 0; column < column_count; column++) { + bool selected = !model->cursor_select && model->selected_row == row && + model->selected_column == column; + const Icon* icon = NULL; + if(keys[column].text == ENTER_KEY) { + icon = selected ? &I_KeySaveSelected_24x11 : &I_KeySave_24x11; + } else if(keys[column].text == SWITCH_KEYBOARD_KEY) { + icon = selected ? &I_KeyKeyboardSelected_10x11 : &I_KeyKeyboard_10x11; + } else if(keys[column].text == BACKSPACE_KEY) { + icon = selected ? &I_KeyBackspaceSelected_16x9 : &I_KeyBackspace_16x9; + } + canvas_set_color(canvas, ColorBlack); + if(icon != NULL) { + canvas_draw_icon( + canvas, + keyboard_origin_x + keys[column].x, + keyboard_origin_y + keys[column].y, + icon); + } else { + if(selected) { + canvas_draw_box( + canvas, + keyboard_origin_x + keys[column].x - 1, + keyboard_origin_y + keys[column].y - 8, + 7, + 10); + canvas_set_color(canvas, ColorWhite); + } + + if(model->clear_default_text || text_length == 0) { + canvas_draw_glyph( + canvas, + keyboard_origin_x + keys[column].x, + keyboard_origin_y + keys[column].y, + char_to_uppercase(keys[column].text)); + } else { + canvas_draw_glyph( + canvas, + keyboard_origin_x + keys[column].x, + keyboard_origin_y + keys[column].y, + keys[column].text); + } + } + } + } + if(model->validator_message_visible) { + canvas_set_font(canvas, FontSecondary); + canvas_set_color(canvas, ColorWhite); + canvas_draw_box(canvas, 8, 10, 110, 48); + canvas_set_color(canvas, ColorBlack); + canvas_draw_icon(canvas, 10, 14, &I_WarningDolphin_45x42); + canvas_draw_rframe(canvas, 8, 8, 112, 50, 3); + canvas_draw_rframe(canvas, 9, 9, 110, 48, 2); + elements_multiline_text(canvas, 62, 20, furi_string_get_cstr(model->validator_text)); + canvas_set_font(canvas, FontKeyboard); + } +} + +static void nfc_maker_text_input_handle_up( + NFCMaker_TextInput* nfc_maker_text_input, + NFCMaker_TextInputModel* model) { + UNUSED(nfc_maker_text_input); + if(model->selected_row > 0) { + model->selected_row--; + if(model->selected_row == 0 && + model->selected_column > + get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 6) { + model->selected_column = model->selected_column + 1; + } + if(model->selected_row == 1 && + model->selected_keyboard == symbol_keyboard.keyboard_index) { + if(model->selected_column > 5) + model->selected_column += 2; + else if(model->selected_column > 1) + model->selected_column += 1; + } + } else { + model->cursor_select = true; + model->clear_default_text = false; + } +} + +static void nfc_maker_text_input_handle_down( + NFCMaker_TextInput* nfc_maker_text_input, + NFCMaker_TextInputModel* model) { + UNUSED(nfc_maker_text_input); + if(model->cursor_select) { + model->cursor_select = false; + } else if(model->selected_row < keyboard_row_count - 1) { + model->selected_row++; + if(model->selected_row == 1 && + model->selected_column > + get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 4) { + model->selected_column = model->selected_column - 1; + } + if(model->selected_row == 2 && + model->selected_keyboard == symbol_keyboard.keyboard_index) { + if(model->selected_column > 7) + model->selected_column -= 2; + else if(model->selected_column > 1) + model->selected_column -= 1; + } + } +} + +static void nfc_maker_text_input_handle_left( + NFCMaker_TextInput* nfc_maker_text_input, + NFCMaker_TextInputModel* model) { + UNUSED(nfc_maker_text_input); + if(model->cursor_select) { + if(model->cursor_pos > 0) { + model->cursor_pos = CLAMP(model->cursor_pos - 1, strlen(model->text_buffer), 0u); + } + } else if(model->selected_column > 0) { + model->selected_column--; + } else { + model->selected_column = + get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 1; + } +} + +static void nfc_maker_text_input_handle_right( + NFCMaker_TextInput* nfc_maker_text_input, + NFCMaker_TextInputModel* model) { + UNUSED(nfc_maker_text_input); + if(model->cursor_select) { + model->cursor_pos = CLAMP(model->cursor_pos + 1, strlen(model->text_buffer), 0u); + } else if( + model->selected_column < + get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 1) { + model->selected_column++; + } else { + model->selected_column = 0; + } +} + +static void nfc_maker_text_input_handle_ok( + NFCMaker_TextInput* nfc_maker_text_input, + NFCMaker_TextInputModel* model, + InputType type) { + if(model->cursor_select) return; + bool shift = type == InputTypeLong; + bool repeat = type == InputTypeRepeat; + char selected = get_selected_char(model); + size_t text_length = strlen(model->text_buffer); + + if(selected == ENTER_KEY) { + if(model->validator_callback && + (!model->validator_callback( + model->text_buffer, model->validator_text, model->validator_callback_context))) { + model->validator_message_visible = true; + furi_timer_start(nfc_maker_text_input->timer, furi_kernel_get_tick_frequency() * 4); + } else if(model->callback != 0 && text_length >= model->minimum_length) { + model->callback(model->callback_context); + } + } else if(selected == SWITCH_KEYBOARD_KEY) { + switch_keyboard(model); + } else { + if(selected == BACKSPACE_KEY) { + nfc_maker_text_input_backspace_cb(model); + } else if(!repeat) { + if(model->clear_default_text) { + text_length = 0; + } + if(text_length < (model->text_buffer_size - 1)) { + if(shift != (text_length == 0)) { + selected = char_to_uppercase(selected); + } + if(model->clear_default_text) { + model->text_buffer[0] = selected; + model->text_buffer[1] = '\0'; + model->cursor_pos = 1; + } else { + char* move = model->text_buffer + model->cursor_pos; + memmove(move + 1, move, strlen(move) + 1); + model->text_buffer[model->cursor_pos] = selected; + model->cursor_pos++; + } + } + } + model->clear_default_text = false; + } +} + +static bool nfc_maker_text_input_view_input_callback(InputEvent* event, void* context) { + NFCMaker_TextInput* nfc_maker_text_input = context; + furi_assert(nfc_maker_text_input); + + bool consumed = false; + + // Acquire model + NFCMaker_TextInputModel* model = view_get_model(nfc_maker_text_input->view); + + if((!(event->type == InputTypePress) && !(event->type == InputTypeRelease)) && + model->validator_message_visible) { + model->validator_message_visible = false; + consumed = true; + } else if(event->type == InputTypeShort) { + consumed = true; + switch(event->key) { + case InputKeyUp: + nfc_maker_text_input_handle_up(nfc_maker_text_input, model); + break; + case InputKeyDown: + nfc_maker_text_input_handle_down(nfc_maker_text_input, model); + break; + case InputKeyLeft: + nfc_maker_text_input_handle_left(nfc_maker_text_input, model); + break; + case InputKeyRight: + nfc_maker_text_input_handle_right(nfc_maker_text_input, model); + break; + case InputKeyOk: + nfc_maker_text_input_handle_ok(nfc_maker_text_input, model, event->type); + break; + default: + consumed = false; + break; + } + } else if(event->type == InputTypeLong) { + consumed = true; + switch(event->key) { + case InputKeyUp: + nfc_maker_text_input_handle_up(nfc_maker_text_input, model); + break; + case InputKeyDown: + nfc_maker_text_input_handle_down(nfc_maker_text_input, model); + break; + case InputKeyLeft: + nfc_maker_text_input_handle_left(nfc_maker_text_input, model); + break; + case InputKeyRight: + nfc_maker_text_input_handle_right(nfc_maker_text_input, model); + break; + case InputKeyOk: + nfc_maker_text_input_handle_ok(nfc_maker_text_input, model, event->type); + break; + case InputKeyBack: + nfc_maker_text_input_backspace_cb(model); + break; + default: + consumed = false; + break; + } + } else if(event->type == InputTypeRepeat) { + consumed = true; + switch(event->key) { + case InputKeyUp: + nfc_maker_text_input_handle_up(nfc_maker_text_input, model); + break; + case InputKeyDown: + nfc_maker_text_input_handle_down(nfc_maker_text_input, model); + break; + case InputKeyLeft: + nfc_maker_text_input_handle_left(nfc_maker_text_input, model); + break; + case InputKeyRight: + nfc_maker_text_input_handle_right(nfc_maker_text_input, model); + break; + case InputKeyOk: + nfc_maker_text_input_handle_ok(nfc_maker_text_input, model, event->type); + break; + case InputKeyBack: + nfc_maker_text_input_backspace_cb(model); + break; + default: + consumed = false; + break; + } + } + + // Commit model + view_commit_model(nfc_maker_text_input->view, consumed); + + return consumed; +} + +void nfc_maker_text_input_timer_callback(void* context) { + furi_assert(context); + NFCMaker_TextInput* nfc_maker_text_input = context; + + with_view_model( + nfc_maker_text_input->view, + NFCMaker_TextInputModel * model, + { model->validator_message_visible = false; }, + true); +} + +NFCMaker_TextInput* nfc_maker_text_input_alloc() { + NFCMaker_TextInput* nfc_maker_text_input = malloc(sizeof(NFCMaker_TextInput)); + nfc_maker_text_input->view = view_alloc(); + view_set_context(nfc_maker_text_input->view, nfc_maker_text_input); + view_allocate_model( + nfc_maker_text_input->view, ViewModelTypeLocking, sizeof(NFCMaker_TextInputModel)); + view_set_draw_callback(nfc_maker_text_input->view, nfc_maker_text_input_view_draw_callback); + view_set_input_callback(nfc_maker_text_input->view, nfc_maker_text_input_view_input_callback); + + nfc_maker_text_input->timer = furi_timer_alloc( + nfc_maker_text_input_timer_callback, FuriTimerTypeOnce, nfc_maker_text_input); + + with_view_model( + nfc_maker_text_input->view, + NFCMaker_TextInputModel * model, + { + model->validator_text = furi_string_alloc(); + model->minimum_length = 1; + model->cursor_pos = 0; + model->cursor_select = false; + }, + false); + + nfc_maker_text_input_reset(nfc_maker_text_input); + + return nfc_maker_text_input; +} + +void nfc_maker_text_input_free(NFCMaker_TextInput* nfc_maker_text_input) { + furi_assert(nfc_maker_text_input); + with_view_model( + nfc_maker_text_input->view, + NFCMaker_TextInputModel * model, + { furi_string_free(model->validator_text); }, + false); + + // Send stop command + furi_timer_stop(nfc_maker_text_input->timer); + // Release allocated memory + furi_timer_free(nfc_maker_text_input->timer); + + view_free(nfc_maker_text_input->view); + + free(nfc_maker_text_input); +} + +void nfc_maker_text_input_reset(NFCMaker_TextInput* nfc_maker_text_input) { + furi_assert(nfc_maker_text_input); + with_view_model( + nfc_maker_text_input->view, + NFCMaker_TextInputModel * model, + { + model->header = ""; + model->selected_row = 0; + model->selected_column = 0; + model->selected_keyboard = 0; + model->minimum_length = 1; + model->clear_default_text = false; + model->cursor_pos = 0; + model->cursor_select = false; + model->text_buffer = NULL; + model->text_buffer_size = 0; + model->callback = NULL; + model->callback_context = NULL; + model->validator_callback = NULL; + model->validator_callback_context = NULL; + furi_string_reset(model->validator_text); + model->validator_message_visible = false; + }, + true); +} + +View* nfc_maker_text_input_get_view(NFCMaker_TextInput* nfc_maker_text_input) { + furi_assert(nfc_maker_text_input); + return nfc_maker_text_input->view; +} + +void nfc_maker_text_input_set_result_callback( + NFCMaker_TextInput* nfc_maker_text_input, + NFCMaker_TextInputCallback callback, + void* callback_context, + char* text_buffer, + size_t text_buffer_size, + bool clear_default_text) { + with_view_model( + nfc_maker_text_input->view, + NFCMaker_TextInputModel * model, + { + model->callback = callback; + model->callback_context = callback_context; + model->text_buffer = text_buffer; + model->text_buffer_size = text_buffer_size; + model->clear_default_text = clear_default_text; + model->cursor_select = false; + if(text_buffer && text_buffer[0] != '\0') { + model->cursor_pos = strlen(text_buffer); + // Set focus on Save + model->selected_row = 2; + model->selected_column = 9; + model->selected_keyboard = 0; + } else { + model->cursor_pos = 0; + } + }, + true); +} + +void nfc_maker_text_input_set_minimum_length( + NFCMaker_TextInput* nfc_maker_text_input, + size_t minimum_length) { + with_view_model( + nfc_maker_text_input->view, + NFCMaker_TextInputModel * model, + { model->minimum_length = minimum_length; }, + true); +} + +void nfc_maker_text_input_set_validator( + NFCMaker_TextInput* nfc_maker_text_input, + NFCMaker_TextInputValidatorCallback callback, + void* callback_context) { + with_view_model( + nfc_maker_text_input->view, + NFCMaker_TextInputModel * model, + { + model->validator_callback = callback; + model->validator_callback_context = callback_context; + }, + true); +} + +NFCMaker_TextInputValidatorCallback + nfc_maker_text_input_get_validator_callback(NFCMaker_TextInput* nfc_maker_text_input) { + NFCMaker_TextInputValidatorCallback validator_callback = NULL; + with_view_model( + nfc_maker_text_input->view, + NFCMaker_TextInputModel * model, + { validator_callback = model->validator_callback; }, + false); + return validator_callback; +} + +void* nfc_maker_text_input_get_validator_callback_context( + NFCMaker_TextInput* nfc_maker_text_input) { + void* validator_callback_context = NULL; + with_view_model( + nfc_maker_text_input->view, + NFCMaker_TextInputModel * model, + { validator_callback_context = model->validator_callback_context; }, + false); + return validator_callback_context; +} + +void nfc_maker_text_input_set_header_text( + NFCMaker_TextInput* nfc_maker_text_input, + const char* text) { + with_view_model( + nfc_maker_text_input->view, + NFCMaker_TextInputModel * model, + { model->header = text; }, + true); +} diff --git a/applications/external/nfc_maker/nfc_maker_text_input.h b/applications/external/nfc_maker/nfc_maker_text_input.h new file mode 100644 index 000000000..91fa93e9d --- /dev/null +++ b/applications/external/nfc_maker/nfc_maker_text_input.h @@ -0,0 +1,85 @@ +#pragma once + +#include +#include "nfc_maker_validators.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Text input anonymous structure */ +typedef struct NFCMaker_TextInput NFCMaker_TextInput; +typedef void (*NFCMaker_TextInputCallback)(void* context); +typedef bool ( + *NFCMaker_TextInputValidatorCallback)(const char* text, FuriString* error, void* context); + +/** Allocate and initialize text input + * + * This text input is used to enter string + * + * @return NFCMaker_TextInput instance + */ +NFCMaker_TextInput* nfc_maker_text_input_alloc(); + +/** Deinitialize and free text input + * + * @param text_input NFCMaker_TextInput instance + */ +void nfc_maker_text_input_free(NFCMaker_TextInput* text_input); + +/** Clean text input view Note: this function does not free memory + * + * @param text_input Text input instance + */ +void nfc_maker_text_input_reset(NFCMaker_TextInput* text_input); + +/** Get text input view + * + * @param text_input NFCMaker_TextInput instance + * + * @return View instance that can be used for embedding + */ +View* nfc_maker_text_input_get_view(NFCMaker_TextInput* text_input); + +/** Set text input result callback + * + * @param text_input NFCMaker_TextInput instance + * @param callback callback fn + * @param callback_context callback context + * @param text_buffer pointer to YOUR text buffer, that we going + * to modify + * @param text_buffer_size YOUR text buffer size in bytes. Max string + * length will be text_buffer_size-1. + * @param clear_default_text clear text from text_buffer on first OK + * event + */ +void nfc_maker_text_input_set_result_callback( + NFCMaker_TextInput* text_input, + NFCMaker_TextInputCallback callback, + void* callback_context, + char* text_buffer, + size_t text_buffer_size, + bool clear_default_text); + +void nfc_maker_text_input_set_validator( + NFCMaker_TextInput* text_input, + NFCMaker_TextInputValidatorCallback callback, + void* callback_context); + +void nfc_maker_text_input_set_minimum_length(NFCMaker_TextInput* text_input, size_t minimum_length); + +NFCMaker_TextInputValidatorCallback + nfc_maker_text_input_get_validator_callback(NFCMaker_TextInput* text_input); + +void* nfc_maker_text_input_get_validator_callback_context(NFCMaker_TextInput* text_input); + +/** Set text input header text + * + * @param text_input NFCMaker_TextInput instance + * @param text text to be shown + */ +void nfc_maker_text_input_set_header_text(NFCMaker_TextInput* text_input, const char* text); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/applications/external/nfc_maker/nfc_maker_validators.c b/applications/external/nfc_maker/nfc_maker_validators.c new file mode 100644 index 000000000..77c1b7fb7 --- /dev/null +++ b/applications/external/nfc_maker/nfc_maker_validators.c @@ -0,0 +1,57 @@ +#include +#include "nfc_maker_validators.h" +#include + +struct ValidatorIsFile { + char* app_path_folder; + const char* app_extension; + char* current_name; +}; + +bool validator_is_file_callback(const char* text, FuriString* error, void* context) { + furi_assert(context); + ValidatorIsFile* instance = context; + + if(instance->current_name != NULL) { + if(strcmp(instance->current_name, text) == 0) { + return true; + } + } + + bool ret = true; + FuriString* path = furi_string_alloc_printf( + "%s/%s%s", instance->app_path_folder, text, instance->app_extension); + Storage* storage = furi_record_open(RECORD_STORAGE); + if(storage_common_stat(storage, furi_string_get_cstr(path), NULL) == FSE_OK) { + ret = false; + furi_string_printf(error, "This name\nexists!\nChoose\nanother one."); + } else { + ret = true; + } + furi_string_free(path); + furi_record_close(RECORD_STORAGE); + + return ret; +} + +ValidatorIsFile* validator_is_file_alloc_init( + const char* app_path_folder, + const char* app_extension, + const char* current_name) { + ValidatorIsFile* instance = malloc(sizeof(ValidatorIsFile)); + + instance->app_path_folder = strdup(app_path_folder); + instance->app_extension = app_extension; + if(current_name != NULL) { + instance->current_name = strdup(current_name); + } + + return instance; +} + +void validator_is_file_free(ValidatorIsFile* instance) { + furi_assert(instance); + free(instance->app_path_folder); + free(instance->current_name); + free(instance); +} diff --git a/applications/external/nfc_maker/nfc_maker_validators.h b/applications/external/nfc_maker/nfc_maker_validators.h new file mode 100644 index 000000000..d9200b6db --- /dev/null +++ b/applications/external/nfc_maker/nfc_maker_validators.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif +typedef struct ValidatorIsFile ValidatorIsFile; + +ValidatorIsFile* validator_is_file_alloc_init( + const char* app_path_folder, + const char* app_extension, + const char* current_name); + +void validator_is_file_free(ValidatorIsFile* instance); + +bool validator_is_file_callback(const char* text, FuriString* error, void* context); + +#ifdef __cplusplus +} +#endif diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_https.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_https.c index 77b32afe1..8f9704a7e 100644 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_https.c +++ b/applications/external/nfc_maker/scenes/nfc_maker_scene_https.c @@ -12,13 +12,13 @@ static void nfc_maker_scene_https_text_input_callback(void* context) { void nfc_maker_scene_https_on_enter(void* context) { NfcMaker* app = context; - TextInput* text_input = app->text_input; + NFCMaker_TextInput* text_input = app->text_input; - text_input_set_header_text(text_input, "Enter HTTPS Link:"); + nfc_maker_text_input_set_header_text(text_input, "Enter HTTPS Link:"); strlcpy(app->text_buf, "google.com", TEXT_INPUT_LEN); - text_input_set_result_callback( + nfc_maker_text_input_set_result_callback( text_input, nfc_maker_scene_https_text_input_callback, app, @@ -49,5 +49,5 @@ bool nfc_maker_scene_https_on_event(void* context, SceneManagerEvent event) { void nfc_maker_scene_https_on_exit(void* context) { NfcMaker* app = context; - text_input_reset(app->text_input); + nfc_maker_text_input_reset(app->text_input); } diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_mail.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_mail.c index 98c648f6a..2f91c542d 100644 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_mail.c +++ b/applications/external/nfc_maker/scenes/nfc_maker_scene_mail.c @@ -12,13 +12,13 @@ static void nfc_maker_scene_mail_text_input_callback(void* context) { void nfc_maker_scene_mail_on_enter(void* context) { NfcMaker* app = context; - TextInput* text_input = app->text_input; + NFCMaker_TextInput* text_input = app->text_input; - text_input_set_header_text(text_input, "Enter EMail Address:"); + nfc_maker_text_input_set_header_text(text_input, "Enter Email Address:"); strlcpy(app->text_buf, "ben.dover@example.com", TEXT_INPUT_LEN); - text_input_set_result_callback( + nfc_maker_text_input_set_result_callback( text_input, nfc_maker_scene_mail_text_input_callback, app, @@ -49,5 +49,5 @@ bool nfc_maker_scene_mail_on_event(void* context, SceneManagerEvent event) { void nfc_maker_scene_mail_on_exit(void* context) { NfcMaker* app = context; - text_input_reset(app->text_input); + nfc_maker_text_input_reset(app->text_input); } diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_menu.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_menu.c index 4268e7e2f..9f8b3c245 100644 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_menu.c +++ b/applications/external/nfc_maker/scenes/nfc_maker_scene_menu.c @@ -22,7 +22,7 @@ void nfc_maker_scene_menu_on_enter(void* context) { submenu, "HTTPS Link", NfcMakerSceneHttps, nfc_maker_scene_menu_submenu_callback, app); submenu_add_item( - submenu, "Mail Address", NfcMakerSceneMail, nfc_maker_scene_menu_submenu_callback, app); + submenu, "Email Address", NfcMakerSceneMail, nfc_maker_scene_menu_submenu_callback, app); submenu_add_item( submenu, "Phone Number", NfcMakerScenePhone, nfc_maker_scene_menu_submenu_callback, app); diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_name.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_name.c index dd5170d94..7f07a4e50 100644 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_name.c +++ b/applications/external/nfc_maker/scenes/nfc_maker_scene_name.c @@ -12,13 +12,13 @@ static void nfc_maker_scene_name_text_input_callback(void* context) { void nfc_maker_scene_name_on_enter(void* context) { NfcMaker* app = context; - TextInput* text_input = app->text_input; + NFCMaker_TextInput* text_input = app->text_input; - text_input_set_header_text(text_input, "Name the NFC tag:"); + nfc_maker_text_input_set_header_text(text_input, "Name the NFC tag:"); set_random_name(app->name_buf, TEXT_INPUT_LEN); - text_input_set_result_callback( + nfc_maker_text_input_set_result_callback( text_input, nfc_maker_scene_name_text_input_callback, app, @@ -28,7 +28,7 @@ void nfc_maker_scene_name_on_enter(void* context) { ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(NFC_APP_FOLDER, NFC_APP_EXTENSION, NULL); - text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); + nfc_maker_text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); view_dispatcher_switch_to_view(app->view_dispatcher, NfcMakerViewTextInput); } @@ -53,5 +53,5 @@ bool nfc_maker_scene_name_on_event(void* context, SceneManagerEvent event) { void nfc_maker_scene_name_on_exit(void* context) { NfcMaker* app = context; - text_input_reset(app->text_input); + nfc_maker_text_input_reset(app->text_input); } diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_phone.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_phone.c index 4e70bcb09..a399e12e3 100644 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_phone.c +++ b/applications/external/nfc_maker/scenes/nfc_maker_scene_phone.c @@ -12,13 +12,13 @@ static void nfc_maker_scene_phone_text_input_callback(void* context) { void nfc_maker_scene_phone_on_enter(void* context) { NfcMaker* app = context; - TextInput* text_input = app->text_input; + NFCMaker_TextInput* text_input = app->text_input; - text_input_set_header_text(text_input, "Enter Phone Number:"); + nfc_maker_text_input_set_header_text(text_input, "Enter Phone Number:"); strlcpy(app->text_buf, "+", TEXT_INPUT_LEN); - text_input_set_result_callback( + nfc_maker_text_input_set_result_callback( text_input, nfc_maker_scene_phone_text_input_callback, app, @@ -49,5 +49,5 @@ bool nfc_maker_scene_phone_on_event(void* context, SceneManagerEvent event) { void nfc_maker_scene_phone_on_exit(void* context) { NfcMaker* app = context; - text_input_reset(app->text_input); + nfc_maker_text_input_reset(app->text_input); } diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_text.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_text.c index 17d84e0a9..fa8698cf4 100644 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_text.c +++ b/applications/external/nfc_maker/scenes/nfc_maker_scene_text.c @@ -12,13 +12,13 @@ static void nfc_maker_scene_text_text_input_callback(void* context) { void nfc_maker_scene_text_on_enter(void* context) { NfcMaker* app = context; - TextInput* text_input = app->text_input; + NFCMaker_TextInput* text_input = app->text_input; - text_input_set_header_text(text_input, "Enter Text Note:"); + nfc_maker_text_input_set_header_text(text_input, "Enter Text Note:"); strlcpy(app->text_buf, "Lorem ipsum", TEXT_INPUT_LEN); - text_input_set_result_callback( + nfc_maker_text_input_set_result_callback( text_input, nfc_maker_scene_text_text_input_callback, app, @@ -49,5 +49,5 @@ bool nfc_maker_scene_text_on_event(void* context, SceneManagerEvent event) { void nfc_maker_scene_text_on_exit(void* context) { NfcMaker* app = context; - text_input_reset(app->text_input); + nfc_maker_text_input_reset(app->text_input); } diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_url.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_url.c index e5a4996b2..8d6ae9e69 100644 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_url.c +++ b/applications/external/nfc_maker/scenes/nfc_maker_scene_url.c @@ -12,13 +12,13 @@ static void nfc_maker_scene_url_text_input_callback(void* context) { void nfc_maker_scene_url_on_enter(void* context) { NfcMaker* app = context; - TextInput* text_input = app->text_input; + NFCMaker_TextInput* text_input = app->text_input; - text_input_set_header_text(text_input, "Enter Plain URL:"); + nfc_maker_text_input_set_header_text(text_input, "Enter Plain URL:"); strlcpy(app->text_buf, "https://google.com", TEXT_INPUT_LEN); - text_input_set_result_callback( + nfc_maker_text_input_set_result_callback( text_input, nfc_maker_scene_url_text_input_callback, app, @@ -49,5 +49,5 @@ bool nfc_maker_scene_url_on_event(void* context, SceneManagerEvent event) { void nfc_maker_scene_url_on_exit(void* context) { NfcMaker* app = context; - text_input_reset(app->text_input); + nfc_maker_text_input_reset(app->text_input); } diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi.c index 68efaf7f6..eabc79c5b 100644 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi.c +++ b/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi.c @@ -12,13 +12,13 @@ static void nfc_maker_scene_wifi_text_input_callback(void* context) { void nfc_maker_scene_wifi_on_enter(void* context) { NfcMaker* app = context; - TextInput* text_input = app->text_input; + NFCMaker_TextInput* text_input = app->text_input; - text_input_set_header_text(text_input, "Enter WiFi SSID:"); + nfc_maker_text_input_set_header_text(text_input, "Enter WiFi SSID:"); strlcpy(app->text_buf, "Bill Wi the Science Fi", WIFI_INPUT_LEN); - text_input_set_result_callback( + nfc_maker_text_input_set_result_callback( text_input, nfc_maker_scene_wifi_text_input_callback, app, @@ -51,5 +51,5 @@ bool nfc_maker_scene_wifi_on_event(void* context, SceneManagerEvent event) { void nfc_maker_scene_wifi_on_exit(void* context) { NfcMaker* app = context; - text_input_reset(app->text_input); + nfc_maker_text_input_reset(app->text_input); } diff --git a/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi_pass.c b/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi_pass.c index 3f5b4bd76..c0301d338 100644 --- a/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi_pass.c +++ b/applications/external/nfc_maker/scenes/nfc_maker_scene_wifi_pass.c @@ -12,13 +12,13 @@ static void nfc_maker_scene_wifi_pass_text_input_callback(void* context) { void nfc_maker_scene_wifi_pass_on_enter(void* context) { NfcMaker* app = context; - TextInput* text_input = app->text_input; + NFCMaker_TextInput* text_input = app->text_input; - text_input_set_header_text(text_input, "Enter WiFi Password:"); + nfc_maker_text_input_set_header_text(text_input, "Enter WiFi Password:"); strlcpy(app->pass_buf, "244466666", WIFI_INPUT_LEN); - text_input_set_result_callback( + nfc_maker_text_input_set_result_callback( text_input, nfc_maker_scene_wifi_pass_text_input_callback, app, @@ -49,5 +49,5 @@ bool nfc_maker_scene_wifi_pass_on_event(void* context, SceneManagerEvent event) void nfc_maker_scene_wifi_pass_on_exit(void* context) { NfcMaker* app = context; - text_input_reset(app->text_input); + nfc_maker_text_input_reset(app->text_input); } From 8369f72afb524d806fd40d5d77538e005ba82857 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Sat, 8 Jul 2023 19:52:25 +0300 Subject: [PATCH 02/14] move app --- applications/external/bad_bt/application.fam | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/external/bad_bt/application.fam b/applications/external/bad_bt/application.fam index a3544b997..981c0c0c0 100644 --- a/applications/external/bad_bt/application.fam +++ b/applications/external/bad_bt/application.fam @@ -10,7 +10,7 @@ App( stack_size=2 * 1024, order=70, fap_libs=["assets"], - fap_category="Tools", + fap_category="Bluetooth", fap_icon="images/badbt_10px.png", fap_icon_assets="images", ) From 27259c0cffb9a9b4c9444ad9ab3dc61b849564d6 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Sun, 9 Jul 2023 00:58:46 +0300 Subject: [PATCH 03/14] update changelog --- CHANGELOG.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74bf3dc9d..820afe918 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,14 @@ ## New changes -* SubGHz: Keeloq: Centurion Nova read and emulate support (+ add manually) +* !!! **Warning! After installing, Desktop settings (Favoutite apps, PIN Code, AutoLock time..) will be resetted to default due to settings changes, Please set your PIN code, Favourite apps again in Settings->Desktop** !!! +* If you have copied any apps manually into `apps` folder - remove `apps` folder or that specific apps you copied on your microSD before installing this release to avoid issues due to OFW API version update! If you using regular builds or extra pack builds (e) without your manually added apps, all included apps will be installed automatically, no extra actions needed! +----- +* SubGHz: **Keeloq: Centurion Nova read and emulate support (+ add manually)** * SubGHz: FAAC SLH - UI Fixes, Fix sending signals with no seed * SubGHz: Code cleanup, proper handling of protocols ignore options (by @gid9798 | PR #516) * SubGHz: Various UI fixes (by @wosk | PR #527) * NFC: Fixed issue #532 (Mifare classic user dict - delete removes more than selected key) * Infrared: Updated universal remote assets (by @amec0e | PR #529) -* Plugins: Use correct categories for all plugins (extra pack too) +* Plugins: **Use correct categories (folders) for all plugins (extra pack too)** * Plugins: Various fixes for uFBT (by @hedger) * Plugins: Added **NFC Maker** plugin (make tags with URLs, Wifi and other things) [(by Willy-JL)](https://github.com/ClaraCrazy/Flipper-Xtreme/tree/dev/applications/external/nfc_maker) * Plugins: Added JetPack Joyride [(by timstrasser)](https://github.com/timstrasser) @@ -14,7 +17,7 @@ * Plugins: Updated i2c Tools [(by NaejEL)](https://github.com/NaejEL/flipperzero-i2ctools) * Settings: Change LED and volume settings by 5% steps (by @cokyrain) * BLE: BadBT fixes and furi_hal_bt cleanup (by @Willy-JL) -* WIP OFW PR 2825: NFC: Improved MFC emulation on some readers (by AloneLiberty) +* WIP OFW PR 2825: **NFC: Improved MFC emulation on some readers (by AloneLiberty)** * OFW PR 2829: Decode only supported Oregon 3 sensor (by @wosk) * OFW PR: Update OFW PR 2782 * OFW: SubGhz: add "SubGhz test" external application and the ability to work "SubGhz" as an external application From b148e396d74ff636c3f90efff43475ba36bf0371 Mon Sep 17 00:00:00 2001 From: Dusan Hlavaty Date: Mon, 10 Jul 2023 08:22:30 +0200 Subject: [PATCH 04/14] feat(infrared): add TCL TV remote (#2853) Adds a TCL TV remote to the universal remotes list. Tested with TCL 55C815 television --- assets/resources/infrared/assets/tv.ir | 36 ++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/assets/resources/infrared/assets/tv.ir b/assets/resources/infrared/assets/tv.ir index ba8807123..c4b6f0c42 100644 --- a/assets/resources/infrared/assets/tv.ir +++ b/assets/resources/infrared/assets/tv.ir @@ -1681,3 +1681,39 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 3462 1592 490 332 513 1200 489 331 514 1201 489 355 490 1201 489 356 512 1178 489 356 512 1178 512 334 487 1202 488 1202 488 357 512 1178 512 334 486 1203 487 1202 488 1203 487 1204 486 383 461 1228 488 357 488 357 487 357 487 1203 486 1204 486 359 485 1205 485 360 485 361 484 360 485 360 485 361 484 361 484 361 484 1206 484 360 484 361 484 361 484 1206 484 361 484 361 484 361 484 1206 484 361 484 1206 484 361 484 71543 3434 1620 486 359 485 1205 485 360 485 1206 484 360 485 1206 484 360 485 1206 484 360 485 1206 484 360 485 1205 485 1206 484 360 485 1206 484 360 485 1206 484 1206 484 1206 484 1206 484 361 484 1206 484 360 485 360 485 361 484 1206 484 1206 484 360 484 1206 484 360 485 361 484 361 484 360 485 361 484 361 484 361 484 1206 484 361 484 361 484 361 484 1206 484 361 484 361 484 361 484 1207 483 361 484 1206 484 361 484 71543 3435 1619 486 358 486 1204 486 359 486 1205 485 360 485 1205 485 360 485 1205 485 360 485 1205 485 360 484 1205 485 1205 485 360 485 1205 485 360 485 1205 485 1205 485 1205 485 1206 484 360 485 1205 485 360 485 360 485 360 485 1205 485 1206 484 360 485 1206 484 360 485 360 485 360 485 360 485 360 485 360 485 360 485 1206 484 360 485 360 485 360 485 1206 484 360 485 360 485 360 485 1205 485 360 485 1206 484 360 485 71542 3436 1619 486 358 487 1204 486 359 485 1205 485 360 485 1205 485 360 485 1205 485 360 485 1205 485 360 485 1205 485 1205 485 360 485 1205 485 360 485 1206 484 1206 484 1206 484 1206 484 360 485 1206 484 360 485 360 485 361 484 1206 484 1206 484 361 484 1206 484 361 484 361 484 361 484 361 484 361 484 361 484 360 485 1206 484 361 484 361 484 361 484 1206 484 361 484 361 484 360 485 1206 484 361 484 1206 484 361 484 71542 3437 1618 487 358 486 1204 486 359 486 1205 485 360 485 1205 485 360 485 1205 485 360 485 1205 485 360 485 1205 485 1206 484 360 485 1205 485 360 485 1206 484 1205 485 1206 484 1205 485 360 485 1205 485 360 485 360 485 360 485 1205 485 1205 485 360 485 1205 485 360 485 360 485 360 485 360 485 360 485 360 485 360 485 1205 485 360 485 360 485 360 485 1205 485 360 485 360 485 360 485 1205 485 360 485 1205 485 360 485 +# Model: TCL +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3977 3993 494 1994 495 1995 496 1997 494 1996 495 1004 496 1004 496 1995 496 1004 496 1997 494 1005 495 1995 495 1007 493 1006 494 1006 494 1005 495 1007 493 1997 494 1995 496 1004 496 1995 496 1005 495 1995 496 1003 497 1995 496 8467 3980 3993 494 1994 495 1996 495 1997 494 1995 496 1004 496 1006 494 1995 496 1004 496 1996 495 1004 496 1996 495 1005 495 1005 495 1004 496 1005 495 1005 495 1996 495 1995 496 1005 495 1996 495 1004 496 1995 496 1006 569 1920 571 8393 3980 3993 571 1918 572 1922 569 1920 571 1920 571 929 572 929 571 1920 571 929 571 1920 571 929 571 1921 570 930 570 929 571 929 571 929 571 928 572 1920 571 1921 570 930 571 1920 572 930 571 1921 571 929 571 1923 569 8396 3980 3994 570 1921 569 1923 569 1921 571 1920 572 929 572 930 571 1921 570 930 571 1922 570 930 571 1921 570 930 570 930 571 929 571 929 571 929 572 1922 570 1921 570 931 570 1922 570 930 571 1922 569 931 570 1921 570 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3979 3995 493 1994 496 1997 495 1999 492 1999 492 1006 495 1008 493 1998 493 1006 494 1997 495 1999 493 1997 494 1998 493 1006 495 1007 493 1005 495 1006 495 2025 467 1998 494 1006 494 1996 495 1006 494 1005 495 1006 494 1007 493 8468 3979 3995 492 1995 495 1999 492 1997 494 1997 494 1007 493 1006 494 1997 494 1006 494 1997 494 1996 571 1923 569 1921 570 930 570 929 571 931 569 931 575 1916 570 1920 571 930 570 1922 570 930 571 930 570 930 576 924 576 +# +name: Vol_dn +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3951 3994 494 1997 493 1998 494 1998 493 1998 493 1005 496 1005 496 1996 495 1005 495 1997 495 1996 495 1996 495 1006 494 1005 495 1006 494 1005 495 1006 494 1996 495 1998 493 1005 495 1997 494 1008 492 1006 494 1006 494 1997 494 8471 3977 3996 493 1996 493 1997 494 1998 493 1997 494 1006 494 1007 493 1997 494 1009 492 1996 495 1996 495 1997 494 1006 494 1006 494 1006 494 1006 494 1006 494 1997 493 1997 494 1006 494 1996 494 1005 495 1004 495 1006 494 1996 494 +# +name: Ch_next +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3978 3994 494 1995 495 1996 495 1996 495 1996 495 1006 494 1004 497 1997 494 1005 495 1997 520 1970 577 923 578 1914 577 924 576 924 576 925 575 924 576 1914 577 1915 576 924 576 1914 577 924 576 923 577 1915 576 926 574 8388 3978 3993 576 1913 576 1915 576 1915 576 1917 574 923 577 923 577 1943 548 925 575 1916 576 1915 575 924 576 1915 576 925 575 927 573 925 575 926 574 1916 574 1918 573 927 573 1918 573 928 572 927 573 1918 573 926 574 8389 4006 3966 572 1918 571 1919 572 1918 573 1920 570 929 571 929 571 1922 569 928 571 1920 571 1921 570 928 572 1919 572 929 571 929 571 929 571 929 571 1921 570 1921 521 980 569 1921 521 981 519 979 521 1971 520 979 521 +# +name: Ch_prev +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3979 3994 494 1995 495 1997 494 1996 495 1998 493 1005 495 1006 494 1997 494 1005 495 1996 495 1995 496 1005 495 1005 495 1006 494 1005 495 1004 496 1005 495 1997 494 1997 494 1004 496 1996 495 1005 495 1005 495 1997 494 1996 495 8467 3976 3991 496 1995 495 1996 494 1994 496 1996 494 1005 495 1005 495 1996 495 1005 495 1995 495 1995 496 1006 494 1005 495 1006 494 1005 495 1004 496 1006 494 1994 496 1996 494 1005 495 1995 495 1004 496 1004 496 1995 495 1996 494 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3981 3992 495 1994 495 1995 496 1996 494 1996 495 1005 495 1006 494 1995 495 1997 494 1996 495 1996 494 1997 494 1996 495 1006 494 1005 495 1004 496 1005 495 1995 496 1994 496 1005 495 1004 496 1005 495 1006 494 1004 496 1006 494 8466 3978 3991 495 1994 495 1997 493 1994 496 1995 495 1004 496 1004 496 1996 494 1997 493 1996 494 1995 495 1995 495 1997 493 1004 495 1004 495 1006 494 1005 494 1998 491 1996 494 1006 494 1004 496 1006 494 1006 493 1005 495 1005 571 From 0195f8bf0044ec913e07b8ad34e449fd3e0f73cb Mon Sep 17 00:00:00 2001 From: Astra <93453568+Astrrra@users.noreply.github.com> Date: Mon, 10 Jul 2023 09:48:00 +0300 Subject: [PATCH 05/14] [FL-3350] Device Info update (#2840) * Update F18 version info * Certification info for F18 Co-authored-by: Aleksandr Kutuzov --- applications/settings/about/about.c | 4 +++- assets/icons/About/Certification2_46x33.png | Bin 0 -> 229 bytes assets/icons/About/Certification2_98x33.png | Bin 2495 -> 0 bytes firmware/targets/f18/api_symbols.csv | 3 ++- .../f18/furi_hal/furi_hal_version_device.c | 12 ++++++++---- firmware/targets/f7/api_symbols.csv | 3 ++- .../f7/furi_hal/furi_hal_version_device.c | 4 ++++ .../targets/furi_hal_include/furi_hal_version.h | 6 ++++++ 8 files changed, 25 insertions(+), 7 deletions(-) create mode 100644 assets/icons/About/Certification2_46x33.png delete mode 100644 assets/icons/About/Certification2_98x33.png diff --git a/applications/settings/about/about.c b/applications/settings/about/about.c index 688103306..55bd43e5c 100644 --- a/applications/settings/about/about.c +++ b/applications/settings/about/about.c @@ -82,7 +82,9 @@ static DialogMessageButton icon1_screen(DialogsApp* dialogs, DialogMessage* mess static DialogMessageButton icon2_screen(DialogsApp* dialogs, DialogMessage* message) { DialogMessageButton result; - dialog_message_set_icon(message, &I_Certification2_98x33, 15, 10); + dialog_message_set_icon(message, &I_Certification2_46x33, 15, 10); + dialog_message_set_text( + message, furi_hal_version_get_mic_id(), 63, 27, AlignLeft, AlignCenter); result = dialog_message_show(dialogs, message); dialog_message_set_icon(message, NULL, 0, 0); diff --git a/assets/icons/About/Certification2_46x33.png b/assets/icons/About/Certification2_46x33.png new file mode 100644 index 0000000000000000000000000000000000000000..d421b829149518d4d379b03d76881f88706c3e87 GIT binary patch literal 229 zcmeAS@N?(olHy`uVBq!ia0vp^dO)nm!3-oP8fIPqQfvV}A+G=b{|7Qd4_&SUQnNf= z978H@t(g+YcR+!|`Qg9maYoZ4y+u8qcz^6{V@k`gJEQe1Lp5T}_AiC!OOBS>-1;=T zdEV~dE9_2v2<2Pid?=n_o3MCO-A5)qmHYo@Jp3jwB`^7eym+fxoxz8QtS6Qam1Y|! zr_NbyeOvU-CA$l&z7_nH6v>?!`zVuf^AS(s0M|6%%_#=?UdNv8|9>xd*oX c{KsLyP+HH}pmOhIG0>F^p00i_>zopr08YJL$p8QV literal 0 HcmV?d00001 diff --git a/assets/icons/About/Certification2_98x33.png b/assets/icons/About/Certification2_98x33.png deleted file mode 100644 index 49c5581c7523f2956fda218cfa9c048cf1998ef5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2495 zcma)7eN+=y77u<<3c9DF1uNPeM(e@FB$G)pm^lQ^7bZ%SFD0_A?JzSTQ=2gmAE?2J5Xf$#Jm7}N>SV;K-w?O!$Zhp2HA`rt! z^CZW31cr4(VoV~3%@edR3~*>DxWL$h(cSz|`k)YU5s@oohAdtmS;=X1IVKB& zqBJTjL8>BEv@}7fQb}`&1X4@KnY}J8eb=iatwkMFfl-d12T>@5bno-1ON*3OAxXc45=JzXPf}z(--R@i^+f~G#HRartn{9 zC=nD?EHTY7`81Wxv96&@EbdZc6dq01V>(oA9H|_tQ5Z~mjmfCeAc)cEPZtaU(VrQk z@Qh6jz1=tLu zJZl%c1V`&~K{tW+w%ZwSX$k@z4k=^`M5cb+!|R|yv?n)pfGm_K7suc*wM2O!{ZZrt z2BYRC$RV%?<}n!T@{!3779-yV+6_Jk9GLu$M_VRIBq4#Ys@tw&4`C)Q2QeoB`% z;R2c+T{rKuis}uK1x3ovo!8E3&XtEOMfUFLuh*G#YqJ|~=g)sLYSxvk8MnTAcT-_a zRrQuXHEce3zkkuD=YD?Cez?2yQQb{PO4jauX+C{g-JxHO)v(&?9iPYl;K zQ+uu=1A`}ytX)t2)%N4fq6g7U|GpJ+`*$6DQQzy%>HnF!|MjBk6wMp`VP}#|=eMdm zW3QfQ`>Fnr>3$m*gYUXj6D2d({q%uv=0DHxeqn;^#P`QCdsZlt|Kz*M(FaSqs1W=`??1& zmu);-rqAdrXl!qP@Amc04|ly*cW>N{o)ezkOw!CMw0~c7JgrCTE_TGn_kGyfyFIkh zN#D5^8MP#9>7H`slqp|$)3@RG|5#JS__|645+%zr&Nt17(2jq9#}(&|`Q+8^`n?~0 z>@Me84b^>LJiulR#vGSU&zMFYh&<@t&o@UsZ*7VWU0r$M>~p*=35~jvbf>iXyS?9? zI`B}p9$wS&A^Ob53ER%Rx_JE!y0K+qVT9V(d#|-6tWBNFpAzLv$@yYa_ZoN#+Nq#Kx~p6 zI1|4u?Z2nG3f~<#*7fmn Date: Mon, 10 Jul 2023 10:04:53 +0300 Subject: [PATCH 06/14] Add Hitachi RAK-50PEB universal ac remote (#2826) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- assets/resources/infrared/assets/ac.ir | 37 ++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/assets/resources/infrared/assets/ac.ir b/assets/resources/infrared/assets/ac.ir index c7b1aaf7e..cb3c2539c 100644 --- a/assets/resources/infrared/assets/ac.ir +++ b/assets/resources/infrared/assets/ac.ir @@ -507,3 +507,40 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 3539 1637 533 1225 502 1193 534 375 501 376 501 376 500 1226 501 376 501 376 500 1226 500 1227 501 376 529 1197 558 320 557 319 555 1169 531 1195 531 346 529 1196 530 1198 528 349 526 352 524 1229 497 379 497 379 497 1230 497 380 497 380 497 379 498 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 9042 3535 1674 496 1230 497 1230 497 380 497 380 497 380 497 1230 497 380 497 380 496 1230 497 1230 497 380 497 1230 497 380 497 380 497 1231 496 1230 497 380 497 1231 496 1231 496 380 496 380 497 1231 496 380 497 380 496 1231 496 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 496 380 497 380 497 380 497 380 497 380 496 381 496 380 497 380 497 380 497 381 496 1231 496 381 496 380 497 380 497 381 496 381 496 1231 496 381 496 381 496 380 497 381 495 1231 496 1231 496 1231 496 380 497 381 496 381 496 380 496 381 496 381 496 381 496 381 496 381 496 1231 496 1231 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 1231 496 381 496 381 496 1232 495 381 495 1232 495 381 496 1231 496 1231 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 495 381 496 381 496 381 496 381 496 1232 495 381 496 381 496 381 496 381 496 381 495 381 496 381 495 382 495 381 496 382 495 381 495 382 495 381 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 381 495 1232 495 1232 495 1232 495 1232 495 1232 495 382 495 382 495 382 495 +# +# Model: Hitachi RAK-50PEB +name: Off +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 30683 50966 3411 1600 493 1186 493 347 492 348 491 348 491 349 490 349 490 350 489 351 488 351 488 352 487 352 488 351 488 1192 487 352 487 351 488 352 487 352 487 352 488 352 488 351 488 1192 487 1191 488 352 487 352 487 352 487 352 487 352 487 352 487 352 487 352 487 1192 487 352 487 1192 487 1192 487 1192 487 1192 488 1192 487 1192 488 352 487 1192 487 1192 487 352 487 352 487 352 487 352 488 352 487 352 488 352 487 352 487 1192 487 1192 487 1192 487 1192 487 1192 487 1192 487 1192 487 1192 487 352 487 352 488 352 487 1192 487 352 487 352 487 352 487 352 487 1192 487 352 487 353 486 1192 487 353 486 353 486 353 486 353 486 1193 486 353 487 353 486 353 486 353 486 353 486 353 486 1193 486 1193 486 353 487 353 486 353 486 353 486 353 487 353 486 353 486 353 486 1193 486 353 486 353 486 1193 486 353 487 353 486 353 487 353 486 353 486 353 486 353 486 353 487 353 486 353 486 1193 486 1193 486 353 487 353 486 353 486 353 486 354 485 353 486 354 485 353 486 354 486 353 486 353 486 354 486 353 486 353 487 1193 486 1194 485 353 487 353 486 354 485 354 485 354 486 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 486 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 486 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 355 484 355 484 355 484 354 485 354 485 355 484 355 484 355 484 355 484 354 486 355 484 378 461 356 484 378 461 355 485 355 484 355 484 355 485 355 484 378 461 378 461 355 484 356 483 355 484 378 461 378 462 355 485 378 461 378 462 378 461 379 461 356 483 378 461 1195 484 378 461 379 461 356 484 378 461 379 460 379 461 378 461 378 462 378 461 379 461 378 461 378 461 379 460 379 460 379 461 378 461 378 461 378 461 378 461 378 461 379 460 379 460 379 460 379 461 379 460 1219 460 1219 460 379 461 1219 460 379 461 1219 460 +# +name: Dh +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 30684 50965 3412 1599 494 1185 494 346 493 346 493 347 492 348 491 349 490 349 490 350 489 351 489 350 489 350 489 351 489 1191 488 351 488 351 488 351 489 351 488 351 488 351 488 351 488 1191 488 1191 488 351 488 351 488 351 488 351 488 351 488 351 489 351 488 351 488 1191 488 351 489 1191 488 1191 488 1191 488 1191 488 1191 488 1191 488 351 488 1191 488 1192 487 351 488 352 487 351 488 351 488 352 487 352 487 352 487 352 488 1192 487 1192 487 1216 463 1192 487 1192 488 1192 487 1193 486 1192 488 352 487 352 487 352 487 1193 486 376 463 376 463 376 464 352 487 1216 463 376 463 376 463 1216 464 376 463 376 463 376 463 1216 463 376 463 376 463 353 486 353 487 376 463 376 463 376 463 1216 463 376 463 1216 463 376 464 376 463 376 463 376 464 376 463 376 463 376 463 376 463 1216 463 376 463 1216 463 376 463 376 463 376 463 376 463 376 463 376 463 376 463 376 463 376 464 376 463 1216 463 1217 463 376 463 377 462 377 462 377 463 376 463 376 463 377 462 376 463 377 462 377 462 377 463 376 463 377 462 377 462 1217 462 1216 463 377 463 377 462 377 462 377 462 377 463 376 463 377 462 377 463 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 463 377 462 377 463 377 462 377 462 1217 462 377 462 377 462 377 463 377 462 377 463 377 462 377 462 377 462 377 462 377 463 377 462 377 462 377 462 377 462 377 462 377 463 377 462 377 462 377 462 377 462 377 462 377 462 377 463 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 463 377 462 377 463 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 1217 462 377 462 377 462 377 462 377 462 378 461 377 462 377 462 378 462 377 462 377 462 377 463 377 462 378 461 378 462 377 462 378 461 377 462 378 461 378 461 378 461 378 462 377 462 378 462 1217 462 1218 461 1218 461 378 461 378 461 1218 462 377 462 378 462 +# +name: Cool_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 30747 50897 3484 1554 543 1137 542 310 529 309 530 309 530 309 530 310 529 309 530 310 529 309 530 309 530 309 530 309 530 1138 541 309 531 309 530 309 530 309 530 309 530 309 530 309 530 1138 541 1138 541 310 529 309 530 309 531 309 530 309 530 309 530 309 530 310 529 1139 541 309 530 1138 541 1138 541 1138 541 1138 542 1138 541 1138 541 310 529 1138 541 1138 541 309 530 309 530 309 531 310 529 309 530 309 530 309 530 309 530 1139 541 1139 540 1139 541 1138 541 1139 540 1139 540 1138 541 1139 540 310 529 310 529 309 530 1139 541 310 529 309 530 309 530 309 530 1139 540 309 530 309 530 1139 541 309 530 309 530 309 530 1139 540 309 531 309 530 1139 541 309 530 309 530 309 530 309 530 309 530 309 530 1139 540 309 531 309 530 309 530 309 530 309 530 309 530 309 531 309 530 309 531 309 530 1139 540 310 529 309 530 309 530 309 530 309 530 309 531 310 529 310 529 309 531 310 529 1140 540 309 530 309 531 309 530 309 530 309 530 309 531 309 530 309 530 309 530 309 530 309 531 309 530 309 531 309 530 310 529 1140 539 1140 539 309 530 309 530 309 530 309 530 310 529 309 530 309 530 309 530 309 530 309 531 309 530 309 530 309 530 309 530 309 530 309 531 309 530 309 530 309 530 309 530 309 530 1140 540 309 530 309 530 309 530 309 530 309 531 309 530 309 531 309 530 309 530 310 530 309 530 309 531 309 530 309 530 309 530 309 530 309 530 309 531 309 530 309 530 309 531 309 530 309 530 309 531 309 531 309 530 309 530 309 530 309 530 309 531 309 531 309 530 309 530 309 530 309 530 309 530 309 531 309 530 309 531 309 530 309 531 309 530 309 530 309 531 309 530 309 530 309 530 309 530 1141 538 309 531 309 530 309 530 309 530 309 531 309 530 309 530 309 530 309 531 309 530 309 530 309 530 309 530 309 530 309 530 309 530 310 530 309 531 309 530 309 530 309 530 309 530 309 530 309 531 1142 537 309 530 1142 538 309 530 1141 538 309 530 309 530 +# +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 30694 50951 3483 1555 542 1137 542 308 531 309 530 308 531 308 531 308 531 308 531 308 531 308 531 308 532 308 531 308 532 1139 541 308 531 308 531 308 531 308 531 308 531 309 531 308 531 1139 541 1139 540 308 531 308 531 308 531 308 531 309 530 308 531 308 531 308 532 1139 541 308 532 1139 540 1139 541 1139 540 1139 540 1139 540 1139 541 309 530 1139 540 1139 540 308 531 308 531 308 531 308 532 308 531 308 531 308 531 308 531 1140 540 1139 541 1139 540 1139 540 1139 540 1139 541 1139 540 1139 540 308 531 308 531 308 531 1140 540 309 530 308 531 308 532 308 531 1140 540 308 531 308 532 1140 539 308 531 308 531 308 531 308 532 308 531 308 531 1140 540 308 531 308 531 308 531 308 531 308 532 308 531 1140 540 308 531 308 531 308 531 308 531 308 531 308 531 1140 540 1140 540 1140 539 308 531 1140 539 308 531 308 531 308 532 308 531 306 533 308 531 306 533 308 531 307 533 308 531 1141 539 308 532 308 531 308 531 306 534 306 533 306 534 306 533 306 533 306 533 306 533 306 534 307 532 307 533 306 533 308 532 1141 539 1141 539 308 531 308 532 308 531 307 533 307 481 352 538 307 533 307 532 307 533 307 481 352 539 307 532 307 533 306 482 352 487 352 537 306 534 307 482 352 538 307 482 352 487 1192 539 309 530 307 531 306 483 352 487 352 538 307 482 352 538 306 483 352 487 352 487 352 487 353 486 352 488 353 486 352 487 352 487 353 487 353 486 353 486 353 487 352 487 353 486 353 486 353 486 353 486 353 487 353 487 353 486 353 486 353 487 353 486 353 486 353 486 353 487 353 486 353 487 352 487 353 486 353 486 353 487 353 486 353 486 353 487 353 486 353 487 353 486 353 487 353 486 1193 537 306 483 353 486 353 487 353 486 353 487 353 486 353 486 353 487 353 486 353 486 353 487 353 486 353 486 353 486 353 486 353 487 353 486 353 486 353 486 353 486 353 486 353 486 353 486 1194 485 353 487 1193 538 1142 486 1193 486 353 486 353 486 353 568 +# +name: Heat_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 30703 50953 3432 1606 490 1189 490 349 490 349 490 349 490 350 489 350 489 350 489 350 490 350 489 350 489 350 490 350 489 1190 490 350 489 350 489 350 489 350 489 350 490 350 489 350 490 1190 490 1190 489 350 489 350 489 350 489 350 490 350 490 350 489 350 490 350 490 1190 489 350 490 1190 489 1190 490 1190 489 1190 490 1190 489 1190 489 350 490 1190 489 1190 489 350 490 350 489 350 490 350 489 350 489 350 490 350 489 350 490 1190 489 1190 489 1190 490 1190 489 1190 490 1190 489 1190 489 1191 489 350 489 350 489 350 490 1190 490 350 489 350 490 350 489 350 490 1190 489 350 490 350 489 1190 490 350 489 350 490 350 490 350 489 350 489 350 489 1191 489 350 489 350 490 350 489 350 489 1191 489 1190 489 350 489 350 490 350 489 350 490 350 489 351 489 350 489 350 489 350 489 350 490 350 489 350 489 1191 489 350 489 351 489 351 488 351 489 351 488 351 489 350 489 351 489 351 489 1191 488 351 488 351 488 351 489 350 489 351 488 350 490 350 489 351 488 351 488 351 489 350 489 350 489 351 489 351 489 350 489 1191 488 1191 489 350 489 351 488 351 489 351 488 351 489 351 488 351 488 351 489 351 489 351 489 350 489 351 489 351 488 351 488 351 488 351 489 351 488 351 488 351 488 351 489 351 489 1191 488 351 489 351 488 351 489 351 488 351 489 351 489 351 488 351 488 351 489 351 489 351 488 351 488 351 488 351 489 351 488 351 488 351 489 351 488 351 488 351 489 351 489 351 488 351 488 351 489 351 489 351 488 351 489 351 488 351 489 351 488 351 489 351 488 351 489 351 488 351 489 351 488 351 488 351 489 351 488 351 489 351 489 351 489 351 488 351 489 351 488 351 488 351 489 351 488 1192 488 351 488 351 488 351 489 351 488 351 488 351 489 351 489 351 489 351 488 351 488 351 489 351 488 351 489 351 488 351 489 351 488 351 488 351 489 351 488 351 489 351 488 351 489 351 488 351 489 351 489 1191 488 1191 488 352 488 351 488 352 488 351 489 +# +name: Heat_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 30675 50953 3432 1606 490 1190 489 350 489 350 489 350 489 350 489 351 488 350 489 351 489 351 488 351 489 351 488 351 489 1191 488 351 488 351 489 351 488 351 488 351 488 351 489 351 488 1191 489 1191 489 351 488 351 488 351 488 351 488 351 489 351 489 351 488 351 489 1191 488 351 488 1191 489 1191 488 1191 488 1191 488 1191 488 1191 488 351 489 1191 488 1191 489 351 488 351 489 351 488 351 489 351 488 351 488 351 488 351 488 1191 488 1191 488 1191 488 1191 489 1191 488 1191 488 1191 489 1191 488 351 488 351 489 351 488 1191 488 351 489 351 488 351 488 351 489 1191 488 351 489 351 488 1191 488 351 488 351 488 351 489 351 489 351 488 351 489 1191 488 351 488 351 489 351 488 351 488 1191 488 1191 488 351 488 351 489 351 488 351 489 351 488 351 489 351 489 1191 488 1192 488 1191 488 351 489 1191 489 351 488 351 488 351 489 351 489 351 488 351 488 351 489 351 488 351 488 351 488 1192 488 351 489 351 488 351 488 351 489 351 489 351 488 351 488 351 488 352 487 352 488 351 488 352 488 351 488 351 488 351 488 1192 488 1192 487 352 488 352 487 352 487 352 488 352 487 352 488 351 488 352 488 352 488 352 487 352 488 351 488 351 488 352 488 352 487 352 488 352 487 352 488 352 488 352 488 352 487 1192 487 352 487 352 488 352 488 352 488 352 487 352 487 352 488 352 487 352 487 352 487 352 488 352 488 352 487 352 487 352 488 352 487 352 488 352 487 352 487 352 487 352 487 352 487 352 488 352 487 352 487 352 487 352 488 352 487 352 488 352 487 352 488 352 487 352 487 352 488 352 487 352 488 352 487 352 488 352 488 352 487 352 487 352 487 352 487 352 487 352 488 352 487 352 487 352 487 1193 486 352 487 352 488 352 487 352 487 352 488 352 487 352 488 352 488 352 487 352 488 352 487 353 486 353 487 352 487 352 488 352 488 352 487 352 487 352 487 352 487 353 487 352 488 352 488 352 487 1193 486 1193 486 1193 486 1193 487 353 487 352 487 353 486 From 9b2d80d6b7459e7e074b59948341046f3f7ee7f2 Mon Sep 17 00:00:00 2001 From: Sergey Gavrilov Date: Mon, 10 Jul 2023 11:03:41 +0300 Subject: [PATCH 07/14] [FL-3400] External menu apps (#2849) * FBT, applications: add MENUEXTERNAL app type * FBT, uFBT: build MENUEXTERNAL as EXTERNAL app * Loader menu: show external menu apps * LFRFID: move to sd card * FBT: always build External Applications list * Archive: look for external apps path * Infrared: move to sd card * Apps: add "start" apps * iButton: move to sd card * BadUSB: move to sd card * External apps: update icons * GPIO: move to sd card * Loader: look for external apps path * U2F: move to sd * SubGHz: move to sd * Apps: "on_start" metapackage * NFC: move to sd * Sync f7 and f18 Co-authored-by: Aleksandr Kutuzov --- applications/main/application.fam | 16 +++- .../archive/scenes/archive_scene_browser.c | 3 +- applications/main/bad_usb/application.fam | 9 +-- applications/main/bad_usb/icon.png | Bin 0 -> 576 bytes applications/main/gpio/application.fam | 6 +- applications/main/gpio/icon.png | Bin 0 -> 1760 bytes applications/main/ibutton/application.fam | 12 +-- applications/main/ibutton/icon.png | Bin 0 -> 304 bytes applications/main/infrared/application.fam | 12 +-- applications/main/infrared/icon.png | Bin 0 -> 305 bytes applications/main/lfrfid/application.fam | 14 +--- applications/main/lfrfid/icon.png | Bin 0 -> 308 bytes applications/main/nfc/application.fam | 13 ++- applications/main/nfc/icon.png | Bin 0 -> 304 bytes applications/main/onewire/application.fam | 8 -- applications/main/subghz/application.fam | 14 ++-- applications/main/subghz/icon.png | Bin 0 -> 299 bytes applications/main/u2f/application.fam | 9 +-- applications/main/u2f/icon.png | Bin 0 -> 583 bytes applications/services/applications.h | 12 +++ applications/services/loader/loader.c | 18 +++++ applications/services/loader/loader_menu.c | 21 ++++- firmware/targets/f18/api_symbols.csv | 2 +- firmware/targets/f7/api_symbols.csv | 75 ++++++++++++------ lib/nfc/SConscript | 5 ++ lib/nfc/helpers/mf_classic_dict.h | 8 ++ lib/nfc/helpers/mfkey32.h | 8 ++ lib/nfc/nfc_types.h | 8 ++ lib/nfc/nfc_worker.h | 10 ++- lib/nfc/parsers/nfc_supported_card.h | 8 ++ lib/nfc/protocols/crypto1.h | 8 ++ lib/nfc/protocols/mifare_classic.h | 8 ++ lib/nfc/protocols/mifare_desfire.h | 8 ++ lib/nfc/protocols/mifare_ultralight.h | 8 ++ scripts/fbt/appmanifest.py | 26 +++++- scripts/fbt_tools/fbt_extapps.py | 5 +- scripts/ufbt/SConstruct | 1 + site_scons/extapps.scons | 1 + 38 files changed, 258 insertions(+), 98 deletions(-) create mode 100644 applications/main/bad_usb/icon.png create mode 100644 applications/main/gpio/icon.png create mode 100644 applications/main/ibutton/icon.png create mode 100644 applications/main/infrared/icon.png create mode 100644 applications/main/lfrfid/icon.png create mode 100644 applications/main/nfc/icon.png create mode 100644 applications/main/subghz/icon.png create mode 100644 applications/main/u2f/icon.png diff --git a/applications/main/application.fam b/applications/main/application.fam index 75d55af93..0a90ee224 100644 --- a/applications/main/application.fam +++ b/applications/main/application.fam @@ -4,7 +4,6 @@ App( apptype=FlipperAppType.METAPACKAGE, provides=[ "gpio", - "onewire", "ibutton", "infrared", "lfrfid", @@ -13,5 +12,20 @@ App( "bad_usb", "u2f", "archive", + "main_apps_on_start", + ], +) + +App( + appid="main_apps_on_start", + name="On start hooks", + apptype=FlipperAppType.METAPACKAGE, + provides=[ + "ibutton_start", + "onewire_start", + "subghz_start", + "infrared_start", + "lfrfid_start", + "nfc_start", ], ) diff --git a/applications/main/archive/scenes/archive_scene_browser.c b/applications/main/archive/scenes/archive_scene_browser.c index e02f7622a..370830a00 100644 --- a/applications/main/archive/scenes/archive_scene_browser.c +++ b/applications/main/archive/scenes/archive_scene_browser.c @@ -5,13 +5,14 @@ #include "../helpers/archive_browser.h" #include "../views/archive_browser_view.h" #include "archive/scenes/archive_scene.h" +#include #define TAG "ArchiveSceneBrowser" #define SCENE_STATE_DEFAULT (0) #define SCENE_STATE_NEED_REFRESH (1) -const char* archive_get_flipper_app_name(ArchiveFileTypeEnum file_type) { +static const char* archive_get_flipper_app_name(ArchiveFileTypeEnum file_type) { switch(file_type) { case ArchiveFileTypeIButton: return "iButton"; diff --git a/applications/main/bad_usb/application.fam b/applications/main/bad_usb/application.fam index 2442dd3aa..5c42c9fa3 100644 --- a/applications/main/bad_usb/application.fam +++ b/applications/main/bad_usb/application.fam @@ -1,15 +1,12 @@ App( appid="bad_usb", name="Bad USB", - apptype=FlipperAppType.APP, + apptype=FlipperAppType.MENUEXTERNAL, entry_point="bad_usb_app", - cdefines=["APP_BAD_USB"], - requires=[ - "gui", - "dialogs", - ], stack_size=2 * 1024, icon="A_BadUsb_14", order=70, fap_libs=["assets"], + fap_icon="icon.png", + fap_category="USB", ) diff --git a/applications/main/bad_usb/icon.png b/applications/main/bad_usb/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..037474aa3bc9c2e1aca79a68483e69980432bcf5 GIT binary patch literal 576 zcmV-G0>AxEX>4Tx04R}tkv&MmKpe$i(`rSk4t5Z6$WWau6cusQDionYs1;guFuC*#nlvOW zE{=k0!NHHks)LKOt`4q(Aou~|=;Wm6A|?JWDYS_3;J6>}?mh0_0Yan9G%FATG`(u3 z5^*t;T@{0`5D-8=V(6BcWz0!Z5}xDh9zMR_MR}I@xj#prnzI<-6NzV;VOEJZh^IHJ z2Iqa^Fe}O`@j3ChNf#u3C`-Nm{=@yu+qV-Xlle$#1U1~DPPFA zta9Gstd(o5bx;1nP)=W2<~q$0B(R7jND!f*h7!uCB1)@HiiH&I$36VRj$a~|Laq`R zITlcX2HEk0|H1EWt^DMKn-q!zT`#u%F$x5Cfo9#dzmILZc>?&Kfh)c3uQY&}Ptxmc zEph}5Yy%h9ZB5w&E_Z;TCqp)6NAlAY@_FF>jJ_!g4Bi60Yi@6?eVjf3Y3eF@0~{Oz zV+G1y_jq?tXK(+WY4!I5C=YUpXXIhH00006VoOIv0RI600RN!9r;`8x010qNS#tmY z3ljhU3ljkVnw%H_000McNliru<^lu`HWXkp{t5s906j@WK~xyijZi@f05Awj>HlAL zr$MwDdI>{Qf+U53tOUR#xOeyy)jcQo#JNRv)7r6DVVK|+*(cmT+R+EbO(O#X#REG4 O00005OriujUt-p2+p8kXl9tpG9lUcLq-^x45JRS1+%E^do6+pY)OCI_kBL^ z^L^j<-uGRTsW5+e-$PrRKtwBnona~L!R4zM%2+9EyT(WuJ-NWa6x8ydq_(isQtPy6tyorO zq|Q%50XGn7)bDn&0_mr)pe_lYB{PnpL5k?4FtgEw=5jnhH42S_z%nCI9dEUf#rij< zo#BeY9HQtUaop$gDSYV)j<@4VtyYT@DqN+KLxx-kup;f3v%*?QBBY@Qf`w;1BEzw$ zq)AtDUXj8uh@;cuB4e9XXNBqG!$jZ`f-4mS{yZJ{nMLRlGLP$o z&vS(7TiC@9&vd3g)Ss{yRIHkb)1 zFQmau+rd`A+C>M2DTx<=?TqzByCmfDN|o5gGH`3vtc!UTqp%DWuAGI+7KEf!lP1Ow zTxLDv2CM*8XQG$|%N7B1ITy#5z_tbywn?K&*97;QsRbFtjhq$2=`TQr+*}jS*%%kZ z@(r+YE4_?MlrtVIH2ddM&^j z3>C_SP=T|FKAH#Fc35Q!%eL7VSfl`IlG+zlp(+KTP|tPoIRKPf{BZbmXt;Fmp2eoa z=S8mz5}v!L&@W_z0{~7Ed}fru#mq1QESx|*95vss`9+B!VY?YvnE3@kkPZ9m_EQDD zo0G0r^jGDbj;@KRzF|7DF+QPsAT_=%=TyR5UgFYU%UaaQa>d>TXHU<*>!%xcU+9SL zXh0u@jf{;RAH&u?#ZxZsoEYwU?ZJKO{!m!Xmp9dEG2!a&suQu*%1_G^8qdYVY|g42 zJJbwr8j53&{&sgw=9Qtmz@f=YS^39WE+h`eHQAf#H=8ncp3FG2Tcy_2=e|;`v)W?T)HzCD&GN>rbh;(bdimjkF(hwtI`7 zerqbMDEpoKVP*39o$Cr>+P?TWw(k_SdfV;JtNYxS1F}cQ>eIUKom1~?75P%ENV#B?PR&Lb*-5QGoBgi((fy> zb5lo|zbC^ttl*oL9*K&DZ;zKf1!V$)EQ^!AVMt4BA~b3Z`s~uggI|53j7Es1vYx4_ z=I9e!lEzKzS2UPnkpqF_t8X7v6MqhT(E8rj<6Re5{q*aBxZXxZxlTB_{+~gr?QQAB NWXLPjcjUa=@GmQdSu_9u literal 0 HcmV?d00001 diff --git a/applications/main/ibutton/application.fam b/applications/main/ibutton/application.fam index 06968bba4..a8faa629c 100644 --- a/applications/main/ibutton/application.fam +++ b/applications/main/ibutton/application.fam @@ -1,25 +1,21 @@ App( appid="ibutton", name="iButton", - apptype=FlipperAppType.APP, + apptype=FlipperAppType.MENUEXTERNAL, targets=["f7"], entry_point="ibutton_app", - cdefines=["APP_IBUTTON"], - requires=[ - "gui", - "dialogs", - ], - provides=["ibutton_start"], icon="A_iButton_14", stack_size=2 * 1024, order=60, fap_libs=["assets"], + fap_icon="icon.png", + fap_category="iButton", ) App( appid="ibutton_start", apptype=FlipperAppType.STARTUP, + targets=["f7"], entry_point="ibutton_on_system_start", - requires=["ibutton"], order=60, ) diff --git a/applications/main/ibutton/icon.png b/applications/main/ibutton/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2fdaf123a657c00c9c84632ca3c151674e451ae1 GIT binary patch literal 304 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2xkYHHq`AGmsv7|ftIx;Y9?C1WI$O_~uBzpw; zGB8xBF)%c=FfjZA3N^f7U???UV0e|lz+g3lfkC`r&aOZkpafHrx4R1i<>&pI=m5)bW_|craZ$KesPZ!4!j_b)kjvx52z42i= z^Wk##wtdVzTiGS{99;2>!TC2M!yZeXz}?LkD}l;YOI#yLQW8s2t&)pUffR$0fsvuE zfvK*cNr<75m9c@9v4ysQft7*5`ikN&C>nC}Q!>*kp&E>VdO{3LtqcsU49p-Jly36? Qy~)7f>FVdQ&MBb@0C$~I0{{R3 literal 0 HcmV?d00001 diff --git a/applications/main/infrared/application.fam b/applications/main/infrared/application.fam index e5483e9ff..b78b088a7 100644 --- a/applications/main/infrared/application.fam +++ b/applications/main/infrared/application.fam @@ -1,25 +1,21 @@ App( appid="infrared", name="Infrared", - apptype=FlipperAppType.APP, + apptype=FlipperAppType.MENUEXTERNAL, entry_point="infrared_app", targets=["f7"], - cdefines=["APP_INFRARED"], - requires=[ - "gui", - "dialogs", - ], - provides=["infrared_start"], icon="A_Infrared_14", stack_size=3 * 1024, order=40, fap_libs=["assets"], + fap_icon="icon.png", + fap_category="Infrared", ) App( appid="infrared_start", apptype=FlipperAppType.STARTUP, + targets=["f7"], entry_point="infrared_on_system_start", - requires=["infrared"], order=20, ) diff --git a/applications/main/infrared/icon.png b/applications/main/infrared/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..22c986180a2bed76dbe4ff439df1cf9177533c32 GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2xkYHHq`AGmsv7|ftIx;Y9?C1WI$O_~uBzpw; zGB8xBF)%c=FfjZA3N^f7U???UV0e|lz+g3lfkC`r&aOZkpafHrx4R1i<>&pI=m5)bWC*+s&X`qmbr;B3<$Ms~3f`-KX%+5*7 zhxan`%;z`w!#>%c-@wM^z<~n{3>VXQv+hhNs0FH5Epd$~Nl7e8wMs5Z1yT$~21bUu z2Bx}(CLxAKR>lTa#unNJ237_J>nn=CplHa=PsvQHglaGb>IpG01*)?$HiBr_e$xf$ PHwFezS3j3^P6<>&pI=m5)bWZjP>yH&963)5S4_<9hOs!iI<>&pI=m5)b(dHL6nbwD9yPZ!4!j_b)k${QZ;XFmLn zjqNsD+YPq1J8W%_*aXBie!OR3*tC!PwU_7Q9H4U564!{5l*E!$tK_0oAjM#0U}UIk zV5)0q5@Kj%Wo%$&Y@uynU}a#izM}XGiiX_$l+3hBs0L%8o)7~QD^p9LQiz6svOM}g O4Gf;HelF{r5}E+GUQp8j literal 0 HcmV?d00001 diff --git a/applications/main/onewire/application.fam b/applications/main/onewire/application.fam index 68d4f6716..3d35abce9 100644 --- a/applications/main/onewire/application.fam +++ b/applications/main/onewire/application.fam @@ -1,14 +1,6 @@ -App( - appid="onewire", - name="1-Wire", - apptype=FlipperAppType.METAPACKAGE, - provides=["onewire_start"], -) - App( appid="onewire_start", apptype=FlipperAppType.STARTUP, entry_point="onewire_on_system_start", - requires=["onewire"], order=60, ) diff --git a/applications/main/subghz/application.fam b/applications/main/subghz/application.fam index f0dc66e89..4f21cb6c4 100644 --- a/applications/main/subghz/application.fam +++ b/applications/main/subghz/application.fam @@ -1,25 +1,21 @@ App( appid="subghz", name="Sub-GHz", - apptype=FlipperAppType.APP, + apptype=FlipperAppType.MENUEXTERNAL, targets=["f7"], entry_point="subghz_app", - cdefines=["APP_SUBGHZ"], - requires=[ - "gui", - "cli", - "dialogs", - ], - provides=["subghz_start"], icon="A_Sub1ghz_14", stack_size=3 * 1024, order=10, + fap_libs=["assets", "hwdrivers"], + fap_icon="icon.png", + fap_category="Sub-GHz", ) App( appid="subghz_start", + targets=["f7"], apptype=FlipperAppType.STARTUP, entry_point="subghz_on_system_start", - requires=["subghz"], order=40, ) diff --git a/applications/main/subghz/icon.png b/applications/main/subghz/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5a25fdf4ef1c6cf53634aa74675001a3e8c85b7b GIT binary patch literal 299 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2xkYHHq`AGmsv7|ftIx;Y9?C1WI$O_~uBzpw; zGB8xBF)%c=FfjZA3N^f7U???UV0e|lz+g3lfkC`r&aOZkpafHrx4R1i<>&pI=m5)cB{fFDGZlI8yr;B3<$MxhJ?+;A4eL&#) z0Ra}bue?07WhLz78x$BO|L3mq-MMxdP^D^#YeY#(Vo9o1a#1RfVlXl=GSoFN)ipE; zF*LF=Hn1|b&^9ozGB8+QQTzo(LvDUbW?CgwgE3G~h=HkEX>4Tx04R}tkv&MmKpe$i(`rSk4t5Z6$WWau6cusQDionYs1;guFuC*#nlvOW zE{=k0!NHHks)LKOt`4q(Aou~|=;Wm6A|?JWDYS_3;J6>}?mh0_0Yan9G%FATG`(u3 z5^*t;T@{0`5D-8=V(6BcWz0!Z5}xDh9zMR_MR}I@xj#prnzI<-6NzV;VOEJZh^IHJ z2Iqa^Fe}O`@j3ChNf#u3C`-Nm{=@yu+qV-Xlle$#1U1~DPPFA zta9Gstd(o5bx;1nP)=W2<~q$0B(R7jND!f*h7!uCB1)@HiiH&I$36VRj$a~|Laq`R zITlcX2HEk0|H1EWt^DMKn-q!zT`#u%F$x5Cfo9#dzmILZc>?&Kfh)c3uQY&}Ptxmc zEph}5Yy%h9ZB5w&E_Z;TCqp)6NAlAY@_FF>jJ_!g4Bi60Yi@6?eVjf3Y3eF@0~{Oz zV+G1y_jq?tXK(+WY4!I5C=YUpXXIhH00006VoOIv00000008+zyMF)x010qNS#tmY z3ljhU3ljkVnw%H_000McNliru<^lu{1uVUoNs|Bo07OYdK~xyijgYww05Avx?TGzX zz7!EC4G1?heldU+2uZR%k^uSL+0?e2taR-}6`h2x#_2kxune}*>oEbW-V;;Yj|primary_menu, + FLIPPER_EXTERNAL_APPS[i].name, + FLIPPER_EXTERNAL_APPS[i].icon, + i, + loader_menu_external_apps_callback, + (void*)menu); + } + for(i = 0; i < FLIPPER_APPS_COUNT; i++) { menu_add_item( app->primary_menu, FLIPPER_APPS[i].name, FLIPPER_APPS[i].icon, i, - loader_menu_callback, + loader_menu_apps_callback, (void*)menu); } menu_add_item( diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index 5704870c9..014970113 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,33.2,, +Version,+,34.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 29739abb5..2e02608a3 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,33.2,, +Version,+,34.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -147,7 +147,12 @@ Header,+,lib/mlib/m-rbtree.h,, Header,+,lib/mlib/m-tuple.h,, Header,+,lib/mlib/m-variant.h,, Header,+,lib/music_worker/music_worker.h,, +Header,+,lib/nfc/helpers/mfkey32.h,, +Header,+,lib/nfc/helpers/nfc_generators.h,, Header,+,lib/nfc/nfc_device.h,, +Header,+,lib/nfc/nfc_types.h,, +Header,+,lib/nfc/nfc_worker.h,, +Header,+,lib/nfc/parsers/nfc_supported_card.h,, Header,+,lib/nfc/protocols/nfc_util.h,, Header,+,lib/one_wire/maxim_crc.h,, Header,+,lib/one_wire/one_wire_host.h,, @@ -1935,40 +1940,40 @@ Function,-,mf_classic_authenticate,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint6 Function,-,mf_classic_authenticate_skip_activate,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint64_t, MfClassicKey, _Bool, uint32_t" Function,-,mf_classic_block_to_value,_Bool,"const uint8_t*, int32_t*, uint8_t*" Function,-,mf_classic_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t" -Function,-,mf_classic_dict_add_key,_Bool,"MfClassicDict*, uint8_t*" +Function,+,mf_classic_dict_add_key,_Bool,"MfClassicDict*, uint8_t*" Function,-,mf_classic_dict_add_key_str,_Bool,"MfClassicDict*, FuriString*" -Function,-,mf_classic_dict_alloc,MfClassicDict*,MfClassicDictType -Function,-,mf_classic_dict_check_presence,_Bool,MfClassicDictType -Function,-,mf_classic_dict_delete_index,_Bool,"MfClassicDict*, uint32_t" +Function,+,mf_classic_dict_alloc,MfClassicDict*,MfClassicDictType +Function,+,mf_classic_dict_check_presence,_Bool,MfClassicDictType +Function,+,mf_classic_dict_delete_index,_Bool,"MfClassicDict*, uint32_t" Function,-,mf_classic_dict_find_index,_Bool,"MfClassicDict*, uint8_t*, uint32_t*" Function,-,mf_classic_dict_find_index_str,_Bool,"MfClassicDict*, FuriString*, uint32_t*" -Function,-,mf_classic_dict_free,void,MfClassicDict* +Function,+,mf_classic_dict_free,void,MfClassicDict* Function,-,mf_classic_dict_get_key_at_index,_Bool,"MfClassicDict*, uint64_t*, uint32_t" -Function,-,mf_classic_dict_get_key_at_index_str,_Bool,"MfClassicDict*, FuriString*, uint32_t" +Function,+,mf_classic_dict_get_key_at_index_str,_Bool,"MfClassicDict*, FuriString*, uint32_t" Function,-,mf_classic_dict_get_next_key,_Bool,"MfClassicDict*, uint64_t*" -Function,-,mf_classic_dict_get_next_key_str,_Bool,"MfClassicDict*, FuriString*" -Function,-,mf_classic_dict_get_total_keys,uint32_t,MfClassicDict* -Function,-,mf_classic_dict_is_key_present,_Bool,"MfClassicDict*, uint8_t*" +Function,+,mf_classic_dict_get_next_key_str,_Bool,"MfClassicDict*, FuriString*" +Function,+,mf_classic_dict_get_total_keys,uint32_t,MfClassicDict* +Function,+,mf_classic_dict_is_key_present,_Bool,"MfClassicDict*, uint8_t*" Function,-,mf_classic_dict_is_key_present_str,_Bool,"MfClassicDict*, FuriString*" Function,-,mf_classic_dict_rewind,_Bool,MfClassicDict* Function,-,mf_classic_emulator,_Bool,"MfClassicEmulator*, FuriHalNfcTxRxContext*, _Bool" Function,-,mf_classic_get_classic_type,MfClassicType,"uint8_t, uint8_t, uint8_t" -Function,-,mf_classic_get_read_sectors_and_keys,void,"MfClassicData*, uint8_t*, uint8_t*" -Function,-,mf_classic_get_sector_by_block,uint8_t,uint8_t +Function,+,mf_classic_get_read_sectors_and_keys,void,"MfClassicData*, uint8_t*, uint8_t*" +Function,+,mf_classic_get_sector_by_block,uint8_t,uint8_t Function,-,mf_classic_get_sector_trailer_block_num_by_sector,uint8_t,uint8_t -Function,-,mf_classic_get_sector_trailer_by_sector,MfClassicSectorTrailer*,"MfClassicData*, uint8_t" +Function,+,mf_classic_get_sector_trailer_by_sector,MfClassicSectorTrailer*,"MfClassicData*, uint8_t" Function,-,mf_classic_get_total_block_num,uint16_t,MfClassicType -Function,-,mf_classic_get_total_sectors_num,uint8_t,MfClassicType +Function,+,mf_classic_get_total_sectors_num,uint8_t,MfClassicType Function,-,mf_classic_get_type_str,const char*,MfClassicType Function,-,mf_classic_halt,void,"FuriHalNfcTxRxContext*, Crypto1*" Function,-,mf_classic_is_allowed_access_data_block,_Bool,"MfClassicData*, uint8_t, MfClassicKey, MfClassicAction" Function,-,mf_classic_is_allowed_access_sector_trailer,_Bool,"MfClassicData*, uint8_t, MfClassicKey, MfClassicAction" -Function,-,mf_classic_is_block_read,_Bool,"MfClassicData*, uint8_t" -Function,-,mf_classic_is_card_read,_Bool,MfClassicData* -Function,-,mf_classic_is_key_found,_Bool,"MfClassicData*, uint8_t, MfClassicKey" +Function,+,mf_classic_is_block_read,_Bool,"MfClassicData*, uint8_t" +Function,+,mf_classic_is_card_read,_Bool,MfClassicData* +Function,+,mf_classic_is_key_found,_Bool,"MfClassicData*, uint8_t, MfClassicKey" Function,-,mf_classic_is_sector_data_read,_Bool,"MfClassicData*, uint8_t" Function,-,mf_classic_is_sector_read,_Bool,"MfClassicData*, uint8_t" -Function,-,mf_classic_is_sector_trailer,_Bool,uint8_t +Function,+,mf_classic_is_sector_trailer,_Bool,uint8_t Function,-,mf_classic_is_value_block,_Bool,"MfClassicData*, uint8_t" Function,-,mf_classic_read_block,_Bool,"FuriHalNfcTxRxContext*, Crypto1*, uint8_t, MfClassicBlock*" Function,-,mf_classic_read_card,uint8_t,"FuriHalNfcTxRxContext*, MfClassicReader*, MfClassicData*" @@ -1986,10 +1991,10 @@ Function,-,mf_classic_value_to_block,void,"int32_t, uint8_t, uint8_t*" Function,-,mf_classic_write_block,_Bool,"FuriHalNfcTxRxContext*, Crypto1*, uint8_t, MfClassicBlock*" Function,-,mf_classic_write_sector,_Bool,"FuriHalNfcTxRxContext*, MfClassicData*, MfClassicData*, uint8_t" Function,-,mf_df_cat_application,void,"MifareDesfireApplication*, FuriString*" -Function,-,mf_df_cat_application_info,void,"MifareDesfireApplication*, FuriString*" -Function,-,mf_df_cat_card_info,void,"MifareDesfireData*, FuriString*" +Function,+,mf_df_cat_application_info,void,"MifareDesfireApplication*, FuriString*" +Function,+,mf_df_cat_card_info,void,"MifareDesfireData*, FuriString*" Function,-,mf_df_cat_data,void,"MifareDesfireData*, FuriString*" -Function,-,mf_df_cat_file,void,"MifareDesfireFile*, FuriString*" +Function,+,mf_df_cat_file,void,"MifareDesfireFile*, FuriString*" Function,-,mf_df_cat_free_mem,void,"MifareDesfireFreeMemory*, FuriString*" Function,-,mf_df_cat_key_settings,void,"MifareDesfireKeySettings*, FuriString*" Function,-,mf_df_cat_version,void,"MifareDesfireVersion*, FuriString*" @@ -2019,8 +2024,8 @@ Function,-,mf_df_prepare_read_records,uint16_t,"uint8_t*, uint8_t, uint32_t, uin Function,-,mf_df_prepare_select_application,uint16_t,"uint8_t*, uint8_t[3]" Function,-,mf_df_read_card,_Bool,"FuriHalNfcTxRxContext*, MifareDesfireData*" Function,-,mf_ul_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t" -Function,-,mf_ul_emulation_supported,_Bool,MfUltralightData* -Function,-,mf_ul_is_full_capture,_Bool,MfUltralightData* +Function,+,mf_ul_emulation_supported,_Bool,MfUltralightData* +Function,+,mf_ul_is_full_capture,_Bool,MfUltralightData* Function,-,mf_ul_prepare_emulation,void,"MfUltralightEmulator*, MfUltralightData*" Function,-,mf_ul_prepare_emulation_response,_Bool,"uint8_t*, uint16_t, uint8_t*, uint16_t*, uint32_t*, void*" Function,-,mf_ul_pwdgen_amiibo,uint32_t,FuriHalNfcDevData* @@ -2030,13 +2035,18 @@ Function,-,mf_ul_reset,void,MfUltralightData* Function,-,mf_ul_reset_emulation,void,"MfUltralightEmulator*, _Bool" Function,-,mf_ultralight_authenticate,_Bool,"FuriHalNfcTxRxContext*, uint32_t, uint16_t*" Function,-,mf_ultralight_fast_read_pages,_Bool,"FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*" -Function,-,mf_ultralight_get_config_pages,MfUltralightConfigPages*,MfUltralightData* +Function,+,mf_ultralight_get_config_pages,MfUltralightConfigPages*,MfUltralightData* Function,-,mf_ultralight_read_counters,_Bool,"FuriHalNfcTxRxContext*, MfUltralightData*" Function,-,mf_ultralight_read_pages,_Bool,"FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*" Function,-,mf_ultralight_read_pages_direct,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint8_t*" Function,-,mf_ultralight_read_signature,_Bool,"FuriHalNfcTxRxContext*, MfUltralightData*" Function,-,mf_ultralight_read_tearing_flags,_Bool,"FuriHalNfcTxRxContext*, MfUltralightData*" Function,-,mf_ultralight_read_version,_Bool,"FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*" +Function,-,mfkey32_alloc,Mfkey32*,uint32_t +Function,-,mfkey32_free,void,Mfkey32* +Function,+,mfkey32_get_auth_sectors,uint16_t,FuriString* +Function,-,mfkey32_process_data,void,"Mfkey32*, uint8_t*, uint16_t, _Bool, _Bool" +Function,-,mfkey32_set_callback,void,"Mfkey32*, Mfkey32ParseDataCallback, void*" Function,-,mkdtemp,char*,char* Function,-,mkostemp,int,"char*, int" Function,-,mkostemps,int,"char*, int, int" @@ -2085,11 +2095,25 @@ Function,+,nfc_device_save_shadow,_Bool,"NfcDevice*, const char*" Function,+,nfc_device_set_loading_callback,void,"NfcDevice*, NfcLoadingCallback, void*" Function,+,nfc_device_set_name,void,"NfcDevice*, const char*" Function,+,nfc_file_select,_Bool,NfcDevice* +Function,-,nfc_generate_mf_classic,void,"NfcDeviceData*, uint8_t, MfClassicType" +Function,+,nfc_get_dev_type,const char*,FuriHalNfcType +Function,-,nfc_guess_protocol,const char*,NfcProtocol +Function,+,nfc_mf_classic_type,const char*,MfClassicType +Function,+,nfc_mf_ul_type,const char*,"MfUltralightType, _Bool" +Function,+,nfc_supported_card_verify_and_parse,_Bool,NfcDeviceData* Function,+,nfc_util_bytes2num,uint64_t,"const uint8_t*, uint8_t" Function,+,nfc_util_even_parity32,uint8_t,uint32_t Function,+,nfc_util_num2bytes,void,"uint64_t, uint8_t, uint8_t*" Function,+,nfc_util_odd_parity,void,"const uint8_t*, uint8_t*, uint8_t" Function,+,nfc_util_odd_parity8,uint8_t,uint8_t +Function,+,nfc_worker_alloc,NfcWorker*, +Function,+,nfc_worker_free,void,NfcWorker* +Function,+,nfc_worker_get_state,NfcWorkerState,NfcWorker* +Function,-,nfc_worker_nfcv_emulate,void,NfcWorker* +Function,-,nfc_worker_nfcv_sniff,void,NfcWorker* +Function,-,nfc_worker_nfcv_unlock,void,NfcWorker* +Function,+,nfc_worker_start,void,"NfcWorker*, NfcWorkerState, NfcDeviceData*, NfcWorkerCallback, void*" +Function,+,nfc_worker_stop,void,NfcWorker* Function,-,nfca_append_crc16,void,"uint8_t*, uint16_t" Function,-,nfca_emulation_handler,_Bool,"uint8_t*, uint16_t, uint8_t*, uint16_t*" Function,-,nfca_get_crc16,uint16_t,"uint8_t*, uint16_t" @@ -2666,6 +2690,7 @@ Function,-,strupr,char*,char* Function,-,strverscmp,int,"const char*, const char*" Function,-,strxfrm,size_t,"char*, const char*, size_t" Function,-,strxfrm_l,size_t,"char*, const char*, size_t, locale_t" +Function,-,stub_parser_verify_read,_Bool,"NfcWorker*, FuriHalNfcTxRxContext*" Function,+,subghz_block_generic_deserialize,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*" Function,+,subghz_block_generic_deserialize_check_count_bit,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*, uint16_t" Function,+,subghz_block_generic_get_preset_name,void,"const char*, FuriString*" @@ -3358,6 +3383,8 @@ Variable,+,message_red_255,const NotificationMessage, Variable,+,message_sound_off,const NotificationMessage, Variable,+,message_vibro_off,const NotificationMessage, Variable,+,message_vibro_on,const NotificationMessage, +Variable,+,nfc_generators,const NfcGenerator*[], +Variable,-,nfc_supported_card,NfcSupportedCard[NfcSupportedCardTypeEnd], Variable,+,sequence_audiovisual_alert,const NotificationSequence, Variable,+,sequence_blink_blue_10,const NotificationSequence, Variable,+,sequence_blink_blue_100,const NotificationSequence, diff --git a/lib/nfc/SConscript b/lib/nfc/SConscript index b8551db84..7a0859ee4 100644 --- a/lib/nfc/SConscript +++ b/lib/nfc/SConscript @@ -6,6 +6,11 @@ env.Append( ], SDK_HEADERS=[ File("nfc_device.h"), + File("nfc_worker.h"), + File("nfc_types.h"), + File("helpers/mfkey32.h"), + File("parsers/nfc_supported_card.h"), + File("helpers/nfc_generators.h"), File("protocols/nfc_util.h"), ], ) diff --git a/lib/nfc/helpers/mf_classic_dict.h b/lib/nfc/helpers/mf_classic_dict.h index 3b2d560ad..b798b1c92 100644 --- a/lib/nfc/helpers/mf_classic_dict.h +++ b/lib/nfc/helpers/mf_classic_dict.h @@ -6,6 +6,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + typedef enum { MfClassicDictTypeUser, MfClassicDictTypeSystem, @@ -97,3 +101,7 @@ bool mf_classic_dict_find_index_str(MfClassicDict* dict, FuriString* key, uint32 * @return true on success */ bool mf_classic_dict_delete_index(MfClassicDict* dict, uint32_t target); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/nfc/helpers/mfkey32.h b/lib/nfc/helpers/mfkey32.h index e1f472e50..e29043224 100644 --- a/lib/nfc/helpers/mfkey32.h +++ b/lib/nfc/helpers/mfkey32.h @@ -2,6 +2,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct Mfkey32 Mfkey32; typedef enum { @@ -24,3 +28,7 @@ void mfkey32_process_data( void mfkey32_set_callback(Mfkey32* instance, Mfkey32ParseDataCallback callback, void* context); uint16_t mfkey32_get_auth_sectors(FuriString* string); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/nfc/nfc_types.h b/lib/nfc/nfc_types.h index fb53ce7c2..5ebb2d27b 100644 --- a/lib/nfc/nfc_types.h +++ b/lib/nfc/nfc_types.h @@ -2,6 +2,10 @@ #include "nfc_device.h" +#ifdef __cplusplus +extern "C" { +#endif + const char* nfc_get_dev_type(FuriHalNfcType type); const char* nfc_guess_protocol(NfcProtocol protocol); @@ -9,3 +13,7 @@ const char* nfc_guess_protocol(NfcProtocol protocol); const char* nfc_mf_ul_type(MfUltralightType type, bool full_name); const char* nfc_mf_classic_type(MfClassicType type); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/nfc/nfc_worker.h b/lib/nfc/nfc_worker.h index 722f14857..f9f5900bb 100644 --- a/lib/nfc/nfc_worker.h +++ b/lib/nfc/nfc_worker.h @@ -2,6 +2,10 @@ #include "nfc_device.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct NfcWorker NfcWorker; typedef enum { @@ -97,4 +101,8 @@ void nfc_worker_start( void nfc_worker_stop(NfcWorker* nfc_worker); void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker); void nfc_worker_nfcv_emulate(NfcWorker* nfc_worker); -void nfc_worker_nfcv_sniff(NfcWorker* nfc_worker); \ No newline at end of file +void nfc_worker_nfcv_sniff(NfcWorker* nfc_worker); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/nfc/parsers/nfc_supported_card.h b/lib/nfc/parsers/nfc_supported_card.h index 877bda737..2e8c48a87 100644 --- a/lib/nfc/parsers/nfc_supported_card.h +++ b/lib/nfc/parsers/nfc_supported_card.h @@ -4,6 +4,10 @@ #include "../nfc_worker.h" #include "../nfc_device.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef enum { NfcSupportedCardTypePlantain, NfcSupportedCardTypeTroika, @@ -37,3 +41,7 @@ bool nfc_supported_card_verify_and_parse(NfcDeviceData* dev_data); // support the card. This is needed for DESFire card parsers which can't // provide keys, and only use NfcSupportedCard->parse. bool stub_parser_verify_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/nfc/protocols/crypto1.h b/lib/nfc/protocols/crypto1.h index 450d1534e..bbf6dc239 100644 --- a/lib/nfc/protocols/crypto1.h +++ b/lib/nfc/protocols/crypto1.h @@ -3,6 +3,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { uint32_t odd; uint32_t even; @@ -35,3 +39,7 @@ void crypto1_encrypt( uint16_t plain_data_bits, uint8_t* encrypted_data, uint8_t* encrypted_parity); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/nfc/protocols/mifare_classic.h b/lib/nfc/protocols/mifare_classic.h index b3e3cbdf8..7efe81b8c 100644 --- a/lib/nfc/protocols/mifare_classic.h +++ b/lib/nfc/protocols/mifare_classic.h @@ -4,6 +4,10 @@ #include "crypto1.h" +#ifdef __cplusplus +extern "C" { +#endif + #define MF_CLASSIC_BLOCK_SIZE (16) #define MF_CLASSIC_TOTAL_BLOCKS_MAX (256) #define MF_MINI_TOTAL_SECTORS_NUM (5) @@ -241,3 +245,7 @@ bool mf_classic_write_sector( MfClassicData* dest_data, MfClassicData* src_data, uint8_t sec_num); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/nfc/protocols/mifare_desfire.h b/lib/nfc/protocols/mifare_desfire.h index 3dc7c4c2a..8faa98ec2 100644 --- a/lib/nfc/protocols/mifare_desfire.h +++ b/lib/nfc/protocols/mifare_desfire.h @@ -5,6 +5,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + #define MF_DF_GET_VERSION (0x60) #define MF_DF_GET_FREE_MEMORY (0x6E) #define MF_DF_GET_KEY_SETTINGS (0x45) @@ -169,3 +173,7 @@ uint16_t mf_df_prepare_read_records(uint8_t* dest, uint8_t file_id, uint32_t off bool mf_df_parse_read_data_response(uint8_t* buf, uint16_t len, MifareDesfireFile* out); bool mf_df_read_card(FuriHalNfcTxRxContext* tx_rx, MifareDesfireData* data); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/nfc/protocols/mifare_ultralight.h b/lib/nfc/protocols/mifare_ultralight.h index d444fa798..9cb7ca535 100644 --- a/lib/nfc/protocols/mifare_ultralight.h +++ b/lib/nfc/protocols/mifare_ultralight.h @@ -2,6 +2,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + // Largest tag is NTAG I2C Plus 2K, both data sectors plus SRAM #define MF_UL_MAX_DUMP_SIZE ((238 + 256 + 16) * 4) @@ -259,3 +263,7 @@ uint32_t mf_ul_pwdgen_amiibo(FuriHalNfcDevData* data); uint32_t mf_ul_pwdgen_xiaomi(FuriHalNfcDevData* data); bool mf_ul_is_full_capture(MfUltralightData* data); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/scripts/fbt/appmanifest.py b/scripts/fbt/appmanifest.py index 73e5c7770..5b830dda9 100644 --- a/scripts/fbt/appmanifest.py +++ b/scripts/fbt/appmanifest.py @@ -18,6 +18,7 @@ class FlipperAppType(Enum): SETTINGS = "Settings" STARTUP = "StartupHook" EXTERNAL = "External" + MENUEXTERNAL = "MenuExternal" METAPACKAGE = "Package" PLUGIN = "Plugin" @@ -213,7 +214,7 @@ class AppBuildset: appmgr: AppManager, appnames: List[str], hw_target: str, - message_writer: Callable = None, + message_writer: Callable | None = None, ): self.appmgr = appmgr self.appnames = set(appnames) @@ -367,6 +368,11 @@ class ApplicationsCGenerator: ), } + APP_EXTERNAL_TYPE = ( + "FlipperExternalApplication", + "FLIPPER_EXTERNAL_APPS", + ) + def __init__(self, buildset: AppBuildset, autorun_app: str = ""): self.buildset = buildset self.autorun = autorun_app @@ -387,6 +393,17 @@ class ApplicationsCGenerator: .icon = {f"&{app.icon}" if app.icon else "NULL"}, .flags = {'|'.join(f"FlipperInternalApplicationFlag{flag}" for flag in app.flags)} }}""" + def get_external_app_descr(self, app: FlipperApplication): + app_path = "/ext/apps" + if app.fap_category: + app_path += f"/{app.fap_category}" + app_path += f"/{app.appid}.fap" + return f""" + {{ + .name = "{app.name}", + .icon = {f"&{app.icon}" if app.icon else "NULL"}, + .path = "{app_path}" }}""" + def generate(self): contents = [ '#include "applications.h"', @@ -418,4 +435,11 @@ class ApplicationsCGenerator: ] ) + entry_type, entry_block = self.APP_EXTERNAL_TYPE + external_apps = self.buildset.get_apps_of_type(FlipperAppType.MENUEXTERNAL) + contents.append(f"const {entry_type} {entry_block}[] = {{") + contents.append(",\n".join(map(self.get_external_app_descr, external_apps))) + contents.append("};") + contents.append(f"const size_t {entry_block}_COUNT = COUNT_OF({entry_block});") + return "\n".join(contents) diff --git a/scripts/fbt_tools/fbt_extapps.py b/scripts/fbt_tools/fbt_extapps.py index 69d700214..a6cd831d4 100644 --- a/scripts/fbt_tools/fbt_extapps.py +++ b/scripts/fbt_tools/fbt_extapps.py @@ -423,7 +423,10 @@ def AddAppLaunchTarget(env, appname, launch_target_name): host_app = env["APPMGR"].get(artifacts_app_to_run.app.requires[0]) if host_app: - if host_app.apptype == FlipperAppType.EXTERNAL: + if host_app.apptype in [ + FlipperAppType.EXTERNAL, + FlipperAppType.MENUEXTERNAL, + ]: _add_host_app_to_targets(host_app) else: # host app is a built-in app diff --git a/scripts/ufbt/SConstruct b/scripts/ufbt/SConstruct index 8812a4e55..703a9187a 100644 --- a/scripts/ufbt/SConstruct +++ b/scripts/ufbt/SConstruct @@ -262,6 +262,7 @@ apps_artifacts = appenv["EXT_APPS"] apps_to_build_as_faps = [ FlipperAppType.PLUGIN, FlipperAppType.EXTERNAL, + FlipperAppType.MENUEXTERNAL, ] known_extapps = [ diff --git a/site_scons/extapps.scons b/site_scons/extapps.scons index 6db0e538d..0893c4556 100644 --- a/site_scons/extapps.scons +++ b/site_scons/extapps.scons @@ -67,6 +67,7 @@ class FlipperExtAppBuildArtifacts: apps_to_build_as_faps = [ FlipperAppType.PLUGIN, FlipperAppType.EXTERNAL, + FlipperAppType.MENUEXTERNAL, FlipperAppType.DEBUG, ] From e56b970eb42a203e6905644ee15f66df99775df8 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 10 Jul 2023 16:48:18 +0300 Subject: [PATCH 08/14] update mifare nested --- applications/external/mifare_nested/application.fam | 2 +- applications/external/mifare_nested/mifare_nested_i.h | 2 +- .../external/mifare_nested/mifare_nested_worker.c | 8 ++++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/applications/external/mifare_nested/application.fam b/applications/external/mifare_nested/application.fam index 5b2c0b466..36dfb2673 100644 --- a/applications/external/mifare_nested/application.fam +++ b/applications/external/mifare_nested/application.fam @@ -21,5 +21,5 @@ App( fap_author="AloneLiberty", fap_description="Recover Mifare Classic keys", fap_weburl="https://github.com/AloneLiberty/FlipperNested", - fap_version="1.5.0" + fap_version="1.5.1" ) diff --git a/applications/external/mifare_nested/mifare_nested_i.h b/applications/external/mifare_nested/mifare_nested_i.h index 69907dcd0..b99f785c6 100644 --- a/applications/external/mifare_nested/mifare_nested_i.h +++ b/applications/external/mifare_nested/mifare_nested_i.h @@ -21,7 +21,7 @@ #include #include "mifare_nested_icons.h" -#define NESTED_VERSION_APP "1.5.0" +#define NESTED_VERSION_APP "1.5.1" #define NESTED_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNested" #define NESTED_RECOVER_KEYS_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNestedRecovery" #define NESTED_NONCE_FORMAT_VERSION "3" diff --git a/applications/external/mifare_nested/mifare_nested_worker.c b/applications/external/mifare_nested/mifare_nested_worker.c index 7598d28c9..360b38f4a 100644 --- a/applications/external/mifare_nested/mifare_nested_worker.c +++ b/applications/external/mifare_nested/mifare_nested_worker.c @@ -478,9 +478,13 @@ SaveNoncesResult_t* mifare_nested_worker_write_nonces( for(uint8_t sector = 0; sector < sector_count; sector++) { for(uint8_t key_type = 0; key_type < 2; key_type++) { if(nonces->nonces[sector][key_type][tries]->invalid) { - result->invalid++; + if (tries == 0) { + result->invalid++; + } } else if(nonces->nonces[sector][key_type][tries]->skipped) { - result->skipped++; + if (tries == 0) { + result->skipped++; + } } else if(nonces->nonces[sector][key_type][tries]->collected) { if(nonces->nonces[sector][key_type][tries]->hardnested) { FuriString* hardnested_path = furi_string_alloc(); From b451fa91def8a4020986e58da4675ad8c51f8774 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 10 Jul 2023 16:52:12 +0300 Subject: [PATCH 09/14] Update wifi marauder app --- .../wifi_marauder_scene_console_output.c | 5 + .../scenes/wifi_marauder_scene_flasher.c | 172 ++++++++++++++++-- .../scenes/wifi_marauder_scene_start.c | 1 - .../wifi_marauder_app.c | 1 + .../wifi_marauder_app.h | 2 +- .../wifi_marauder_app_i.h | 17 ++ .../wifi_marauder_custom_event.h | 3 +- .../wifi_marauder_flasher.c | 113 ++++++++---- .../wifi_marauder_flasher.h | 7 + 9 files changed, 264 insertions(+), 57 deletions(-) diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c index 236fe4eff..9e1719d08 100644 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c +++ b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c @@ -182,6 +182,11 @@ bool wifi_marauder_scene_console_output_on_event(void* context, SceneManagerEven consumed = true; } else if(event.type == SceneManagerEventTypeTick) { consumed = true; + } else { + if(app->flash_worker_busy) { + // ignore button presses while flashing + consumed = true; + } } return consumed; diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_flasher.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_flasher.c index 79682879d..8fe91bbba 100644 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_flasher.c +++ b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_flasher.c @@ -1,9 +1,14 @@ #include "../wifi_marauder_app_i.h" +#include "../wifi_marauder_flasher.h" enum SubmenuIndex { + SubmenuIndexS3Mode, SubmenuIndexBoot, SubmenuIndexPart, + SubmenuIndexNvs, + SubmenuIndexBootApp0, SubmenuIndexApp, + SubmenuIndexCustom, SubmenuIndexFlash, }; @@ -20,16 +25,30 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index) // TODO refactor switch(index) { + case SubmenuIndexS3Mode: + // toggle S3 mode + app->selected_flash_options[SelectedFlashS3Mode] = !app->selected_flash_options[SelectedFlashS3Mode]; + view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); + break; case SubmenuIndexBoot: - if(dialog_file_browser_show( - app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { - strncpy( - app->bin_file_path_boot, - furi_string_get_cstr(selected_filepath), - sizeof(app->bin_file_path_boot)); + app->selected_flash_options[SelectedFlashBoot] = !app->selected_flash_options[SelectedFlashBoot]; + if (app->selected_flash_options[SelectedFlashBoot]) { + if(dialog_file_browser_show( + app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { + strncpy( + app->bin_file_path_boot, + furi_string_get_cstr(selected_filepath), + sizeof(app->bin_file_path_boot)); + } } + if (app->bin_file_path_boot[0] == '\0') { + // if user didn't select a file, leave unselected + app->selected_flash_options[SelectedFlashBoot] = false; + } + view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); break; case SubmenuIndexPart: + app->selected_flash_options[SelectedFlashPart] = !app->selected_flash_options[SelectedFlashPart]; if(dialog_file_browser_show( app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { strncpy( @@ -37,8 +56,44 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index) furi_string_get_cstr(selected_filepath), sizeof(app->bin_file_path_part)); } + if (app->bin_file_path_part[0] == '\0') { + // if user didn't select a file, leave unselected + app->selected_flash_options[SelectedFlashPart] = false; + } + view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); + break; + case SubmenuIndexNvs: + app->selected_flash_options[SelectedFlashNvs] = !app->selected_flash_options[SelectedFlashNvs]; + if(dialog_file_browser_show( + app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { + strncpy( + app->bin_file_path_nvs, + furi_string_get_cstr(selected_filepath), + sizeof(app->bin_file_path_nvs)); + } + if (app->bin_file_path_nvs[0] == '\0') { + // if user didn't select a file, leave unselected + app->selected_flash_options[SelectedFlashNvs] = false; + } + view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); + break; + case SubmenuIndexBootApp0: + app->selected_flash_options[SelectedFlashBootApp0] = !app->selected_flash_options[SelectedFlashBootApp0]; + if(dialog_file_browser_show( + app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { + strncpy( + app->bin_file_path_boot_app0, + furi_string_get_cstr(selected_filepath), + sizeof(app->bin_file_path_boot_app0)); + } + if (app->bin_file_path_boot_app0[0] == '\0') { + // if user didn't select a file, leave unselected + app->selected_flash_options[SelectedFlashBootApp0] = false; + } + view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); break; case SubmenuIndexApp: + app->selected_flash_options[SelectedFlashApp] = !app->selected_flash_options[SelectedFlashApp]; if(dialog_file_browser_show( app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { strncpy( @@ -46,10 +101,39 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index) furi_string_get_cstr(selected_filepath), sizeof(app->bin_file_path_app)); } + if (app->bin_file_path_app[0] == '\0') { + // if user didn't select a file, leave unselected + app->selected_flash_options[SelectedFlashApp] = false; + } + view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); + break; + case SubmenuIndexCustom: + app->selected_flash_options[SelectedFlashCustom] = !app->selected_flash_options[SelectedFlashCustom]; + if(dialog_file_browser_show( + app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { + strncpy( + app->bin_file_path_custom, + furi_string_get_cstr(selected_filepath), + sizeof(app->bin_file_path_custom)); + } + if (app->bin_file_path_custom[0] == '\0') { + // if user didn't select a file, leave unselected + app->selected_flash_options[SelectedFlashCustom] = false; + } + view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); break; case SubmenuIndexFlash: - // TODO error checking - scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); + // count how many options are selected + app->num_selected_flash_options = 0; + for (bool* option = &app->selected_flash_options[SelectedFlashBoot]; option < &app->selected_flash_options[NUM_FLASH_OPTIONS]; ++option) { + if (*option) { + ++app->num_selected_flash_options; + } + } + if (app->num_selected_flash_options) { + // only start next scene if at least one option is selected + scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); + } break; } @@ -57,31 +141,83 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index) furi_string_free(predefined_filepath); } -void wifi_marauder_scene_flasher_on_enter(void* context) { - WifiMarauderApp* app = context; - +#define STR_SELECT "[x]" +#define STR_UNSELECT "[ ]" +#define STR_BOOT "Bootloader (" TOSTRING(ESP_ADDR_BOOT) ")" +#define STR_BOOT_S3 "Bootloader (" TOSTRING(ESP_ADDR_BOOT_S3) ")" +#define STR_PART "Part Table (" TOSTRING(ESP_ADDR_PART) ")" +#define STR_NVS "NVS (" TOSTRING(ESP_ADDR_NVS) ")" +#define STR_BOOT_APP0 "boot_app0 (" TOSTRING(ESP_ADDR_BOOT_APP0) ")" +#define STR_APP "Firmware (" TOSTRING(ESP_ADDR_APP) ")" +#define STR_CUSTOM "Custom" +#define STR_FLASH_S3 "[>] FLASH (ESP32-S3)" +#define STR_FLASH "[>] FLASH" +static void _refresh_submenu(WifiMarauderApp* app) { Submenu* submenu = app->submenu; + submenu_reset(app->submenu); + submenu_set_header(submenu, "Browse for files to flash"); submenu_add_item( - submenu, "Bootloader", SubmenuIndexBoot, wifi_marauder_scene_flasher_callback, app); + submenu, app->selected_flash_options[SelectedFlashS3Mode] ? "[x] Using ESP32-S3" : "[ ] Check if using S3", SubmenuIndexS3Mode, wifi_marauder_scene_flasher_callback, app); + const char* strSelectBootloader = STR_UNSELECT " " STR_BOOT; + if (app->selected_flash_options[SelectedFlashS3Mode]) { + if (app->selected_flash_options[SelectedFlashBoot]) { + strSelectBootloader = STR_SELECT " " STR_BOOT_S3; + } else { + strSelectBootloader = STR_UNSELECT " " STR_BOOT_S3; + } + } else { + if (app->selected_flash_options[SelectedFlashBoot]) { + strSelectBootloader = STR_SELECT " " STR_BOOT; + } else { + strSelectBootloader = STR_UNSELECT " " STR_BOOT; + } + } submenu_add_item( - submenu, "Partition Table", SubmenuIndexPart, wifi_marauder_scene_flasher_callback, app); + submenu, strSelectBootloader, SubmenuIndexBoot, wifi_marauder_scene_flasher_callback, app); submenu_add_item( - submenu, "Application", SubmenuIndexApp, wifi_marauder_scene_flasher_callback, app); + submenu, app->selected_flash_options[SelectedFlashPart] ? STR_SELECT " " STR_PART : STR_UNSELECT " " STR_PART, SubmenuIndexPart, wifi_marauder_scene_flasher_callback, app); submenu_add_item( - submenu, "[>] FLASH", SubmenuIndexFlash, wifi_marauder_scene_flasher_callback, app); + submenu, app->selected_flash_options[SelectedFlashNvs] ? STR_SELECT " " STR_NVS : STR_UNSELECT " " STR_NVS, SubmenuIndexNvs, wifi_marauder_scene_flasher_callback, app); + submenu_add_item( + submenu, app->selected_flash_options[SelectedFlashBootApp0] ? STR_SELECT " " STR_BOOT_APP0 : STR_UNSELECT " " STR_BOOT_APP0, SubmenuIndexBootApp0, wifi_marauder_scene_flasher_callback, app); + submenu_add_item( + submenu, app->selected_flash_options[SelectedFlashApp] ? STR_SELECT " " STR_APP : STR_UNSELECT " " STR_APP, SubmenuIndexApp, wifi_marauder_scene_flasher_callback, app); + // TODO: custom addr + //submenu_add_item( + // submenu, app->selected_flash_options[SelectedFlashCustom] ? STR_SELECT " " STR_CUSTOM : STR_UNSELECT " " STR_CUSTOM, SubmenuIndexCustom, wifi_marauder_scene_flasher_callback, app); + submenu_add_item( + submenu, app->selected_flash_options[SelectedFlashS3Mode] ? STR_FLASH_S3 : STR_FLASH, SubmenuIndexFlash, wifi_marauder_scene_flasher_callback, app); submenu_set_selected_item( submenu, scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneFlasher)); view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewSubmenu); } +void wifi_marauder_scene_flasher_on_enter(void* context) { + WifiMarauderApp* app = context; + + memset(app->selected_flash_options, 0, sizeof(app->selected_flash_options)); + app->bin_file_path_boot[0] = '\0'; + app->bin_file_path_part[0] = '\0'; + app->bin_file_path_nvs[0] = '\0'; + app->bin_file_path_boot_app0[0] = '\0'; + app->bin_file_path_app[0] = '\0'; + app->bin_file_path_custom[0] = '\0'; + + _refresh_submenu(app); +} + bool wifi_marauder_scene_flasher_on_event(void* context, SceneManagerEvent event) { - //WifiMarauderApp* app = context; - UNUSED(context); - UNUSED(event); + WifiMarauderApp* app = context; bool consumed = false; + if (event.type == SceneManagerEventTypeCustom) { + if (event.event == WifiMarauderEventRefreshSubmenu) { + _refresh_submenu(app); + consumed = true; + } + } return consumed; } diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c index 06dcd7fd7..97b26fc7f 100644 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c +++ b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c @@ -243,7 +243,6 @@ void wifi_marauder_scene_start_on_enter(void* context) { } bool wifi_marauder_scene_start_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); WifiMarauderApp* app = context; bool consumed = false; diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_app.c b/applications/external/wifi_marauder_companion/wifi_marauder_app.c index 91fcb2372..c27a941ad 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_app.c +++ b/applications/external/wifi_marauder_companion/wifi_marauder_app.c @@ -87,6 +87,7 @@ WifiMarauderApp* wifi_marauder_app_alloc() { app->view_dispatcher, WifiMarauderAppViewSubmenu, submenu_get_view(app->submenu)); app->flash_mode = false; + app->flash_worker_busy = false; scene_manager_next_scene(app->scene_manager, WifiMarauderSceneStart); diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_app.h b/applications/external/wifi_marauder_companion/wifi_marauder_app.h index b6664fdab..187a0aaaa 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_app.h +++ b/applications/external/wifi_marauder_companion/wifi_marauder_app.h @@ -4,7 +4,7 @@ extern "C" { #endif -#define WIFI_MARAUDER_APP_VERSION "v0.5.0" +#define WIFI_MARAUDER_APP_VERSION "v0.5.1" typedef struct WifiMarauderApp WifiMarauderApp; diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h b/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h index cd248648a..a5c4818f0 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h +++ b/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h @@ -48,6 +48,17 @@ typedef enum WifiMarauderUserInputType { WifiMarauderUserInputTypeFileName } WifiMarauderUserInputType; +typedef enum SelectedFlashOptions { + SelectedFlashS3Mode, + SelectedFlashBoot, + SelectedFlashPart, + SelectedFlashNvs, + SelectedFlashBootApp0, + SelectedFlashApp, + SelectedFlashCustom, + NUM_FLASH_OPTIONS +} SelectedFlashOptions; + struct WifiMarauderApp { Gui* gui; ViewDispatcher* view_dispatcher; @@ -115,10 +126,16 @@ struct WifiMarauderApp { char special_case_input_dst_addr[20]; // For flashing - TODO: put into its own struct? + bool selected_flash_options[NUM_FLASH_OPTIONS]; + int num_selected_flash_options; char bin_file_path_boot[100]; char bin_file_path_part[100]; + char bin_file_path_nvs[100]; + char bin_file_path_boot_app0[100]; char bin_file_path_app[100]; + char bin_file_path_custom[100]; FuriThread* flash_worker; + bool flash_worker_busy; bool flash_mode; }; diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_custom_event.h b/applications/external/wifi_marauder_companion/wifi_marauder_custom_event.h index 8f020b754..ff03f31dd 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_custom_event.h +++ b/applications/external/wifi_marauder_companion/wifi_marauder_custom_event.h @@ -10,5 +10,6 @@ typedef enum { WifiMarauderEventStartLogViewer, WifiMarauderEventStartScriptSelect, WifiMarauderEventStartSniffPmkidOptions, - WifiMarauderEventStartFlasher + WifiMarauderEventStartFlasher, + WifiMarauderEventRefreshSubmenu } WifiMarauderCustomEvent; diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_flasher.c b/applications/external/wifi_marauder_companion/wifi_marauder_flasher.c index 8d30c1539..63820be0b 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_flasher.c +++ b/applications/external/wifi_marauder_companion/wifi_marauder_flasher.c @@ -18,6 +18,8 @@ static esp_loader_error_t _flash_file(WifiMarauderApp* app, char* filepath, uint static uint8_t payload[1024]; File* bin_file = storage_file_alloc(app->storage); + char user_msg[256]; + // open file if(!storage_file_open(bin_file, filepath, FSAM_READ, FSOM_OPEN_EXISTING)) { storage_file_close(bin_file); @@ -28,48 +30,34 @@ static esp_loader_error_t _flash_file(WifiMarauderApp* app, char* filepath, uint uint64_t size = storage_file_size(bin_file); - /* - // TODO packet drops with higher BR? - err = esp_loader_change_transmission_rate(230400); - if (err != ESP_LOADER_SUCCESS) { - char err_msg[256]; - snprintf( - err_msg, - sizeof(err_msg), - "Cannot change transmission rate. Error: %u\n", - err); - storage_file_close(bin_file); - storage_file_free(bin_file); - loader_port_debug_print(err_msg); - return; - } - - furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400); - // TODO remember to change BR back! - */ - loader_port_debug_print("Erasing flash...this may take a while\n"); err = esp_loader_flash_start(addr, size, sizeof(payload)); if(err != ESP_LOADER_SUCCESS) { storage_file_close(bin_file); storage_file_free(bin_file); - char err_msg[256]; - snprintf(err_msg, sizeof(err_msg), "Erasing flash failed with error %d\n", err); - loader_port_debug_print(err_msg); + snprintf(user_msg, sizeof(user_msg), "Erasing flash failed with error %d\n", err); + loader_port_debug_print(user_msg); return err; } loader_port_debug_print("Start programming\n"); + uint64_t last_updated = size; while(size > 0) { + if ((last_updated - size) > 50000) { + // inform user every 50k bytes + // TODO: draw a progress bar next update + snprintf(user_msg, sizeof(user_msg), "%llu bytes left.\n", size); + loader_port_debug_print(user_msg); + last_updated = size; + } size_t to_read = MIN(size, sizeof(payload)); uint16_t num_bytes = storage_file_read(bin_file, payload, to_read); err = esp_loader_flash_write(payload, num_bytes); if(err != ESP_LOADER_SUCCESS) { - char err_msg[256]; - snprintf(err_msg, sizeof(err_msg), "Packet could not be written! Error: %u\n", err); + snprintf(user_msg, sizeof(user_msg), "Packet could not be written! Error: %u\n", err); storage_file_close(bin_file); storage_file_free(bin_file); - loader_port_debug_print(err_msg); + loader_port_debug_print(user_msg); return err; } @@ -86,10 +74,49 @@ static esp_loader_error_t _flash_file(WifiMarauderApp* app, char* filepath, uint return ESP_LOADER_SUCCESS; } +typedef struct { + SelectedFlashOptions selected; + const char* description; + char* path; + uint32_t addr; +} FlashItem; + +static void _flash_all_files(WifiMarauderApp* app) { + esp_loader_error_t err; + const int num_steps = app->num_selected_flash_options; + + #define NUM_FLASH_ITEMS 6 + FlashItem items[NUM_FLASH_ITEMS] = { + { SelectedFlashBoot, "bootloader", app->bin_file_path_boot, app->selected_flash_options[SelectedFlashS3Mode] ? ESP_ADDR_BOOT_S3 : ESP_ADDR_BOOT }, + { SelectedFlashPart, "partition table", app->bin_file_path_part, ESP_ADDR_PART }, + { SelectedFlashNvs, "NVS", app->bin_file_path_nvs, ESP_ADDR_NVS }, + { SelectedFlashBootApp0, "boot_app0", app->bin_file_path_boot_app0, ESP_ADDR_BOOT_APP0 }, + { SelectedFlashApp, "firmware", app->bin_file_path_app, ESP_ADDR_APP }, + { SelectedFlashCustom, "custom data", app->bin_file_path_custom, 0x0 }, + /* if you add more entries, update NUM_FLASH_ITEMS above! */ + }; + + char user_msg[256]; + + int current_step = 1; + for (FlashItem* item = &items[0]; item < &items[NUM_FLASH_ITEMS]; ++item) { + if(app->selected_flash_options[item->selected]) { + snprintf(user_msg, sizeof(user_msg), "Flashing %s (%d/%d) to address 0x%lx\n", item->description, current_step++, num_steps, item->addr); + loader_port_debug_print(user_msg); + err = _flash_file(app, item->path, item->addr); + if(err) { + break; + } + } + } +} + static int32_t wifi_marauder_flash_bin(void* context) { WifiMarauderApp* app = (void*)context; esp_loader_error_t err; + app->flash_worker_busy = true; + // alloc global objects flash_rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1); timer = furi_timer_alloc(_timer_callback, FuriTimerTypePeriodic, app); @@ -103,22 +130,36 @@ static int32_t wifi_marauder_flash_bin(void* context) { loader_port_debug_print(err_msg); } + #if 0 // still getting packet drops with this + // higher BR + if(!err) { + loader_port_debug_print("Increasing speed for faster flash\n"); + err = esp_loader_change_transmission_rate(230400); + if (err != ESP_LOADER_SUCCESS) { + char err_msg[256]; + snprintf( + err_msg, + sizeof(err_msg), + "Cannot change transmission rate. Error: %u\n", + err); + loader_port_debug_print(err_msg); + } + furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400); + } + #endif + if(!err) { loader_port_debug_print("Connected\n"); - loader_port_debug_print("Flashing bootloader (1/3)\n"); - err = _flash_file(app, app->bin_file_path_boot, 0x1000); - } - if(!err) { - loader_port_debug_print("Flashing partition table (2/3)\n"); - err = _flash_file(app, app->bin_file_path_part, 0x8000); - } - if(!err) { - loader_port_debug_print("Flashing app (3/3)\n"); - err = _flash_file(app, app->bin_file_path_app, 0x10000); + _flash_all_files(app); + #if 0 + loader_port_debug_print("Restoring transmission rate\n"); + furi_hal_uart_set_br(FuriHalUartIdUSART1, 115200); + #endif loader_port_debug_print("Done flashing. Please reset the board manually.\n"); } // done + app->flash_worker_busy = false; // cleanup furi_stream_buffer_free(flash_rx_stream); diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_flasher.h b/applications/external/wifi_marauder_companion/wifi_marauder_flasher.h index 796e258e5..3688ed09f 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_flasher.h +++ b/applications/external/wifi_marauder_companion/wifi_marauder_flasher.h @@ -5,6 +5,13 @@ #define SERIAL_FLASHER_INTERFACE_UART /* TODO why is application.fam not passing this via cdefines */ #include "esp_loader_io.h" +#define ESP_ADDR_BOOT_S3 0x0 +#define ESP_ADDR_BOOT 0x1000 +#define ESP_ADDR_PART 0x8000 +#define ESP_ADDR_NVS 0x9000 +#define ESP_ADDR_BOOT_APP0 0xE000 +#define ESP_ADDR_APP 0x10000 + void wifi_marauder_flash_start_thread(WifiMarauderApp* app); void wifi_marauder_flash_stop_thread(WifiMarauderApp* app); void wifi_marauder_flash_handle_rx_data_cb(uint8_t* buf, size_t len, void* context); \ No newline at end of file From 9c6d0e7f2101158031f8d49ca74c07a5fb1b1365 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 10 Jul 2023 16:52:58 +0300 Subject: [PATCH 10/14] fbt format --- .../mifare_nested/mifare_nested_worker.c | 4 +- .../scenes/wifi_marauder_scene_flasher.c | 118 ++++++++++++------ .../wifi_marauder_flasher.c | 38 +++--- .../wifi_marauder_flasher.h | 10 +- 4 files changed, 109 insertions(+), 61 deletions(-) diff --git a/applications/external/mifare_nested/mifare_nested_worker.c b/applications/external/mifare_nested/mifare_nested_worker.c index 360b38f4a..60540c74b 100644 --- a/applications/external/mifare_nested/mifare_nested_worker.c +++ b/applications/external/mifare_nested/mifare_nested_worker.c @@ -478,11 +478,11 @@ SaveNoncesResult_t* mifare_nested_worker_write_nonces( for(uint8_t sector = 0; sector < sector_count; sector++) { for(uint8_t key_type = 0; key_type < 2; key_type++) { if(nonces->nonces[sector][key_type][tries]->invalid) { - if (tries == 0) { + if(tries == 0) { result->invalid++; } } else if(nonces->nonces[sector][key_type][tries]->skipped) { - if (tries == 0) { + if(tries == 0) { result->skipped++; } } else if(nonces->nonces[sector][key_type][tries]->collected) { diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_flasher.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_flasher.c index 8fe91bbba..2d6b8ea50 100644 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_flasher.c +++ b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_flasher.c @@ -27,28 +27,31 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index) switch(index) { case SubmenuIndexS3Mode: // toggle S3 mode - app->selected_flash_options[SelectedFlashS3Mode] = !app->selected_flash_options[SelectedFlashS3Mode]; + app->selected_flash_options[SelectedFlashS3Mode] = + !app->selected_flash_options[SelectedFlashS3Mode]; view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); break; case SubmenuIndexBoot: - app->selected_flash_options[SelectedFlashBoot] = !app->selected_flash_options[SelectedFlashBoot]; - if (app->selected_flash_options[SelectedFlashBoot]) { + app->selected_flash_options[SelectedFlashBoot] = + !app->selected_flash_options[SelectedFlashBoot]; + if(app->selected_flash_options[SelectedFlashBoot]) { if(dialog_file_browser_show( - app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { + app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { strncpy( app->bin_file_path_boot, furi_string_get_cstr(selected_filepath), sizeof(app->bin_file_path_boot)); } } - if (app->bin_file_path_boot[0] == '\0') { + if(app->bin_file_path_boot[0] == '\0') { // if user didn't select a file, leave unselected app->selected_flash_options[SelectedFlashBoot] = false; } view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); break; case SubmenuIndexPart: - app->selected_flash_options[SelectedFlashPart] = !app->selected_flash_options[SelectedFlashPart]; + app->selected_flash_options[SelectedFlashPart] = + !app->selected_flash_options[SelectedFlashPart]; if(dialog_file_browser_show( app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { strncpy( @@ -56,14 +59,15 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index) furi_string_get_cstr(selected_filepath), sizeof(app->bin_file_path_part)); } - if (app->bin_file_path_part[0] == '\0') { + if(app->bin_file_path_part[0] == '\0') { // if user didn't select a file, leave unselected app->selected_flash_options[SelectedFlashPart] = false; } view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); break; case SubmenuIndexNvs: - app->selected_flash_options[SelectedFlashNvs] = !app->selected_flash_options[SelectedFlashNvs]; + app->selected_flash_options[SelectedFlashNvs] = + !app->selected_flash_options[SelectedFlashNvs]; if(dialog_file_browser_show( app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { strncpy( @@ -71,14 +75,15 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index) furi_string_get_cstr(selected_filepath), sizeof(app->bin_file_path_nvs)); } - if (app->bin_file_path_nvs[0] == '\0') { + if(app->bin_file_path_nvs[0] == '\0') { // if user didn't select a file, leave unselected app->selected_flash_options[SelectedFlashNvs] = false; } view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); break; case SubmenuIndexBootApp0: - app->selected_flash_options[SelectedFlashBootApp0] = !app->selected_flash_options[SelectedFlashBootApp0]; + app->selected_flash_options[SelectedFlashBootApp0] = + !app->selected_flash_options[SelectedFlashBootApp0]; if(dialog_file_browser_show( app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { strncpy( @@ -86,14 +91,15 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index) furi_string_get_cstr(selected_filepath), sizeof(app->bin_file_path_boot_app0)); } - if (app->bin_file_path_boot_app0[0] == '\0') { + if(app->bin_file_path_boot_app0[0] == '\0') { // if user didn't select a file, leave unselected app->selected_flash_options[SelectedFlashBootApp0] = false; } view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); break; case SubmenuIndexApp: - app->selected_flash_options[SelectedFlashApp] = !app->selected_flash_options[SelectedFlashApp]; + app->selected_flash_options[SelectedFlashApp] = + !app->selected_flash_options[SelectedFlashApp]; if(dialog_file_browser_show( app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { strncpy( @@ -101,14 +107,15 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index) furi_string_get_cstr(selected_filepath), sizeof(app->bin_file_path_app)); } - if (app->bin_file_path_app[0] == '\0') { + if(app->bin_file_path_app[0] == '\0') { // if user didn't select a file, leave unselected app->selected_flash_options[SelectedFlashApp] = false; } view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventRefreshSubmenu); break; case SubmenuIndexCustom: - app->selected_flash_options[SelectedFlashCustom] = !app->selected_flash_options[SelectedFlashCustom]; + app->selected_flash_options[SelectedFlashCustom] = + !app->selected_flash_options[SelectedFlashCustom]; if(dialog_file_browser_show( app->dialogs, selected_filepath, predefined_filepath, &browser_options)) { strncpy( @@ -116,7 +123,7 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index) furi_string_get_cstr(selected_filepath), sizeof(app->bin_file_path_custom)); } - if (app->bin_file_path_custom[0] == '\0') { + if(app->bin_file_path_custom[0] == '\0') { // if user didn't select a file, leave unselected app->selected_flash_options[SelectedFlashCustom] = false; } @@ -125,12 +132,14 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index) case SubmenuIndexFlash: // count how many options are selected app->num_selected_flash_options = 0; - for (bool* option = &app->selected_flash_options[SelectedFlashBoot]; option < &app->selected_flash_options[NUM_FLASH_OPTIONS]; ++option) { - if (*option) { + for(bool* option = &app->selected_flash_options[SelectedFlashBoot]; + option < &app->selected_flash_options[NUM_FLASH_OPTIONS]; + ++option) { + if(*option) { ++app->num_selected_flash_options; } } - if (app->num_selected_flash_options) { + if(app->num_selected_flash_options) { // only start next scene if at least one option is selected scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput); } @@ -141,17 +150,17 @@ static void wifi_marauder_scene_flasher_callback(void* context, uint32_t index) furi_string_free(predefined_filepath); } -#define STR_SELECT "[x]" -#define STR_UNSELECT "[ ]" -#define STR_BOOT "Bootloader (" TOSTRING(ESP_ADDR_BOOT) ")" -#define STR_BOOT_S3 "Bootloader (" TOSTRING(ESP_ADDR_BOOT_S3) ")" -#define STR_PART "Part Table (" TOSTRING(ESP_ADDR_PART) ")" -#define STR_NVS "NVS (" TOSTRING(ESP_ADDR_NVS) ")" -#define STR_BOOT_APP0 "boot_app0 (" TOSTRING(ESP_ADDR_BOOT_APP0) ")" -#define STR_APP "Firmware (" TOSTRING(ESP_ADDR_APP) ")" -#define STR_CUSTOM "Custom" -#define STR_FLASH_S3 "[>] FLASH (ESP32-S3)" -#define STR_FLASH "[>] FLASH" +#define STR_SELECT "[x]" +#define STR_UNSELECT "[ ]" +#define STR_BOOT "Bootloader (" TOSTRING(ESP_ADDR_BOOT) ")" +#define STR_BOOT_S3 "Bootloader (" TOSTRING(ESP_ADDR_BOOT_S3) ")" +#define STR_PART "Part Table (" TOSTRING(ESP_ADDR_PART) ")" +#define STR_NVS "NVS (" TOSTRING(ESP_ADDR_NVS) ")" +#define STR_BOOT_APP0 "boot_app0 (" TOSTRING(ESP_ADDR_BOOT_APP0) ")" +#define STR_APP "Firmware (" TOSTRING(ESP_ADDR_APP) ")" +#define STR_CUSTOM "Custom" +#define STR_FLASH_S3 "[>] FLASH (ESP32-S3)" +#define STR_FLASH "[>] FLASH" static void _refresh_submenu(WifiMarauderApp* app) { Submenu* submenu = app->submenu; @@ -159,16 +168,21 @@ static void _refresh_submenu(WifiMarauderApp* app) { submenu_set_header(submenu, "Browse for files to flash"); submenu_add_item( - submenu, app->selected_flash_options[SelectedFlashS3Mode] ? "[x] Using ESP32-S3" : "[ ] Check if using S3", SubmenuIndexS3Mode, wifi_marauder_scene_flasher_callback, app); + submenu, + app->selected_flash_options[SelectedFlashS3Mode] ? "[x] Using ESP32-S3" : + "[ ] Check if using S3", + SubmenuIndexS3Mode, + wifi_marauder_scene_flasher_callback, + app); const char* strSelectBootloader = STR_UNSELECT " " STR_BOOT; - if (app->selected_flash_options[SelectedFlashS3Mode]) { - if (app->selected_flash_options[SelectedFlashBoot]) { + if(app->selected_flash_options[SelectedFlashS3Mode]) { + if(app->selected_flash_options[SelectedFlashBoot]) { strSelectBootloader = STR_SELECT " " STR_BOOT_S3; } else { strSelectBootloader = STR_UNSELECT " " STR_BOOT_S3; } } else { - if (app->selected_flash_options[SelectedFlashBoot]) { + if(app->selected_flash_options[SelectedFlashBoot]) { strSelectBootloader = STR_SELECT " " STR_BOOT; } else { strSelectBootloader = STR_UNSELECT " " STR_BOOT; @@ -177,18 +191,42 @@ static void _refresh_submenu(WifiMarauderApp* app) { submenu_add_item( submenu, strSelectBootloader, SubmenuIndexBoot, wifi_marauder_scene_flasher_callback, app); submenu_add_item( - submenu, app->selected_flash_options[SelectedFlashPart] ? STR_SELECT " " STR_PART : STR_UNSELECT " " STR_PART, SubmenuIndexPart, wifi_marauder_scene_flasher_callback, app); + submenu, + app->selected_flash_options[SelectedFlashPart] ? STR_SELECT " " STR_PART : + STR_UNSELECT " " STR_PART, + SubmenuIndexPart, + wifi_marauder_scene_flasher_callback, + app); submenu_add_item( - submenu, app->selected_flash_options[SelectedFlashNvs] ? STR_SELECT " " STR_NVS : STR_UNSELECT " " STR_NVS, SubmenuIndexNvs, wifi_marauder_scene_flasher_callback, app); + submenu, + app->selected_flash_options[SelectedFlashNvs] ? STR_SELECT " " STR_NVS : + STR_UNSELECT " " STR_NVS, + SubmenuIndexNvs, + wifi_marauder_scene_flasher_callback, + app); submenu_add_item( - submenu, app->selected_flash_options[SelectedFlashBootApp0] ? STR_SELECT " " STR_BOOT_APP0 : STR_UNSELECT " " STR_BOOT_APP0, SubmenuIndexBootApp0, wifi_marauder_scene_flasher_callback, app); + submenu, + app->selected_flash_options[SelectedFlashBootApp0] ? STR_SELECT " " STR_BOOT_APP0 : + STR_UNSELECT " " STR_BOOT_APP0, + SubmenuIndexBootApp0, + wifi_marauder_scene_flasher_callback, + app); submenu_add_item( - submenu, app->selected_flash_options[SelectedFlashApp] ? STR_SELECT " " STR_APP : STR_UNSELECT " " STR_APP, SubmenuIndexApp, wifi_marauder_scene_flasher_callback, app); + submenu, + app->selected_flash_options[SelectedFlashApp] ? STR_SELECT " " STR_APP : + STR_UNSELECT " " STR_APP, + SubmenuIndexApp, + wifi_marauder_scene_flasher_callback, + app); // TODO: custom addr //submenu_add_item( // submenu, app->selected_flash_options[SelectedFlashCustom] ? STR_SELECT " " STR_CUSTOM : STR_UNSELECT " " STR_CUSTOM, SubmenuIndexCustom, wifi_marauder_scene_flasher_callback, app); submenu_add_item( - submenu, app->selected_flash_options[SelectedFlashS3Mode] ? STR_FLASH_S3 : STR_FLASH, SubmenuIndexFlash, wifi_marauder_scene_flasher_callback, app); + submenu, + app->selected_flash_options[SelectedFlashS3Mode] ? STR_FLASH_S3 : STR_FLASH, + SubmenuIndexFlash, + wifi_marauder_scene_flasher_callback, + app); submenu_set_selected_item( submenu, scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneFlasher)); @@ -212,8 +250,8 @@ void wifi_marauder_scene_flasher_on_enter(void* context) { bool wifi_marauder_scene_flasher_on_event(void* context, SceneManagerEvent event) { WifiMarauderApp* app = context; bool consumed = false; - if (event.type == SceneManagerEventTypeCustom) { - if (event.event == WifiMarauderEventRefreshSubmenu) { + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == WifiMarauderEventRefreshSubmenu) { _refresh_submenu(app); consumed = true; } diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_flasher.c b/applications/external/wifi_marauder_companion/wifi_marauder_flasher.c index 63820be0b..ffc1acb78 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_flasher.c +++ b/applications/external/wifi_marauder_companion/wifi_marauder_flasher.c @@ -43,7 +43,7 @@ static esp_loader_error_t _flash_file(WifiMarauderApp* app, char* filepath, uint loader_port_debug_print("Start programming\n"); uint64_t last_updated = size; while(size > 0) { - if ((last_updated - size) > 50000) { + if((last_updated - size) > 50000) { // inform user every 50k bytes // TODO: draw a progress bar next update snprintf(user_msg, sizeof(user_msg), "%llu bytes left.\n", size); @@ -85,23 +85,33 @@ static void _flash_all_files(WifiMarauderApp* app) { esp_loader_error_t err; const int num_steps = app->num_selected_flash_options; - #define NUM_FLASH_ITEMS 6 +#define NUM_FLASH_ITEMS 6 FlashItem items[NUM_FLASH_ITEMS] = { - { SelectedFlashBoot, "bootloader", app->bin_file_path_boot, app->selected_flash_options[SelectedFlashS3Mode] ? ESP_ADDR_BOOT_S3 : ESP_ADDR_BOOT }, - { SelectedFlashPart, "partition table", app->bin_file_path_part, ESP_ADDR_PART }, - { SelectedFlashNvs, "NVS", app->bin_file_path_nvs, ESP_ADDR_NVS }, - { SelectedFlashBootApp0, "boot_app0", app->bin_file_path_boot_app0, ESP_ADDR_BOOT_APP0 }, - { SelectedFlashApp, "firmware", app->bin_file_path_app, ESP_ADDR_APP }, - { SelectedFlashCustom, "custom data", app->bin_file_path_custom, 0x0 }, + {SelectedFlashBoot, + "bootloader", + app->bin_file_path_boot, + app->selected_flash_options[SelectedFlashS3Mode] ? ESP_ADDR_BOOT_S3 : ESP_ADDR_BOOT}, + {SelectedFlashPart, "partition table", app->bin_file_path_part, ESP_ADDR_PART}, + {SelectedFlashNvs, "NVS", app->bin_file_path_nvs, ESP_ADDR_NVS}, + {SelectedFlashBootApp0, "boot_app0", app->bin_file_path_boot_app0, ESP_ADDR_BOOT_APP0}, + {SelectedFlashApp, "firmware", app->bin_file_path_app, ESP_ADDR_APP}, + {SelectedFlashCustom, "custom data", app->bin_file_path_custom, 0x0}, /* if you add more entries, update NUM_FLASH_ITEMS above! */ }; char user_msg[256]; int current_step = 1; - for (FlashItem* item = &items[0]; item < &items[NUM_FLASH_ITEMS]; ++item) { + for(FlashItem* item = &items[0]; item < &items[NUM_FLASH_ITEMS]; ++item) { if(app->selected_flash_options[item->selected]) { - snprintf(user_msg, sizeof(user_msg), "Flashing %s (%d/%d) to address 0x%lx\n", item->description, current_step++, num_steps, item->addr); + snprintf( + user_msg, + sizeof(user_msg), + "Flashing %s (%d/%d) to address 0x%lx\n", + item->description, + current_step++, + num_steps, + item->addr); loader_port_debug_print(user_msg); err = _flash_file(app, item->path, item->addr); if(err) { @@ -130,7 +140,7 @@ static int32_t wifi_marauder_flash_bin(void* context) { loader_port_debug_print(err_msg); } - #if 0 // still getting packet drops with this +#if 0 // still getting packet drops with this // higher BR if(!err) { loader_port_debug_print("Increasing speed for faster flash\n"); @@ -146,15 +156,15 @@ static int32_t wifi_marauder_flash_bin(void* context) { } furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400); } - #endif +#endif if(!err) { loader_port_debug_print("Connected\n"); _flash_all_files(app); - #if 0 +#if 0 loader_port_debug_print("Restoring transmission rate\n"); furi_hal_uart_set_br(FuriHalUartIdUSART1, 115200); - #endif +#endif loader_port_debug_print("Done flashing. Please reset the board manually.\n"); } diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_flasher.h b/applications/external/wifi_marauder_companion/wifi_marauder_flasher.h index 3688ed09f..d875c2dbe 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_flasher.h +++ b/applications/external/wifi_marauder_companion/wifi_marauder_flasher.h @@ -5,12 +5,12 @@ #define SERIAL_FLASHER_INTERFACE_UART /* TODO why is application.fam not passing this via cdefines */ #include "esp_loader_io.h" -#define ESP_ADDR_BOOT_S3 0x0 -#define ESP_ADDR_BOOT 0x1000 -#define ESP_ADDR_PART 0x8000 -#define ESP_ADDR_NVS 0x9000 +#define ESP_ADDR_BOOT_S3 0x0 +#define ESP_ADDR_BOOT 0x1000 +#define ESP_ADDR_PART 0x8000 +#define ESP_ADDR_NVS 0x9000 #define ESP_ADDR_BOOT_APP0 0xE000 -#define ESP_ADDR_APP 0x10000 +#define ESP_ADDR_APP 0x10000 void wifi_marauder_flash_start_thread(WifiMarauderApp* app); void wifi_marauder_flash_stop_thread(WifiMarauderApp* app); From dab2e6e39c3ace355581471f03215c45cb63d4cb Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 10 Jul 2023 17:10:43 +0300 Subject: [PATCH 11/14] remove debug pack for now, fw should fit in debug --- .vscode/example/tasks.json | 16 ++++++++-------- documentation/HowToBuild.md | 8 ++------ fbt_options.py | 13 ------------- 3 files changed, 10 insertions(+), 27 deletions(-) diff --git a/.vscode/example/tasks.json b/.vscode/example/tasks.json index 16437cb10..28e67d456 100644 --- a/.vscode/example/tasks.json +++ b/.vscode/example/tasks.json @@ -13,7 +13,7 @@ "label": "[Debug] Build", "group": "build", "type": "shell", - "command": "./fbt FIRMWARE_APP_SET=debug_pack" + "command": "./fbt" }, { "label": "[Release] Flash (ST-Link)", @@ -25,7 +25,7 @@ "label": "[Debug] Flash (ST-Link)", "group": "build", "type": "shell", - "command": "./fbt FIRMWARE_APP_SET=debug_pack FORCE=1 flash" + "command": "./fbt FORCE=1 flash" }, { "label": "[Release] Flash (blackmagic)", @@ -37,7 +37,7 @@ "label": "[Debug] Flash (blackmagic)", "group": "build", "type": "shell", - "command": "./fbt FIRMWARE_APP_SET=debug_pack FORCE=1 flash_blackmagic" + "command": "./fbt FORCE=1 flash_blackmagic" }, { "label": "[Release] Flash (JLink)", @@ -49,7 +49,7 @@ "label": "[Debug] Flash (JLink)", "group": "build", "type": "shell", - "command": "./fbt FIRMWARE_APP_SET=debug_pack FORCE=1 jflash" + "command": "./fbt FORCE=1 jflash" }, { "label": "[Release] Build update bundle", @@ -61,7 +61,7 @@ "label": "[Debug] Build update bundle", "group": "build", "type": "shell", - "command": "./fbt FIRMWARE_APP_SET=debug_pack updater_package" + "command": "./fbt updater_package" }, { "label": "[Release] Build updater", @@ -73,13 +73,13 @@ "label": "[Debug] Build updater", "group": "build", "type": "shell", - "command": "./fbt FIRMWARE_APP_SET=debug_pack updater_all" + "command": "./fbt updater_all" }, { "label": "[Debug] Flash (USB, w/o resources)", "group": "build", "type": "shell", - "command": "./fbt FIRMWARE_APP_SET=debug_pack FORCE=1 flash_usb" + "command": "./fbt FORCE=1 flash_usb" }, { "label": "[Release] Flash (USB, w/o resources)", @@ -97,7 +97,7 @@ "label": "[Debug] Flash (USB, with resources)", "group": "build", "type": "shell", - "command": "./fbt FIRMWARE_APP_SET=debug_pack FORCE=1 flash_usb_full" + "command": "./fbt FORCE=1 flash_usb_full" }, { "label": "[Release] Flash (USB, with resources)", diff --git a/documentation/HowToBuild.md b/documentation/HowToBuild.md index 76830063f..ddf759f1b 100644 --- a/documentation/HowToBuild.md +++ b/documentation/HowToBuild.md @@ -31,11 +31,9 @@ Check out `documentation/fbt.md` for details on building and flashing firmware. ### Compile everything for development -Edit this file to enable/disable Main apps that you need in DEBUG mode, flash space doesn't allows us to fit them all in DEBUG currently -- `applications/main/application.fam` ```sh -./fbt FIRMWARE_APP_SET=debug_pack updater_package +./fbt updater_package ``` ### Compile everything for release + get updater package to update from microSD card @@ -55,11 +53,9 @@ Check out `documentation/fbt.md` for details on building and flashing firmware. ### Compile everything for development -Edit this file to enable/disable Main apps that you need in DEBUG mode, flash space doesn't allows us to fit them all in DEBUG currently -- `applications/main/application.fam` ```sh -./fbt.cmd FIRMWARE_APP_SET=debug_pack updater_package +./fbt.cmd updater_package ``` ### Compile everything for release + get updater package to update from microSD card diff --git a/fbt_options.py b/fbt_options.py index 561b818d4..4286e08e8 100644 --- a/fbt_options.py +++ b/fbt_options.py @@ -74,19 +74,6 @@ FIRMWARE_APPS = { "updater_app", "unit_tests", ], - "debug_pack": [ - # Svc - "basic_services", - # Apps - "main_apps_default", - "system_apps", - # Settings - "settings_apps", - # Plugins - # "basic_plugins", - # Debug - # "debug_apps", - ], } FIRMWARE_APP_SET = "default" From 5398fb806ed763a8d69a00ea8998e9225d868f49 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 10 Jul 2023 17:21:49 +0300 Subject: [PATCH 12/14] move last apps into microsd --- applications/main/clock_app/application.fam | 7 +++---- applications/main/clock_app/icon.png | Bin 0 -> 7920 bytes applications/main/subghz_remote/application.fam | 14 ++++---------- applications/main/subghz_remote/icon.png | Bin 0 -> 5000 bytes .../main/subghz_remote/subghz_remote_app_i.h | 3 +++ 5 files changed, 10 insertions(+), 14 deletions(-) create mode 100644 applications/main/clock_app/icon.png create mode 100644 applications/main/subghz_remote/icon.png diff --git a/applications/main/clock_app/application.fam b/applications/main/clock_app/application.fam index 9016973c5..47f152b1d 100644 --- a/applications/main/clock_app/application.fam +++ b/applications/main/clock_app/application.fam @@ -1,12 +1,11 @@ App( appid="clock", name="Clock", - apptype=FlipperAppType.APP, + apptype=FlipperAppType.MENUEXTERNAL, entry_point="clock_app", - cdefines=["APP_CLOCK"], - requires=["gui"], icon="A_Clock_14", stack_size=2 * 1024, order=81, + fap_icon="icon.png", + fap_category="Tools", ) - diff --git a/applications/main/clock_app/icon.png b/applications/main/clock_app/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8a5406e6ce5bf26a43d916c16d14bd43fb0d7cdf GIT binary patch literal 7920 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 Date: Mon, 10 Jul 2023 19:59:25 +0300 Subject: [PATCH 13/14] Fix SubGhz Apps & LF RFID --- .../main/subghz_remote/application.fam | 1 + .../subghz_remote/helpers/txrx/subghz_txrx.c | 571 ++++++++++++++++++ .../subghz_remote/helpers/txrx/subghz_txrx.h | 319 +++++++++- .../helpers/txrx/subghz_txrx_i.h | 29 + firmware/targets/f7/api_symbols.csv | 30 +- .../f7/platform_specific/intrinsic_export.h | 1 + lib/subghz/SConscript | 2 + lib/subghz/blocks/custom_btn.h | 10 +- lib/subghz/subghz_file_encoder_worker.h | 8 + lib/subghz/subghz_protocol_registry.h | 52 ++ 10 files changed, 1017 insertions(+), 6 deletions(-) create mode 100644 applications/main/subghz_remote/helpers/txrx/subghz_txrx.c create mode 100644 applications/main/subghz_remote/helpers/txrx/subghz_txrx_i.h diff --git a/applications/main/subghz_remote/application.fam b/applications/main/subghz_remote/application.fam index f8980c0a7..8e916289b 100644 --- a/applications/main/subghz_remote/application.fam +++ b/applications/main/subghz_remote/application.fam @@ -6,6 +6,7 @@ App( icon="A_SubGHzRemote_14", stack_size=2 * 1024, order=11, + fap_libs=["assets",], fap_icon="icon.png", fap_category="Sub-Ghz", ) diff --git a/applications/main/subghz_remote/helpers/txrx/subghz_txrx.c b/applications/main/subghz_remote/helpers/txrx/subghz_txrx.c new file mode 100644 index 000000000..3275b7288 --- /dev/null +++ b/applications/main/subghz_remote/helpers/txrx/subghz_txrx.c @@ -0,0 +1,571 @@ +#include "subghz_txrx_i.h" +#include +#include + +#define TAG "SubGhz" + +SubGhzTxRx* subghz_txrx_alloc() { + SubGhzTxRx* instance = malloc(sizeof(SubGhzTxRx)); + instance->setting = subghz_setting_alloc(); + subghz_setting_load(instance->setting, EXT_PATH("subghz/assets/setting_user")); + + instance->preset = malloc(sizeof(SubGhzRadioPreset)); + instance->preset->name = furi_string_alloc(); + subghz_txrx_set_preset( + instance, "AM650", subghz_setting_get_default_frequency(instance->setting), NULL, 0); + + instance->txrx_state = SubGhzTxRxStateSleep; + + subghz_txrx_hopper_set_state(instance, SubGhzHopperStateOFF); + subghz_txrx_speaker_set_state(instance, SubGhzSpeakerStateDisable); + subghz_txrx_set_debug_pin_state(instance, false); + + instance->worker = subghz_worker_alloc(); + instance->fff_data = flipper_format_string_alloc(); + + instance->environment = subghz_environment_alloc(); + instance->is_database_loaded = subghz_environment_load_keystore( + instance->environment, EXT_PATH("subghz/assets/keeloq_mfcodes")); + subghz_environment_load_keystore( + instance->environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user")); + subghz_environment_set_came_atomo_rainbow_table_file_name( + instance->environment, EXT_PATH("subghz/assets/came_atomo")); + subghz_environment_set_alutech_at_4n_rainbow_table_file_name( + instance->environment, EXT_PATH("subghz/assets/alutech_at_4n")); + subghz_environment_set_nice_flor_s_rainbow_table_file_name( + instance->environment, EXT_PATH("subghz/assets/nice_flor_s")); + subghz_environment_set_protocol_registry( + instance->environment, (void*)&subghz_protocol_registry); + instance->receiver = subghz_receiver_alloc_init(instance->environment); + + subghz_worker_set_overrun_callback( + instance->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset); + subghz_worker_set_pair_callback( + instance->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode); + subghz_worker_set_context(instance->worker, instance->receiver); + + return instance; +} + +void subghz_txrx_free(SubGhzTxRx* instance) { + furi_assert(instance); + + subghz_worker_free(instance->worker); + subghz_receiver_free(instance->receiver); + subghz_environment_free(instance->environment); + flipper_format_free(instance->fff_data); + furi_string_free(instance->preset->name); + subghz_setting_free(instance->setting); + free(instance->preset); + free(instance); +} + +bool subghz_txrx_is_database_loaded(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->is_database_loaded; +} + +void subghz_txrx_set_preset( + SubGhzTxRx* instance, + const char* preset_name, + uint32_t frequency, + uint8_t* preset_data, + size_t preset_data_size) { + furi_assert(instance); + furi_string_set(instance->preset->name, preset_name); + SubGhzRadioPreset* preset = instance->preset; + preset->frequency = frequency; + preset->data = preset_data; + preset->data_size = preset_data_size; +} + +const char* subghz_txrx_get_preset_name(SubGhzTxRx* instance, const char* preset) { + UNUSED(instance); + const char* preset_name = ""; + if(!strcmp(preset, "FuriHalSubGhzPresetOok270Async")) { + preset_name = "AM270"; + } else if(!strcmp(preset, "FuriHalSubGhzPresetOok650Async")) { + preset_name = "AM650"; + } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev238Async")) { + preset_name = "FM238"; + } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev476Async")) { + preset_name = "FM476"; + } else if(!strcmp(preset, "FuriHalSubGhzPresetCustom")) { + preset_name = "CUSTOM"; + } else { + FURI_LOG_E(TAG, "Unknown preset"); + } + return preset_name; +} + +SubGhzRadioPreset subghz_txrx_get_preset(SubGhzTxRx* instance) { + furi_assert(instance); + return *instance->preset; +} + +void subghz_txrx_get_frequency_and_modulation( + SubGhzTxRx* instance, + FuriString* frequency, + FuriString* modulation, + bool long_name) { + furi_assert(instance); + SubGhzRadioPreset* preset = instance->preset; + if(frequency != NULL) { + furi_string_printf( + frequency, + "%03ld.%02ld", + preset->frequency / 1000000 % 1000, + preset->frequency / 10000 % 100); + } + if(modulation != NULL) { + if(long_name) { + furi_string_printf(modulation, "%s", furi_string_get_cstr(preset->name)); + } else { + furi_string_printf(modulation, "%.2s", furi_string_get_cstr(preset->name)); + } + } +} + +static void subghz_txrx_begin(SubGhzTxRx* instance, uint8_t* preset_data) { + furi_assert(instance); + furi_hal_subghz_reset(); + furi_hal_subghz_idle(); + furi_hal_subghz_load_custom_preset(preset_data); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); + instance->txrx_state = SubGhzTxRxStateIDLE; +} + +static uint32_t subghz_txrx_rx(SubGhzTxRx* instance, uint32_t frequency) { + furi_assert(instance); + if(!furi_hal_subghz_is_frequency_valid(frequency)) { + furi_crash("SubGhz: Incorrect RX frequency."); + } + furi_assert( + instance->txrx_state != SubGhzTxRxStateRx && instance->txrx_state != SubGhzTxRxStateSleep); + + furi_hal_subghz_idle(); + uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_subghz_flush_rx(); + subghz_txrx_speaker_on(instance); + furi_hal_subghz_rx(); + + furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, instance->worker); + subghz_worker_start(instance->worker); + instance->txrx_state = SubGhzTxRxStateRx; + return value; +} + +static void subghz_txrx_idle(SubGhzTxRx* instance) { + furi_assert(instance); + furi_assert(instance->txrx_state != SubGhzTxRxStateSleep); + furi_hal_subghz_idle(); + subghz_txrx_speaker_off(instance); + instance->txrx_state = SubGhzTxRxStateIDLE; +} + +static void subghz_txrx_rx_end(SubGhzTxRx* instance) { + furi_assert(instance); + furi_assert(instance->txrx_state == SubGhzTxRxStateRx); + + if(subghz_worker_is_running(instance->worker)) { + subghz_worker_stop(instance->worker); + furi_hal_subghz_stop_async_rx(); + } + furi_hal_subghz_idle(); + subghz_txrx_speaker_off(instance); + instance->txrx_state = SubGhzTxRxStateIDLE; +} + +void subghz_txrx_sleep(SubGhzTxRx* instance) { + furi_assert(instance); + furi_hal_subghz_sleep(); + instance->txrx_state = SubGhzTxRxStateSleep; +} + +static bool subghz_txrx_tx(SubGhzTxRx* instance, uint32_t frequency) { + furi_assert(instance); + if(!furi_hal_subghz_is_frequency_valid(frequency)) { + furi_crash("SubGhz: Incorrect TX frequency."); + } + furi_assert(instance->txrx_state != SubGhzTxRxStateSleep); + furi_hal_subghz_idle(); + furi_hal_subghz_set_frequency_and_path(frequency); + furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false); + furi_hal_gpio_init( + furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + bool ret = furi_hal_subghz_tx(); + if(ret) { + subghz_txrx_speaker_on(instance); + instance->txrx_state = SubGhzTxRxStateTx; + } + + return ret; +} + +SubGhzTxRxStartTxState subghz_txrx_tx_start(SubGhzTxRx* instance, FlipperFormat* flipper_format) { + furi_assert(instance); + furi_assert(flipper_format); + + subghz_txrx_stop(instance); + + SubGhzTxRxStartTxState ret = SubGhzTxRxStartTxStateErrorParserOthers; + FuriString* temp_str = furi_string_alloc(); + uint32_t repeat = 200; + do { + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + if(!flipper_format_read_string(flipper_format, "Protocol", temp_str)) { + FURI_LOG_E(TAG, "Missing Protocol"); + break; + } + if(!flipper_format_insert_or_update_uint32(flipper_format, "Repeat", &repeat, 1)) { + FURI_LOG_E(TAG, "Unable Repeat"); + break; + } + ret = SubGhzTxRxStartTxStateOk; + + SubGhzRadioPreset* preset = instance->preset; + instance->transmitter = + subghz_transmitter_alloc_init(instance->environment, furi_string_get_cstr(temp_str)); + + if(instance->transmitter) { + if(subghz_transmitter_deserialize(instance->transmitter, flipper_format) == + SubGhzProtocolStatusOk) { + if(strcmp(furi_string_get_cstr(preset->name), "") != 0) { + subghz_txrx_begin( + instance, + subghz_setting_get_preset_data_by_name( + instance->setting, furi_string_get_cstr(preset->name))); + if(preset->frequency) { + if(!subghz_txrx_tx(instance, preset->frequency)) { + FURI_LOG_E(TAG, "Only Rx"); + ret = SubGhzTxRxStartTxStateErrorOnlyRx; + } + } else { + ret = SubGhzTxRxStartTxStateErrorParserOthers; + } + + } else { + FURI_LOG_E( + TAG, "Unknown name preset \" %s \"", furi_string_get_cstr(preset->name)); + ret = SubGhzTxRxStartTxStateErrorParserOthers; + } + + if(ret == SubGhzTxRxStartTxStateOk) { + //Start TX + furi_hal_subghz_start_async_tx( + subghz_transmitter_yield, instance->transmitter); + } + } else { + ret = SubGhzTxRxStartTxStateErrorParserOthers; + } + } else { + ret = SubGhzTxRxStartTxStateErrorParserOthers; + } + if(ret != SubGhzTxRxStartTxStateOk) { + subghz_transmitter_free(instance->transmitter); + if(instance->txrx_state != SubGhzTxRxStateIDLE) { + subghz_txrx_idle(instance); + } + } + + } while(false); + furi_string_free(temp_str); + return ret; +} + +void subghz_txrx_rx_start(SubGhzTxRx* instance) { + furi_assert(instance); + subghz_txrx_stop(instance); + subghz_txrx_begin( + instance, + subghz_setting_get_preset_data_by_name( + subghz_txrx_get_setting(instance), furi_string_get_cstr(instance->preset->name))); + subghz_txrx_rx(instance, instance->preset->frequency); +} + +void subghz_txrx_set_need_save_callback( + SubGhzTxRx* instance, + SubGhzTxRxNeedSaveCallback callback, + void* context) { + furi_assert(instance); + instance->need_save_callback = callback; + instance->need_save_context = context; +} + +static void subghz_txrx_tx_stop(SubGhzTxRx* instance) { + furi_assert(instance); + furi_assert(instance->txrx_state == SubGhzTxRxStateTx); + //Stop TX + furi_hal_subghz_stop_async_tx(); + subghz_transmitter_stop(instance->transmitter); + subghz_transmitter_free(instance->transmitter); + + //if protocol dynamic then we save the last upload + if(instance->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) { + if(instance->need_save_callback) { + instance->need_save_callback(instance->need_save_context); + } + } + subghz_txrx_idle(instance); + subghz_txrx_speaker_off(instance); + //Todo: Show message + // notification_message(notifications, &sequence_reset_red); +} + +FlipperFormat* subghz_txrx_get_fff_data(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->fff_data; +} + +SubGhzSetting* subghz_txrx_get_setting(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->setting; +} + +void subghz_txrx_stop(SubGhzTxRx* instance) { + furi_assert(instance); + + switch(instance->txrx_state) { + case SubGhzTxRxStateTx: + subghz_txrx_tx_stop(instance); + subghz_txrx_speaker_unmute(instance); + break; + case SubGhzTxRxStateRx: + subghz_txrx_rx_end(instance); + subghz_txrx_speaker_mute(instance); + break; + + default: + break; + } +} + +void subghz_txrx_hopper_update(SubGhzTxRx* instance) { + furi_assert(instance); + + switch(instance->hopper_state) { + case SubGhzHopperStateOFF: + case SubGhzHopperStatePause: + return; + case SubGhzHopperStateRSSITimeOut: + if(instance->hopper_timeout != 0) { + instance->hopper_timeout--; + return; + } + break; + default: + break; + } + float rssi = -127.0f; + if(instance->hopper_state != SubGhzHopperStateRSSITimeOut) { + // See RSSI Calculation timings in CC1101 17.3 RSSI + rssi = furi_hal_subghz_get_rssi(); + + // Stay if RSSI is high enough + if(rssi > -90.0f) { + instance->hopper_timeout = 10; + instance->hopper_state = SubGhzHopperStateRSSITimeOut; + return; + } + } else { + instance->hopper_state = SubGhzHopperStateRunning; + } + // Select next frequency + if(instance->hopper_idx_frequency < + subghz_setting_get_hopper_frequency_count(instance->setting) - 1) { + instance->hopper_idx_frequency++; + } else { + instance->hopper_idx_frequency = 0; + } + + if(instance->txrx_state == SubGhzTxRxStateRx) { + subghz_txrx_rx_end(instance); + }; + if(instance->txrx_state == SubGhzTxRxStateIDLE) { + subghz_receiver_reset(instance->receiver); + instance->preset->frequency = + subghz_setting_get_hopper_frequency(instance->setting, instance->hopper_idx_frequency); + subghz_txrx_rx(instance, instance->preset->frequency); + } +} + +SubGhzHopperState subghz_txrx_hopper_get_state(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->hopper_state; +} + +void subghz_txrx_hopper_set_state(SubGhzTxRx* instance, SubGhzHopperState state) { + furi_assert(instance); + instance->hopper_state = state; +} + +void subghz_txrx_hopper_unpause(SubGhzTxRx* instance) { + furi_assert(instance); + if(instance->hopper_state == SubGhzHopperStatePause) { + instance->hopper_state = SubGhzHopperStateRunning; + } +} + +void subghz_txrx_hopper_pause(SubGhzTxRx* instance) { + furi_assert(instance); + if(instance->hopper_state == SubGhzHopperStateRunning) { + instance->hopper_state = SubGhzHopperStatePause; + } +} + +void subghz_txrx_speaker_on(SubGhzTxRx* instance) { + furi_assert(instance); + if(instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(&gpio_ibutton); + } + + if(instance->speaker_state == SubGhzSpeakerStateEnable) { + if(furi_hal_speaker_acquire(30)) { + if(!instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(&gpio_speaker); + } + } else { + instance->speaker_state = SubGhzSpeakerStateDisable; + } + } +} + +void subghz_txrx_speaker_off(SubGhzTxRx* instance) { + furi_assert(instance); + if(instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(NULL); + } + if(instance->speaker_state != SubGhzSpeakerStateDisable) { + if(furi_hal_speaker_is_mine()) { + if(!instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(NULL); + } + furi_hal_speaker_release(); + if(instance->speaker_state == SubGhzSpeakerStateShutdown) + instance->speaker_state = SubGhzSpeakerStateDisable; + } + } +} + +void subghz_txrx_speaker_mute(SubGhzTxRx* instance) { + furi_assert(instance); + if(instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(NULL); + } + if(instance->speaker_state == SubGhzSpeakerStateEnable) { + if(furi_hal_speaker_is_mine()) { + if(!instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(NULL); + } + } + } +} + +void subghz_txrx_speaker_unmute(SubGhzTxRx* instance) { + furi_assert(instance); + if(instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(&gpio_ibutton); + } + if(instance->speaker_state == SubGhzSpeakerStateEnable) { + if(furi_hal_speaker_is_mine()) { + if(!instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(&gpio_speaker); + } + } + } +} + +void subghz_txrx_speaker_set_state(SubGhzTxRx* instance, SubGhzSpeakerState state) { + furi_assert(instance); + instance->speaker_state = state; +} + +SubGhzSpeakerState subghz_txrx_speaker_get_state(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->speaker_state; +} + +bool subghz_txrx_load_decoder_by_name_protocol(SubGhzTxRx* instance, const char* name_protocol) { + furi_assert(instance); + furi_assert(name_protocol); + bool res = false; + instance->decoder_result = + subghz_receiver_search_decoder_base_by_name(instance->receiver, name_protocol); + if(instance->decoder_result) { + res = true; + } + return res; +} + +SubGhzProtocolDecoderBase* subghz_txrx_get_decoder(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->decoder_result; +} + +bool subghz_txrx_protocol_is_serializable(SubGhzTxRx* instance) { + furi_assert(instance); + return ( + (instance->decoder_result->protocol->flag & SubGhzProtocolFlag_Save) == + SubGhzProtocolFlag_Save); +} + +bool subghz_txrx_protocol_is_transmittable(SubGhzTxRx* instance, bool check_type) { + furi_assert(instance); + const SubGhzProtocol* protocol = instance->decoder_result->protocol; + if(check_type) { + return ( + ((protocol->flag & SubGhzProtocolFlag_Send) == SubGhzProtocolFlag_Send) && + protocol->encoder->deserialize && protocol->type == SubGhzProtocolTypeStatic); + } + return ( + ((protocol->flag & SubGhzProtocolFlag_Send) == SubGhzProtocolFlag_Send) && + protocol->encoder->deserialize); +} + +void subghz_txrx_receiver_set_filter(SubGhzTxRx* instance, SubGhzProtocolFlag filter) { + furi_assert(instance); + subghz_receiver_set_filter(instance->receiver, filter); +} + +void subghz_txrx_set_rx_calback( + SubGhzTxRx* instance, + SubGhzReceiverCallback callback, + void* context) { + subghz_receiver_set_rx_callback(instance->receiver, callback, context); +} + +void subghz_txrx_set_raw_file_encoder_worker_callback_end( + SubGhzTxRx* instance, + SubGhzProtocolEncoderRAWCallbackEnd callback, + void* context) { + subghz_protocol_raw_file_encoder_worker_set_callback_end( + (SubGhzProtocolEncoderRAW*)subghz_transmitter_get_protocol_instance(instance->transmitter), + callback, + context); +} + +void subghz_txrx_set_debug_pin_state(SubGhzTxRx* instance, bool state) { + furi_assert(instance); + instance->debug_pin_state = state; +} + +bool subghz_txrx_get_debug_pin_state(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->debug_pin_state; +} + +void subghz_txrx_reset_dynamic_and_custom_btns(SubGhzTxRx* instance) { + furi_assert(instance); + subghz_environment_reset_keeloq(instance->environment); + + subghz_custom_btns_reset(); +} + +SubGhzReceiver* subghz_txrx_get_receiver(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->receiver; +} \ No newline at end of file diff --git a/applications/main/subghz_remote/helpers/txrx/subghz_txrx.h b/applications/main/subghz_remote/helpers/txrx/subghz_txrx.h index 5241f402f..6e7641734 100644 --- a/applications/main/subghz_remote/helpers/txrx/subghz_txrx.h +++ b/applications/main/subghz_remote/helpers/txrx/subghz_txrx.h @@ -1,3 +1,320 @@ #pragma once -#include "../../../subghz/helpers/subghz_txrx.h" \ No newline at end of file +#include +#include +#include +#include +#include + +typedef struct SubGhzTxRx SubGhzTxRx; + +typedef void (*SubGhzTxRxNeedSaveCallback)(void* context); + +typedef enum { + SubGhzTxRxStartTxStateOk, + SubGhzTxRxStartTxStateErrorOnlyRx, + SubGhzTxRxStartTxStateErrorParserOthers, +} SubGhzTxRxStartTxState; + +// Type from subghz_types.h need for txrx working +/** SubGhzTxRx state */ +typedef enum { + SubGhzTxRxStateIDLE, + SubGhzTxRxStateRx, + SubGhzTxRxStateTx, + SubGhzTxRxStateSleep, +} SubGhzTxRxState; + +/** SubGhzHopperState state */ +typedef enum { + SubGhzHopperStateOFF, + SubGhzHopperStateRunning, + SubGhzHopperStatePause, + SubGhzHopperStateRSSITimeOut, +} SubGhzHopperState; + +/** SubGhzSpeakerState state */ +typedef enum { + SubGhzSpeakerStateDisable, + SubGhzSpeakerStateShutdown, + SubGhzSpeakerStateEnable, +} SubGhzSpeakerState; + +/** + * Allocate SubGhzTxRx + * + * @return SubGhzTxRx* pointer to SubGhzTxRx + */ +SubGhzTxRx* subghz_txrx_alloc(); + +/** + * Free SubGhzTxRx + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_free(SubGhzTxRx* instance); + +/** + * Check if the database is loaded + * + * @param instance Pointer to a SubGhzTxRx + * @return bool True if the database is loaded + */ +bool subghz_txrx_is_database_loaded(SubGhzTxRx* instance); + +/** + * Set preset + * + * @param instance Pointer to a SubGhzTxRx + * @param preset_name Name of preset + * @param frequency Frequency in Hz + * @param preset_data Data of preset + * @param preset_data_size Size of preset data + */ +void subghz_txrx_set_preset( + SubGhzTxRx* instance, + const char* preset_name, + uint32_t frequency, + uint8_t* preset_data, + size_t preset_data_size); + +/** + * Get name of preset + * + * @param instance Pointer to a SubGhzTxRx + * @param preset String of preset + * @return const char* Name of preset + */ +const char* subghz_txrx_get_preset_name(SubGhzTxRx* instance, const char* preset); + +/** + * Get of preset + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzRadioPreset Preset + */ +SubGhzRadioPreset subghz_txrx_get_preset(SubGhzTxRx* instance); + +/** + * Get string frequency and modulation + * + * @param instance Pointer to a SubGhzTxRx + * @param frequency Pointer to a string frequency + * @param modulation Pointer to a string modulation + */ +void subghz_txrx_get_frequency_and_modulation( + SubGhzTxRx* instance, + FuriString* frequency, + FuriString* modulation, + bool long_name); + +/** + * Start TX CC1101 + * + * @param instance Pointer to a SubGhzTxRx + * @param flipper_format Pointer to a FlipperFormat + * @return SubGhzTxRxStartTxState + */ +SubGhzTxRxStartTxState subghz_txrx_tx_start(SubGhzTxRx* instance, FlipperFormat* flipper_format); + +/** + * Start RX CC1101 + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_rx_start(SubGhzTxRx* instance); + +/** + * Stop TX/RX CC1101 + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_stop(SubGhzTxRx* instance); + +/** + * Set sleep mode CC1101 + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_sleep(SubGhzTxRx* instance); + +/** + * Update frequency CC1101 in automatic mode (hopper) + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_hopper_update(SubGhzTxRx* instance); + +/** + * Get state hopper + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzHopperState + */ +SubGhzHopperState subghz_txrx_hopper_get_state(SubGhzTxRx* instance); + +/** + * Set state hopper + * + * @param instance Pointer to a SubGhzTxRx + * @param state State hopper + */ +void subghz_txrx_hopper_set_state(SubGhzTxRx* instance, SubGhzHopperState state); + +/** + * Unpause hopper + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_hopper_unpause(SubGhzTxRx* instance); + +/** + * Set pause hopper + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_hopper_pause(SubGhzTxRx* instance); + +/** + * Speaker on + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_speaker_on(SubGhzTxRx* instance); + +/** + * Speaker off + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_speaker_off(SubGhzTxRx* instance); + +/** + * Speaker mute + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_speaker_mute(SubGhzTxRx* instance); + +/** + * Speaker unmute + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_speaker_unmute(SubGhzTxRx* instance); + +/** + * Set state speaker + * + * @param instance Pointer to a SubGhzTxRx + * @param state State speaker + */ +void subghz_txrx_speaker_set_state(SubGhzTxRx* instance, SubGhzSpeakerState state); + +/** + * Get state speaker + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzSpeakerState + */ +SubGhzSpeakerState subghz_txrx_speaker_get_state(SubGhzTxRx* instance); + +/** + * load decoder by name protocol + * + * @param instance Pointer to a SubGhzTxRx + * @param name_protocol Name protocol + * @return bool True if the decoder is loaded + */ +bool subghz_txrx_load_decoder_by_name_protocol(SubGhzTxRx* instance, const char* name_protocol); + +/** + * Get decoder + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzProtocolDecoderBase* Pointer to a SubGhzProtocolDecoderBase + */ +SubGhzProtocolDecoderBase* subghz_txrx_get_decoder(SubGhzTxRx* instance); + +/** + * Set callback for save data + * + * @param instance Pointer to a SubGhzTxRx + * @param callback Callback for save data + * @param context Context for callback + */ +void subghz_txrx_set_need_save_callback( + SubGhzTxRx* instance, + SubGhzTxRxNeedSaveCallback callback, + void* context); + +/** + * Get pointer to a load data key + * + * @param instance Pointer to a SubGhzTxRx + * @return FlipperFormat* + */ +FlipperFormat* subghz_txrx_get_fff_data(SubGhzTxRx* instance); + +/** + * Get pointer to a SugGhzSetting + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzSetting* + */ +SubGhzSetting* subghz_txrx_get_setting(SubGhzTxRx* instance); + +/** + * Is it possible to save this protocol + * + * @param instance Pointer to a SubGhzTxRx + * @return bool True if it is possible to save this protocol + */ +bool subghz_txrx_protocol_is_serializable(SubGhzTxRx* instance); + +/** + * Is it possible to send this protocol + * + * @param instance Pointer to a SubGhzTxRx + * @return bool True if it is possible to send this protocol + */ +bool subghz_txrx_protocol_is_transmittable(SubGhzTxRx* instance, bool check_type); + +/** + * Set filter, what types of decoder to use + * + * @param instance Pointer to a SubGhzTxRx + * @param filter Filter + */ +void subghz_txrx_receiver_set_filter(SubGhzTxRx* instance, SubGhzProtocolFlag filter); + +/** + * Set callback for receive data + * + * @param instance Pointer to a SubGhzTxRx + * @param callback Callback for receive data + * @param context Context for callback + */ +void subghz_txrx_set_rx_calback( + SubGhzTxRx* instance, + SubGhzReceiverCallback callback, + void* context); + +/** + * Set callback for Raw decoder, end of data transfer + * + * @param instance Pointer to a SubGhzTxRx + * @param callback Callback for Raw decoder, end of data transfer + * @param context Context for callback + */ +void subghz_txrx_set_raw_file_encoder_worker_callback_end( + SubGhzTxRx* instance, + SubGhzProtocolEncoderRAWCallbackEnd callback, + void* context); + +void subghz_txrx_set_debug_pin_state(SubGhzTxRx* instance, bool state); +bool subghz_txrx_get_debug_pin_state(SubGhzTxRx* instance); + +void subghz_txrx_reset_dynamic_and_custom_btns(SubGhzTxRx* instance); + +SubGhzReceiver* subghz_txrx_get_receiver(SubGhzTxRx* instance); // TODO use only in DecodeRaw diff --git a/applications/main/subghz_remote/helpers/txrx/subghz_txrx_i.h b/applications/main/subghz_remote/helpers/txrx/subghz_txrx_i.h new file mode 100644 index 000000000..680d27158 --- /dev/null +++ b/applications/main/subghz_remote/helpers/txrx/subghz_txrx_i.h @@ -0,0 +1,29 @@ + +#pragma once +#include "subghz_txrx.h" + +struct SubGhzTxRx { + SubGhzWorker* worker; + + SubGhzEnvironment* environment; + SubGhzReceiver* receiver; + SubGhzTransmitter* transmitter; + SubGhzProtocolDecoderBase* decoder_result; + FlipperFormat* fff_data; + + SubGhzRadioPreset* preset; + SubGhzSetting* setting; + + uint8_t hopper_timeout; + uint8_t hopper_idx_frequency; + bool is_database_loaded; + SubGhzHopperState hopper_state; + + SubGhzTxRxState txrx_state; + SubGhzSpeakerState speaker_state; + + SubGhzTxRxNeedSaveCallback need_save_callback; + void* need_save_context; + + bool debug_pin_state; +}; \ No newline at end of file diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index c18f3bf24..a20ac6fbb 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -188,6 +188,7 @@ Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_usart.h,, Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_utils.h,, Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_wwdg.h,, Header,+,lib/subghz/blocks/const.h,, +Header,+,lib/subghz/blocks/custom_btn.h,, Header,+,lib/subghz/blocks/decoder.h,, Header,+,lib/subghz/blocks/encoder.h,, Header,+,lib/subghz/blocks/generic.h,, @@ -196,6 +197,7 @@ Header,+,lib/subghz/environment.h,, Header,+,lib/subghz/protocols/raw.h,, Header,+,lib/subghz/receiver.h,, Header,+,lib/subghz/registry.h,, +Header,+,lib/subghz/subghz_file_encoder_worker.h,, Header,+,lib/subghz/subghz_protocol_registry.h,, Header,+,lib/subghz/subghz_setting.h,, Header,+,lib/subghz/subghz_tx_rx_worker.h,, @@ -323,6 +325,7 @@ Function,-,LL_mDelay,void,uint32_t Function,-,SystemCoreClockUpdate,void, Function,-,SystemInit,void, Function,-,_Exit,void,int +Function,+,__aeabi_uldivmod,void*,"uint64_t, uint64_t" Function,-,__assert,void,"const char*, int, const char*" Function,+,__assert_func,void,"const char*, int, const char*, const char*" Function,+,__clear_cache,void,"void*, void*" @@ -1443,9 +1446,9 @@ Function,+,furi_hal_subghz_set_async_mirror_pin,void,const GpioPin* Function,+,furi_hal_subghz_set_external_power_disable,void,_Bool Function,+,furi_hal_subghz_set_frequency,uint32_t,uint32_t Function,+,furi_hal_subghz_set_frequency_and_path,uint32_t,uint32_t -Function,-,furi_hal_subghz_set_rolling_counter_mult,void,uint8_t -Function,+,furi_hal_subghz_shutdown,void, Function,+,furi_hal_subghz_set_path,void,FuriHalSubGhzPath +Function,+,furi_hal_subghz_set_rolling_counter_mult,void,uint8_t +Function,+,furi_hal_subghz_shutdown,void, Function,+,furi_hal_subghz_sleep,void, Function,+,furi_hal_subghz_start_async_rx,void,"FuriHalSubGhzCaptureCallback, void*" Function,+,furi_hal_subghz_start_async_tx,_Bool,"FuriHalSubGhzAsyncTxCallback, void*" @@ -2757,6 +2760,11 @@ Function,+,subghz_block_generic_deserialize,SubGhzProtocolStatus,"SubGhzBlockGen Function,+,subghz_block_generic_deserialize_check_count_bit,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*, uint16_t" Function,+,subghz_block_generic_get_preset_name,void,"const char*, FuriString*" Function,+,subghz_block_generic_serialize,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*, SubGhzRadioPreset*" +Function,+,subghz_custom_btn_get,uint8_t, +Function,+,subghz_custom_btn_get_original,uint8_t, +Function,+,subghz_custom_btn_is_allowed,_Bool, +Function,+,subghz_custom_btn_set,_Bool,uint8_t +Function,+,subghz_custom_btns_reset,void, Function,+,subghz_environment_alloc,SubGhzEnvironment*, Function,+,subghz_environment_free,void,SubGhzEnvironment* Function,+,subghz_environment_get_alutech_at_4n_rainbow_table_file_name,const char*,SubGhzEnvironment* @@ -2771,6 +2779,14 @@ Function,+,subghz_environment_set_alutech_at_4n_rainbow_table_file_name,void,"Su Function,+,subghz_environment_set_came_atomo_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*" Function,+,subghz_environment_set_nice_flor_s_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*" Function,+,subghz_environment_set_protocol_registry,void,"SubGhzEnvironment*, const SubGhzProtocolRegistry*" +Function,+,subghz_file_encoder_worker_alloc,SubGhzFileEncoderWorker*, +Function,+,subghz_file_encoder_worker_callback_end,void,"SubGhzFileEncoderWorker*, SubGhzFileEncoderWorkerCallbackEnd, void*" +Function,+,subghz_file_encoder_worker_free,void,SubGhzFileEncoderWorker* +Function,+,subghz_file_encoder_worker_get_level_duration,LevelDuration,void* +Function,+,subghz_file_encoder_worker_get_text_progress,void,"SubGhzFileEncoderWorker*, FuriString*" +Function,+,subghz_file_encoder_worker_is_running,_Bool,SubGhzFileEncoderWorker* +Function,+,subghz_file_encoder_worker_start,_Bool,"SubGhzFileEncoderWorker*, const char*" +Function,+,subghz_file_encoder_worker_stop,void,SubGhzFileEncoderWorker* Function,-,subghz_keystore_alloc,SubGhzKeystore*, Function,-,subghz_keystore_free,void,SubGhzKeystore* Function,-,subghz_keystore_get_data,SubGhzKeyArray_t*,SubGhzKeystore* @@ -2779,6 +2795,7 @@ Function,-,subghz_keystore_raw_encrypted_save,_Bool,"const char*, const char*, u Function,-,subghz_keystore_raw_get_data,_Bool,"const char*, size_t, uint8_t*, size_t" Function,-,subghz_keystore_reset_kl,void,SubGhzKeystore* Function,-,subghz_keystore_save,_Bool,"SubGhzKeystore*, const char*, uint8_t*" +Function,+,subghz_protocol_alutech_at_4n_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, SubGhzRadioPreset*" Function,+,subghz_protocol_blocks_add_bit,void,"SubGhzBlockDecoder*, uint8_t" Function,+,subghz_protocol_blocks_add_bytes,uint8_t,"const uint8_t[], size_t" Function,+,subghz_protocol_blocks_add_to_128_bit,void,"SubGhzBlockDecoder*, uint8_t, uint64_t*" @@ -2800,6 +2817,7 @@ Function,+,subghz_protocol_blocks_parity_bytes,uint8_t,"const uint8_t[], size_t" Function,+,subghz_protocol_blocks_reverse_key,uint64_t,"uint64_t, uint8_t" Function,+,subghz_protocol_blocks_set_bit_array,void,"_Bool, uint8_t[], size_t, size_t" Function,+,subghz_protocol_blocks_xor_bytes,uint8_t,"const uint8_t[], size_t" +Function,+,subghz_protocol_came_atomo_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint16_t, SubGhzRadioPreset*" Function,+,subghz_protocol_decoder_base_deserialize,SubGhzProtocolStatus,"SubGhzProtocolDecoderBase*, FlipperFormat*" Function,+,subghz_protocol_decoder_base_get_hash_data,uint8_t,SubGhzProtocolDecoderBase* Function,+,subghz_protocol_decoder_base_get_string,_Bool,"SubGhzProtocolDecoderBase*, FuriString*" @@ -2817,7 +2835,10 @@ Function,+,subghz_protocol_encoder_raw_deserialize,SubGhzProtocolStatus,"void*, Function,+,subghz_protocol_encoder_raw_free,void,void* Function,+,subghz_protocol_encoder_raw_stop,void,void* Function,+,subghz_protocol_encoder_raw_yield,LevelDuration,void* +Function,+,subghz_protocol_faac_slh_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint32_t, uint32_t, const char*, SubGhzRadioPreset*" +Function,+,subghz_protocol_keeloq_bft_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, uint32_t, const char*, SubGhzRadioPreset*" Function,+,subghz_protocol_keeloq_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, const char*, SubGhzRadioPreset*" +Function,+,subghz_protocol_nice_flor_s_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, SubGhzRadioPreset*, _Bool" Function,+,subghz_protocol_raw_file_encoder_worker_set_callback_end,void,"SubGhzProtocolEncoderRAW*, SubGhzProtocolEncoderRAWCallbackEnd, void*" Function,+,subghz_protocol_raw_gen_fff_data,void,"FlipperFormat*, const char*" Function,+,subghz_protocol_raw_get_sample_write,size_t,SubGhzProtocolDecoderRAW* @@ -2829,6 +2850,7 @@ Function,+,subghz_protocol_registry_get_by_index,const SubGhzProtocol*,"const Su Function,+,subghz_protocol_registry_get_by_name,const SubGhzProtocol*,"const SubGhzProtocolRegistry*, const char*" Function,+,subghz_protocol_secplus_v1_check_fixed,_Bool,uint32_t Function,+,subghz_protocol_secplus_v2_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint32_t, SubGhzRadioPreset*" +Function,+,subghz_protocol_somfy_telis_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, SubGhzRadioPreset*" Function,+,subghz_receiver_alloc_init,SubGhzReceiver*,SubGhzEnvironment* Function,+,subghz_receiver_decode,void,"SubGhzReceiver*, _Bool, uint32_t" Function,+,subghz_receiver_free,void,SubGhzReceiver* @@ -2837,7 +2859,7 @@ Function,+,subghz_receiver_search_decoder_base_by_name,SubGhzProtocolDecoderBase Function,+,subghz_receiver_set_filter,void,"SubGhzReceiver*, SubGhzProtocolFlag" Function,+,subghz_receiver_set_rx_callback,void,"SubGhzReceiver*, SubGhzReceiverCallback, void*" Function,+,subghz_setting_alloc,SubGhzSetting*, -Function,-,subghz_setting_customs_presets_to_log,uint8_t,SubGhzSetting* +Function,+,subghz_setting_customs_presets_to_log,uint8_t,SubGhzSetting* Function,+,subghz_setting_delete_custom_preset,_Bool,"SubGhzSetting*, const char*" Function,+,subghz_setting_free,void,SubGhzSetting* Function,+,subghz_setting_get_default_frequency,uint32_t,SubGhzSetting* @@ -2890,7 +2912,7 @@ Function,+,submenu_set_header,void,"Submenu*, const char*" Function,+,submenu_set_selected_item,void,"Submenu*, uint32_t" Function,-,system,int,const char* Function,+,t5577_write,void,LFRFIDT5577* -Function,-,t5577_write_with_pass,void,"LFRFIDT5577*, uint32_t" +Function,+,t5577_write_with_pass,void,"LFRFIDT5577*, uint32_t" Function,-,tan,double,double Function,-,tanf,float,float Function,-,tanh,double,double diff --git a/firmware/targets/f7/platform_specific/intrinsic_export.h b/firmware/targets/f7/platform_specific/intrinsic_export.h index c0d76fb89..9180ae11d 100644 --- a/firmware/targets/f7/platform_specific/intrinsic_export.h +++ b/firmware/targets/f7/platform_specific/intrinsic_export.h @@ -6,6 +6,7 @@ extern "C" { #endif void __clear_cache(void*, void*); +void* __aeabi_uldivmod(uint64_t, uint64_t); #ifdef __cplusplus } diff --git a/lib/subghz/SConscript b/lib/subghz/SConscript index 3a0325b71..58afc76a8 100644 --- a/lib/subghz/SConscript +++ b/lib/subghz/SConscript @@ -10,6 +10,7 @@ env.Append( File("registry.h"), File("subghz_worker.h"), File("subghz_tx_rx_worker.h"), + File("subghz_file_encoder_worker.h"), File("transmitter.h"), File("protocols/raw.h"), File("blocks/const.h"), @@ -17,6 +18,7 @@ env.Append( File("blocks/encoder.h"), File("blocks/generic.h"), File("blocks/math.h"), + File("blocks/custom_btn.h"), File("subghz_setting.h"), File("subghz_protocol_registry.h"), ], diff --git a/lib/subghz/blocks/custom_btn.h b/lib/subghz/blocks/custom_btn.h index e06457ccd..45cd839d4 100644 --- a/lib/subghz/blocks/custom_btn.h +++ b/lib/subghz/blocks/custom_btn.h @@ -4,6 +4,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + // Default btn ID #define SUBGHZ_CUSTOM_BTN_OK (0U) #define SUBGHZ_CUSTOM_BTN_UP (1U) @@ -19,4 +23,8 @@ uint8_t subghz_custom_btn_get_original(); void subghz_custom_btns_reset(); -bool subghz_custom_btn_is_allowed(); \ No newline at end of file +bool subghz_custom_btn_is_allowed(); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/subghz/subghz_file_encoder_worker.h b/lib/subghz/subghz_file_encoder_worker.h index 19a46f1e6..f90875c98 100644 --- a/lib/subghz/subghz_file_encoder_worker.h +++ b/lib/subghz/subghz_file_encoder_worker.h @@ -2,6 +2,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + typedef void (*SubGhzFileEncoderWorkerCallbackEnd)(void* context); typedef struct SubGhzFileEncoderWorker SubGhzFileEncoderWorker; @@ -63,3 +67,7 @@ void subghz_file_encoder_worker_stop(SubGhzFileEncoderWorker* instance); * @return bool - true if running */ bool subghz_file_encoder_worker_is_running(SubGhzFileEncoderWorker* instance); + +#ifdef __cplusplus +} +#endif diff --git a/lib/subghz/subghz_protocol_registry.h b/lib/subghz/subghz_protocol_registry.h index 8e80071b5..e5cf75cda 100644 --- a/lib/subghz/subghz_protocol_registry.h +++ b/lib/subghz/subghz_protocol_registry.h @@ -27,12 +27,64 @@ bool subghz_protocol_keeloq_create_data( const char* manufacture_name, SubGhzRadioPreset* preset); +bool subghz_protocol_keeloq_bft_create_data( + void* context, + FlipperFormat* flipper_format, + uint32_t serial, + uint8_t btn, + uint16_t cnt, + uint32_t seed, + const char* manufacture_name, + SubGhzRadioPreset* preset); + void subghz_protocol_decoder_bin_raw_data_input_rssi( SubGhzProtocolDecoderBinRAW* instance, float rssi); bool subghz_protocol_secplus_v1_check_fixed(uint32_t fixed); +bool subghz_protocol_faac_slh_create_data( + void* context, + FlipperFormat* flipper_format, + uint32_t serial, + uint8_t btn, + uint32_t cnt, + uint32_t seed, + const char* manufacture_name, + SubGhzRadioPreset* preset); + +bool subghz_protocol_came_atomo_create_data( + void* context, + FlipperFormat* flipper_format, + uint32_t serial, + uint16_t cnt, + SubGhzRadioPreset* preset); + +bool subghz_protocol_somfy_telis_create_data( + void* context, + FlipperFormat* flipper_format, + uint32_t serial, + uint8_t btn, + uint16_t cnt, + SubGhzRadioPreset* preset); + +bool subghz_protocol_nice_flor_s_create_data( + void* context, + FlipperFormat* flipper_format, + uint32_t serial, + uint8_t btn, + uint16_t cnt, + SubGhzRadioPreset* preset, + bool nice_one); + +bool subghz_protocol_alutech_at_4n_create_data( + void* context, + FlipperFormat* flipper_format, + uint32_t serial, + uint8_t btn, + uint16_t cnt, + SubGhzRadioPreset* preset); + #ifdef __cplusplus } #endif From 5897b8278b6f10fe2100088d43a1a3bf018f631e Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 10 Jul 2023 22:46:57 +0300 Subject: [PATCH 14/14] api --- firmware/targets/f7/api_symbols.csv | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 7924d1052..bfadb79a8 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -2731,6 +2731,11 @@ Function,+,subghz_block_generic_deserialize,SubGhzProtocolStatus,"SubGhzBlockGen Function,+,subghz_block_generic_deserialize_check_count_bit,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*, uint16_t" Function,+,subghz_block_generic_get_preset_name,void,"const char*, FuriString*" Function,+,subghz_block_generic_serialize,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*, SubGhzRadioPreset*" +Function,+,subghz_custom_btn_get,uint8_t, +Function,+,subghz_custom_btn_get_original,uint8_t, +Function,+,subghz_custom_btn_is_allowed,_Bool, +Function,+,subghz_custom_btn_set,_Bool,uint8_t +Function,+,subghz_custom_btns_reset,void, Function,+,subghz_devices_begin,_Bool,const SubGhzDevice* Function,+,subghz_devices_deinit,void, Function,+,subghz_devices_end,void,const SubGhzDevice* @@ -2761,11 +2766,6 @@ Function,+,subghz_devices_start_async_tx,_Bool,"const SubGhzDevice*, void*, void Function,+,subghz_devices_stop_async_rx,void,const SubGhzDevice* Function,+,subghz_devices_stop_async_tx,void,const SubGhzDevice* Function,+,subghz_devices_write_packet,void,"const SubGhzDevice*, const uint8_t*, uint8_t" -Function,+,subghz_custom_btn_get,uint8_t, -Function,+,subghz_custom_btn_get_original,uint8_t, -Function,+,subghz_custom_btn_is_allowed,_Bool, -Function,+,subghz_custom_btn_set,_Bool,uint8_t -Function,+,subghz_custom_btns_reset,void, Function,+,subghz_environment_alloc,SubGhzEnvironment*, Function,+,subghz_environment_free,void,SubGhzEnvironment* Function,+,subghz_environment_get_alutech_at_4n_rainbow_table_file_name,const char*,SubGhzEnvironment* @@ -2786,7 +2786,7 @@ Function,+,subghz_file_encoder_worker_free,void,SubGhzFileEncoderWorker* Function,+,subghz_file_encoder_worker_get_level_duration,LevelDuration,void* Function,+,subghz_file_encoder_worker_get_text_progress,void,"SubGhzFileEncoderWorker*, FuriString*" Function,+,subghz_file_encoder_worker_is_running,_Bool,SubGhzFileEncoderWorker* -Function,+,subghz_file_encoder_worker_start,_Bool,"SubGhzFileEncoderWorker*, const char*" +Function,+,subghz_file_encoder_worker_start,_Bool,"SubGhzFileEncoderWorker*, const char*, const char*" Function,+,subghz_file_encoder_worker_stop,void,SubGhzFileEncoderWorker* Function,-,subghz_keystore_alloc,SubGhzKeystore*, Function,-,subghz_keystore_free,void,SubGhzKeystore*