From 39f0566283624a3d4642c9d876cece8e8ab65645 Mon Sep 17 00:00:00 2001 From: Stefan Helmert Date: Sat, 4 Jan 2014 02:34:53 +0100 Subject: [PATCH] first commit: event device reading, heng long protocl conversion with CRC --- UDPclient.cbp | 42 ++++++++ UDPclient.depend | 21 ++++ UDPclient.layout | 9 ++ bin/Debug/UDPclient | Bin 0 -> 16199 bytes main.c | 248 ++++++++++++++++++++++++++++++++++++++++++++ obj/Debug/main.o | Bin 0 -> 10240 bytes 6 files changed, 320 insertions(+) create mode 100644 UDPclient.cbp create mode 100644 UDPclient.depend create mode 100644 UDPclient.layout create mode 100755 bin/Debug/UDPclient create mode 100644 main.c create mode 100644 obj/Debug/main.o diff --git a/UDPclient.cbp b/UDPclient.cbp new file mode 100644 index 0000000..7d087c6 --- /dev/null +++ b/UDPclient.cbp @@ -0,0 +1,42 @@ + + + + + + diff --git a/UDPclient.depend b/UDPclient.depend new file mode 100644 index 0000000..ec8f039 --- /dev/null +++ b/UDPclient.depend @@ -0,0 +1,21 @@ +# depslib dependency file v1.0 +1388607752 source:/home/stefan/Proj/UDPclient/main.c + + + + + + + + + + + + + + + + + + + diff --git a/UDPclient.layout b/UDPclient.layout new file mode 100644 index 0000000..dfbb5ac --- /dev/null +++ b/UDPclient.layout @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/bin/Debug/UDPclient b/bin/Debug/UDPclient new file mode 100755 index 0000000000000000000000000000000000000000..1e1513d89ab3f48a9266b069b8e7e9c480f82d69 GIT binary patch literal 16199 zcmeG@eRNdSo%hYl$K->|W5P#7EDsr4sxl#nG)mP0GCHw?Ac92;oeVQC$>3xrosR$t z0*zS4f!)N`ZM)rFv$e-%&uW*mYlS1W1hJxL-5z?5M{!H{WIbpnB_8Rv>!ym%{(kq~ z-^_cDq#JtO_`laQV0dp}+_(aR>oHr_@scR>0LO<-HCcP)Pd_u(|wRhEzg?m|r>hBr4!{ zrVElFV>)M`9hUXtRh$Ia!4ZN(vK&VwBs(P0uIY1J9bgAX2#&~t5v2NI-S9dn{T+1p zfI`}bK$fZuQ5Vy?cQR4L=W3h;=;H{%pkOnCWOoZ`k@L!ySpPYoBn}ok>68;Y+;WKDA z=}a_o?X}oema|Z(t0$QVr8D7FCKO`5neLPkj)o#|&loIpM_*{Y(G^Q)jMVCQIGr}q z=%7c~0@f9Ygwja0AYWP|y@a8kl0RcdEK?%xkHzC9BAm&jLa_vhlf6cQMdHb{fxaRl zkKSx1&3aR@M5dF)l95cDWz%uP=!Jr#k}P;nIF?|y2isSz4lVUA_1*xLht{j|7L1s{ zkyhoO0IBDI}CX1rX(!gxpb*kI(DieC!w0N08B^cOc+>1^WRd z-Ncte0T(SY@v&b~T4Lgx$D>vgANwOEpNUUn1j+&?KK55i>r8y?zmzta_}I58b(r`# zUQp^b@o_An)NA6?*nqMfCcb&h3G|OS3kx7(g@3}^dr-GP|4YtOBr|8bdj% z1Ksjod+wKC59Hns^q;@DZbSR&;Uz8~3!FYV)PUght#v+D=mNz*3=Ckb0{O~)vvn5O zKb&zC&+t%ndR_A#27fS^&tn?{xp(eH#l1IQ1U;7h3Rt`k*l{P!yn%fe7=n`@se%3r zO5nz`X-}tXUK@j;4=aIO<g|^+p9ECF?7p_;RA*;7%Rv9l z&Y6%8=9_UJ!%|?`oLf$4kWq02vjXaa!Zm;m*GXOP!X8|^$%yrZ^r?Y=t z%l-pWdEearaV7i21!dsGPch%8KQ0y_gXb~ppAGmcd{oAM5aj%qKn6K?0&xPXP&fw| z)<3sS`gIz*x7;G@3gj3|ew!rg&=W8>f~ z_tVW#@IdY-*pE*8Ujr7jjxijGPx}ivXq@(+7t9d>&Ixc|=r4FQ50+_^|aAKKZCvgw{Og*vs(j^BZ5w zy-{kDX%Jzn7{Jix*Du>#s}IoFooGLm0&KEJV$ z&yEH2k9UJOnA_m-0p2U|KwB>8X>H53d6wjMc^2h&zXU+f?>+;dDZl$H04=}!6#&ls z?$>i)_N>gk<!ik8 zPg!k-RqZUP@wQf0YqYAJAvNCm+VX48wn1;nuNld2JfF|PNHiv%qxAtoLyJQ@1aJ)k z|M0Py@YRyvIBaTe6@SF`>pw;VW8q0)>>qYL`~VCv1ALea?0X5j5f0F$8DSuhi+j!n zb5YMo;Lzd~E}aDrEnJ2G_=R9DVKYLIVNxDg&y*dSa%FwBa{%}r z;LU~W><7i-2td}L-PX`_hpTS8b1%Df&WdZU_gsx^)Mhk<<%{g^LsU# zOr@y^OhsTS0#gx~iojF^rXnyEfvE^gMPMod{}&N}&oQ3Jmz^d)eqv#=!&QP^;s;iRKf4?J>>9l?7u!K;!jGMIfFIEZ~zv(bh ze)O9K(eOFU>vKfvL)`QE;I^-cPs+hLU>nbengmwT_*dt1CME!XM2F=O!(?+xCi zUle>ciR$$es9p!zh)9d)gzKZ2zER1+Ww*bA<|y@*zlIi}90nD9lw|mLgRf-dP@Mk) zgu_ui7gQY;)qgWPORF*!|R2v|}}Bg-aB*sQe{X@fNDx_&5+ynBQ_x z*$1HRK@eya^Qr*UV>_;xZ=iGmtIq+e;_6;bIa$RPAS-7tLzR9+ulOpUbq~X>scKdj z%{91H&HgnvVD-3a42&=9Tl)HWd=v2*_&Sf)L-5&wbmBvQ_)OUbLnYmj! zc@(KxJd_Kd45+Bg#>}QEe#GY}7(99qo?0JJB3%oQtRbB00v%LQ2fw$+W%M!Sb0|;; zhxTZwr_94zI0oa|f1*2GP@A>cNX-{iw<{H8%GH9{q+!{W1%le3J%@^(72wk`*uiSB zq)70vE3C?ib(*fMUcZ_ts}wY%GVYRP#fP>JEZpBiPpgFA&8`Sj+5{elx;CS1Ew?AT zqtgCqus>C@Un}i3Ty9hDDtj12`abS~Eb-SkOt?aqfg#Yn8VKb+>A{Upny5|g0TZ>M zp$Eb$71z1@xNBh+bl+s60`7k|nK5_FL^<8}m^3wwSATQ4z_*}om=~A|O8qPjhTn%y z>3)mrpp82C+C%O-bQng7Iyn50hH6R#TaY?fptPw7*Bvz{jHwo_VP8 z`{=3@UAbaR=@LF)*dyZDEyyE#G#;XDNIC{LYdl1f+NALi-7jPtTo@urtkZaiBo)+n zh$I!zc!(s`rtuJQN*z45N8>S)LZ627sc@RX zp~J)K>TUrR)J~#K=(n?&+Hh0din{hj=)W#dfnJCJ>FU`^T^$M)Ae_@onl*~j-iX}V z`K-OM8I0;06}6$PU0>F2t%a`XRc@^p8GWI?y%Edgt3vyRN~StR{tnP{EwhjiO)4Eq zr*kh{-Ri{+USus$ud!?fvDgaF)4`5nRFsbzrokPDA$$Q*n!A%dMl);z=?o{D*QJu% znm4wsi^O9vyRhbLI@KIYMB>?~(Y!SVyEQDFaJpx4mys}1v4~Z`w=FS-J2$-0W1%1I z>^0KfZk#XV;=PHJiS-yl1_S@%cpSDmb;E8A7E8be5kR5g!pQBQ(M+AA9RJ(Co&C;d zx}H!Q{zl!dJ3O_M`I}?l8Ge~JX);Jh$kbl%ud(>6OPBa609#A z&l)V~>}WWted z_{9Wv{``sZG|Oj}O{Brvi0YB|-bn2AIM;`J0d5S0`}1h^0? z%CcKq-)0vcj(2E2HP2NcL zGH)W8F}y2RwJ*+uyO_5tk@a?m)7{J)-I)Mm0ihLfNuQBQV{bPTA&{kvco+>N)(hi^ zm+zeOW{e$xcLD*jByY=JqdUYqPN+KywnQ;+B$G^~AwvPSML-BX!#yxSd%Ke025w&N zTlm?U2JJ|)rw2!SZ`9bD?Fxlc;Y1hg1(akg(U~MXyme~|n!A+1C~puBAt4k7FjM&c zH|UjMj7>y7#?rp$Udh1UGtEghrxI%cVEFD%_6Hq4pvwD=bxxIUrT!>cxYZDw3)vrW z_<+LiZw?r~@?xS7Bx*e5rv+s2lWmgh={wyClN%-~zujI);f)y(c&#YqPv7y2r2Sr5 zVf@ZVl=7$V>D9nPRmz{%1rEys{sv^`WRKrhK#1SqWKZAS1G2!nG^X;C9>Gl@$8UO~ z>AU`jH1J7#EI;Z{`6Zim0fI#(`-_!6F1je~sh*TS*%SX8HhWr^aLR>|R#{=RuZPQS zj~_^=BGpUlGCpinkSHHPiLw%o5I-c%_8rweWU~%wKf$`#@y2FP%4#1#Ojn z$OG9C{Vkh4tt0Jl2@U+*HYaMg#5)8C=1=iIAlIP|Nc+b~Q9_CzvGKFoY)||1Y2QA6 zZTZP7i}Fwmm98twYf{ixF9WYM*3J<$4ut&H2;5=5gGs1&Q!Ye4#O9Yw&hmTo$tP(DJ#3 z!X8&B%*jUby)$+m>c9ATVby69+DKS?nmB%o772SN4Ge-Tm6iNlEA6GY1eRPQ(AP-O zW>1RK0ikD4JcO6771Z)iu}873h}^Jsxv(FW9cKZMUx16+AC2oZz?&%l@h=PewKnIr z;s~Wl?kYs9*WtTNisu;UJ;f}r*FVTEw7OHR>iRLjY-^FNtvhuak`7kSg zI?N+JGmGOYoEW0>Zf2p%V5Nq}f0ICkU1~J0o7nKQW|q#uS^2XVjl)*{Y*rdyO#&6( zGHBd1vBCcpjK)JNe~y_f;VQ$o>C2N^dJDD6RCbk>At{x~$;&2HnVeKE}5PcH&Pw=;o$1Fnhu7bfB3 zeC3{~f5E^ukstRY{1)I(hf{~tA8DHN0biRS&TA&|6XX18jMnz?dk9lz68!^{@P7#W z>5e9LK)yc+FO2;o=QlDuHDgXMa6i)+9?!v)<9EhzzQX57zg29KeB2SPP0%0DN&b*6 z-~S*#H9p}1XiWH9%S3UW4h;$8X7BG!z@JEe=_LF%&Y#BUhXcMx7xHcA{0YWqxfmF_ zJ-Bw&%3x^iZMWU+-w@ica#heDf+aItpMd3pRCs5|NJOm+zBikN+U~t`<(l@@43`_k zc|LjI&*w8A=`%0X$-{qSurJPC!H?0K;8GPA@wD7E_RRQ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef struct input_thread_t +{ + char* filename; + struct input_event event; +} input_thread_t; + + +void *input_thread_fcn(void * arg) +{ + printf("pthread started\n"); + + struct input_event ev[2]; + int result = 0; + int fevdev; + int size = sizeof(struct input_event); + int rd; + int value; + input_thread_t* args; + + args = (input_thread_t*) arg; + fevdev = open(args->filename, O_RDONLY); + if (fevdev == -1) { + printf("Failed to open event device.\n"); + exit(1); + } + + while (1) + { + if ((rd = read(fevdev, ev, size * 2)) < size) { + break; + } + + value = ev[0].value; + + args->event = ev[1]; + // quit + if(16==args->event.code && 1==args->event.value) break; + } + + printf("Exiting.\n"); + result = ioctl(fevdev, EVIOCGRAB, 1); + close(fevdev); + + pthread_exit(0); +} + + +int CRC(int data) +{ + int c; + c = 0; + c ^= data & 0x03; + c ^= (data >> 2) & 0x0F; + c ^= (data >> 6) & 0x0F; + c ^= (data >> 10) & 0x0F; + c ^= (data >> 14) & 0x0F; + c ^= (data >> 18) & 0x0F; + return c; +} + +int data2frame(int data) +{ + int frame; + frame = 0; + frame |= CRC(data) << 2; + frame |= data << 6; + frame |= 0xFE000000; + return frame; +} + + +int values2data(int velocity, int direction, int ignation, int mg, int fire, int turretelev, int turret_left, int turret_right, int recoil) +{ + int data = 0; + data = (mg & 1) | (ignation & 1) << 1 | (direction & 0b11111) << 2 | (fire & 1) << 7 | (turretelev & 1) << 8 | (turret_left & 1) << 9 | (turret_right & 1) << 10 | (recoil & 1) << 11 | (velocity & 0b11111) << 12; + return data; +} + +int main(int argc, char* argv[]) +{ + pthread_t inpthread; + pthread_attr_t inp_thread_attr; + input_thread_t input_thread_args; + int inpdetachstate; + int i=0; + int frame; + + int velocity = 0b10000, direction=0b01111; + int ignation = 0, mg = 0, fire = 0, turretelev = 0, turret_left = 0, turret_right = 0, recoil = 0, smoke = 0; + + + input_thread_args.filename = argv[1]; + + + pthread_attr_init(&inp_thread_attr); + if (pthread_create(&inpthread, &inp_thread_attr, input_thread_fcn , (void *) &input_thread_args)) printf("failed to create thread %d\n", i); + + + while(1){ + usleep(100000); + printf("%d %d %d %d %d %d %d %d %d %d | %d %d %d %d\n", velocity, direction, ignation, mg, fire, turret_left, turret_right, turretelev, recoil, smoke, input_thread_args.event.code, input_thread_args.event.value, input_thread_args.event.type, input_thread_args.event.time); + if(108==input_thread_args.event.code){ + if(input_thread_args.event.value){ + velocity = 0b11111; + }else{ + velocity = 0b10000; + } + } + if(103==input_thread_args.event.code){ + if(input_thread_args.event.value){ + velocity = 0b00000; + }else{ + velocity = 0b10000; + } + } + if(105==input_thread_args.event.code){ + if(input_thread_args.event.value){ + direction = 0b00000; + }else{ + direction = 0b01111; + } + } + if(106==input_thread_args.event.code){ + if(input_thread_args.event.value){ + direction = 0b11111; + }else{ + direction = 0b01111; + } + } + if(23==input_thread_args.event.code){ + if(input_thread_args.event.value){ + ignation = 1; + }else{ + ignation = 0; + } + } + if(34==input_thread_args.event.code){ + if(input_thread_args.event.value){ + mg = 1; + }else{ + mg = 0; + } + } + if(33==input_thread_args.event.code){ + if(input_thread_args.event.value){ + fire = 1; + }else{ + fire = 0; + } + } + if(29==input_thread_args.event.code){ + if(input_thread_args.event.value){ + turret_left = 1; + }else{ + turret_left = 0; + } + } + if(20==input_thread_args.event.code){ + if(input_thread_args.event.value){ + turretelev = 1; + }else{ + turretelev = 0; + } + } + if(19==input_thread_args.event.code){ + if(input_thread_args.event.value){ + recoil = 1; + }else{ + recoil = 0; + } + } + + frame = data2frame(values2data(velocity, direction, ignation, mg, fire, turretelev, turret_left, turret_right, recoil)); + printf("%#x\n", frame); + if(pthread_kill(inpthread, 0)) break; + } + + return 0; +} + + + +/* Sample UDP client */ +/* +#include +#include +#include + +int main(int argc, char**argv) +{ + + FILE *kbfp; + char key; + + kbfp = fopen("/dev/input/event2", "rb"); + + while(1){ + key = fgetc(kbfp); + printf("%c\n", key); + } + fclose(kbfp); + + int sockfd,n; + struct sockaddr_in servaddr,cliaddr; + char sendline[1000]; + char recvline[1000]; + + if (argc != 2) + { + printf("usage: udpcli \n"); + exit(1); + } + + sockfd=socket(AF_INET,SOCK_DGRAM,0); + + bzero(&servaddr,sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr=inet_addr(argv[1]); + servaddr.sin_port=htons(32000); + + while (fgets(sendline, 10000,stdin) != NULL) + { + sendto(sockfd,sendline,strlen(sendline),0, + (struct sockaddr *)&servaddr,sizeof(servaddr)); + n=recvfrom(sockfd,recvline,10000,0,NULL,NULL); + recvline[n]=0; + fputs(recvline,stdout); + } +} +*/ diff --git a/obj/Debug/main.o b/obj/Debug/main.o new file mode 100644 index 0000000000000000000000000000000000000000..a4543cba4d6ec18973f0e7993fdf219cd990ad53 GIT binary patch literal 10240 zcmbta4RBP|6~1p@NHz&13lWI?ltnW%ngn+3d#Mw;>=A zF-2LoSfZuc>Ik*%R9kVZg98IrL2-mJiLWTNa5a$ zf55gOZ`LJmuLJZ)Bf`+K;!8^y1^aDH1l%63Ywf|FNZ!RtbIEta)-0Lr@&Cl@?$S877AIG2W9;5+- zM$dpb&yT7nhFm=Zl}r~q=rRXg;h@JceQD!6RM+Y}-xU4CfU8u67$}y+r7@84mubW< zy(dkoWL5rXMs;47ic>NU{{kYDtzM>6K(Tk}z`cF}k!*<)MbKF0gZO2%M#Vwc+yR%YpRk z4bYwPp8*IK$)HDe7b|6VUV#IuJEyvS)xEE})2i!J-AU{MnO*2Jkg0VC(!1_Ma*zLE zSYC381oosJ4(!=S@R30JcSofWiFX~hC&^`)X*`oYo3|!$RUCNKP;0RA@UAZKTwi(k zbbV&mb|3-SCc7bJzwumsX5&C+?fFdO#Y}2&O=e#kh}Wdo&#VQygXlngddr&dzk7gwC7k?t`v6)7=l9C)0fzI(Me~{q(Y#H>W@Jr(yj%ZWf9R>o}U4q>_PQ zltMM9!O%V}p|a-GS~WE+KmoN#zM3o_s>#{OdAnazImtP1SLLe> zu-X77nNypduXc{rro=QAnTi3Zg?=1(9kH17PzX}KNOmK$tHM|fkDrQdbD^4r_KxO{o9GzjcGIRq8? z*2Z_RFwi>ewuBW7dy{rBVOwFbG8lLmQiP*->eA3gc@iFnbT|z^z#r z({L27-l*cdirb*L>56NsOoWATm13HdXolj}D{kge@agKkPn2S&$jGuAqS%dN8f(Z@vXZDFPqZeF3*>P$M6z?|$vi6I4O+s%5flCaEJEcWh&E>LnTLo)iP?Mn zA>}djxRky~(;dcp!tDKwq!vz(+1vM!Jp36g=&CXzj8^6I4YF!e?5o7ykF2YgRta&m zFg7dM`bsPjF%2pe;@0GGfjq9>!I`~BC>|Ns<_Qn&fYpV!i7>_*vnr~}&5FqtV~uf! z2R0ekOi^CG93U7Sk+4w|O%P_qjpa+rSHo~eRf38T#n>TVGSMh6N1*|XdyGS~)G$_8 zAzC(Ftgfm7qw*@ltjKAP&S@`!ZFY>$_~vL8=$g^1t1ze9VzjRqB}})9?*hHbg?X$8 zSjrBiW2G0Vp6_KGcyZ`e<;<`c)a32}v`cJJn>NsL+ftZ^Y2M6TqEl9v%vDED_~k+R zBCLpdz&uRfmBl(eOgCk*Epn%J`e)hQ4jra9Ps?E*raR<=PWfm0fh;!M|8+7K%qYKfY=aVK+XQ2B ziNgRH#=k4Zz*Wv1phitwyxpov+Ez<2R@0D(-(S;M-w=vM;0z&ZQprS3Bo>OM!dA_u zh@H$wg30zdtyauRL_+z3Xe5^E5~4jAiTPl+7Q)`zVI_TScvhgpivzJE?Us_kLw`;* zx@aMAu<1r(9Vr_~xgblaYH-(1GLHSIb8CaFiyjN2H=skGTe0M743Rm4U&;8hz4_r&eyJsAeR<0T2ip@UZ ze#AVq!@J-09i!^K{ZDTBFMeIF8>-x`?x*gC+tM%+Rx%Z}h27blv_c};7Ejn-JjZ-h ziNleE6|y7on5>ov2koHfw4(7)#NI08Nlr932cwbJnCJ{fQ&wbkk!Gqxg`{Xq`(tYI39_D-_*QCsz!NUo0~Cgvn-f0h4Ln#w17g* zF`otVaaL0}t#THU^W{XXy0y_;=UwPq|iSCzbPNN-SvG3BC`SkpVH? z7C^OFop5%~_h$>Ss;=%v@9b4@TgKxmq_<<9Z{C9Iyd4p1&RpO1zWLWuDp%00Z*03m z7+oG?^5_!xUbqXZ0iVL#0`TJI3eTgix-oe4Mtlj$ny_b?YaLiCxx_)V)G6Qq$1iUxhQ)nyBx zEWK}2GAVqCxMHLex1np}0A&%4IY=`Jc+yF3hCVq@AZ2U7Z;a43XbX$ubN>|R6taJL ztTY$6zMYNjxPK0WOgr`Z$=-<}t?T}hFfC2N_D3`aJbs2>2BJ{?c2oVjND=FYDX~4* z6*2wZMU%bq^-+jp$T*swKk|C+sNTl`$oY7{a7y&}rGOQR--jC;v=>yDz3TC^0*yeu zBJnwX*dEr*VY8rA%z~LqZlCCE$g;5~#aNN%e#a#)w z%%AdZ0v;Rg--z?ur#$BX)<`(NHSPu;TM&Mz&u@G3Tmx7O{0haz`>zoG*a-L&BjEU{ zvXCEs;Tm=dhWDtXz;DCCg0I1F9u9^@Bp$M(A{31$t?c1bO7Vl7uT+v$Rrs z3+_>j-$pn-i_j0(WIf@y7didN&%b~njlg;af}=KZPJP_K)ii+Zojj%kzQ* z$32$)|J{M(-pBYQ2R^}pchI`Td?q^ZXAyvg9d3#2=QYAHPkPh=CB#vOJ{|#CAHRuW z<8dugtoVaNe=1QHf#37_fd>+G;{iyL6eO*?iK9k>khoyfzKzL{qF)9 zwt9!Y(|@A_$3IQ6e>(oj@s>yr>cTrG`o|;I=TvuGW7rsfL$Lzq4jbc`D>fVpHZ-SF zNq)M#=5Rj0UrRXp!5_D|M6mxq5x-c&Z>2n!YxvcK`!)Qhgs;)?FNt5L;r!$XYWTCn zucTr;s^JOJ&uI8E(tlpVSCRfp8h#h??`rrQ^7DHQFC#x6YWPm# z|ES@=CH+q{oY&BhhJQr*CDe0$_7gu&!#^N?s)m1;{9dc!D~MmL;nRutYxol4*J*e& z`Nyw<*f`I%RJWLhZ&qqzyN2IRct*q7&(j+I2=Omaj~#`So_?<5#J@&8=IJ~&^*eBS zMUsC0tl=vu$UillpXaPsbt6a06CszotBW8oq__Wg5=U>0311CjU(u z{tWqP(eOIb@6>SKuXhs8b>sS^HJqOpy$(NEH=dUtI&iGRUn%ZO8h#Vyc|^mH6Mjm= zdEKAY@GnUJf`%WYxL;^E=Q)~QnfN~9`JJTUJioIwoaeVr!+Cyh*KnTSW)0{0ZP##~ z-|ZUC^ZU4lTQpwhxq@jF@i~;|m(=BdIzU>-y`+H4otC^rmgzXve}jheKC@lJ`F?y( I!+E{^2Sh|BTL1t6 literal 0 HcmV?d00001