
    :h6                     &   S r SSKrSSKrSSKrSSKJr  SSKJr  SSKrSSK	r	SSK
J
r
  SSKJr  \" SS5      r\" S	S
SSS5      \" SSSSS5      \" SSSSS5      \" SSSSS5      \" SSSSS5      \" SSSSS5      \" SSSSS5      \" SSSSS5      \" SSSSS5      \" SSSSS5      \" SSSSS5      \" SSSSS5      \" SSSSS5      \" SSSSS5      S .rS!S"S#S$S%S&S'S(S).rS*rSrS@S+\	R$                  S,\S-\S.\4S/ jjrS+\	R$                  S0\S.\4S1 jrS2\S.\\   4S3 jrS4\	R$                  S5\4S6 jrS4\	R$                  S.\4S7 jrS4\	R$                  S8\S.\4S9 jrS4\	R$                  S:\4S; jrS4\	R$                  S:\S<\4S= jrS> r\S?:X  a  \" 5         gg)Aa  
ELAN 04F3:0C4C Match-on-Chip fingerprint reader driver PoC.

Usage:
    ARGV0 -h | --help
    ARGV0 info
    ARGV0 soft_reset
    ARGV0 hard_reset
    ARGV0 finger_info <id>
    ARGV0 verify
    ARGV0 enrolled_count
    ARGV0 enroll (-u UD)
    ARGV0 delete <id>
    ARGV0 finger_info_all
    ARGV0 delete_all
    ARGV0 wipe_all
    ARGV0 fw_ver
    ARGV0 capture <png>
    ARGV0 read_reg <reg>
    ARGV0 dump_regs
    ARGV0 raw (-e EP) <hex>...

Options:
-h, --help         Show help
-e EP, --ep-in EP  Input endpoint for raw commands
-u UD. --user UD   User data for enroll command

Commands:
info               Get device info
soft_reset         Reset sensor (via libusb)
hard_reset         Reset sensor (via hardware - disconnect and reconnect)
finger_info <id>   Get finger info
verify             Verify finger
enrolled_count     Get number of fingers currently enrolled
enroll             Enroll a new finger
delete <id>        Delete finger
delete_all         Delete all enrolled fingers (one by one)
wipe_all           Wipe all enrolled fingers (using special command)
fw_ver             Get firmware version
capture            Capture image into a PNG file
read_reg <reg>     Read register
dump_regs          Read all registers
raw                Send raw command
    N)
namedtuple)Optional)docopt)ImageCommand)commandout_lenin_lenep_outep_ins   @'WDTRST      s   @      s   @   s   @F   s   @s    s   @ s   @s   @H   s   @   s   @s   @s   @   s   @)reset_devicefw_ververifyfinger_infoenrolled_numsensor_sizeenrolled_num1abortcommitenrollcheck_enrolled_collisiondelete_subsiddeletewipe_allzMove slightly downwardszMove slightly to the rightzMove slightly upwardszMove slightly to the leftzSensor is dirty or wetzFinger not enrolledzFinger area not enoughz*Maximum number of enrolled fingers reached)A   B   C   D               ))  i   )r,   iL  )r,   i^  usbcmdnamepayloadreturnc                 T   [         U   u  pEpgnXB-   n	[        U	5      U:w  a%  [        R                  " S[        U	5       SU 35        U R	                  XyU5        US:X  d  Uc  gU R                  XU5      n
[        U
5      U:  a%  [        R                  " S[        U	5       SU 35        U
$ )NzWrong command size: z vs r       z$Device replied with shorter answer: )COMMANDSlenwarningswarn	bulkWritebulkRead)r-   r.   r/   timeout
outpayloadoutleninlenr   r   cmdresps              #/mnt/public/Repos/elanpoc/elanfp.pyr   r   w   s    /7/@,Ju

C
3x6,SXJd6(CDMM&w'zU]<<g.D
4y5<SXJd5'RSKr2   regc                 Z   SUs=::  a  S:  d  O  [        S5      eS[        SU-   /5      -   nU R                  SU5        U R                  SS5      n[	        U5      S:w  a"  [
        R                  " S[	        U5       35        [        US   5      nU(       a  [        S	U S
U 35      eUS   $ )Nr   @   zRegister out of range (0-63)   @r   r   r   z Device replied with wrong size: zFailing to read register : )	
ValueErrorbytesr7   r8   r4   r5   r6   	get_errorIOError)r-   r@   r=   r>   errors        r?   read_registerrJ      s    =b=788
E4#:,'
'CMM!S<<1D
4yA~8TDEd1gE1#b@AA7Nr2   bytec                 X    U S-  S:X  a  g U [         ;  a  S[        U 5       3$ [         U    $ )N   r   zUnknown error )ERRORShex)rK   s    r?   rG   rG      s4    t6D	{++$<r2   handle	user_datac           	         [        U S5      n[        US   5      nU(       a  [        SU 35        g US   =pE[        SU 35         [        S5        [        U SSS9n[        US   5      nU(       d  [        S	US    35        M?  US   S
:w  a  [        SU 35        MX  [        S5         SnSnXv:  a  [        SUS-    SU S35        [        R                  " SXFUS5      n[        U SUSS9n[        US   5      nUS   S:w  a*  [        SU S[        US   5       S35        US   S:X  a  g M  US-  nXv:  a  M  [        U S5      nUS   S:w  a  US   n	[        SU	 35        g [        S5        [        R                  " SSUS-   -  5      U-   R                  SS 5      n[        U S!U5      nUS   S:X  a  [        S"5        g [        S#UR                  S$5       35        g )%Nr   r   z/Failed to retrieve currently enrolled fingers: Enrolled fingers: Place finger on readerr     r9   zFinger already enrolled: r)   Error: 
Proceedingr   r   zPlace finger on reader [/]BBBBr   '   ()r+   r    r   z-Error: Finger was already enrolled as finger z2No collisions detected, committing enrolled fingerBrM   r   E       r   u   Enroll successful 🎉zSensor is angry:  )r   rG   printstructpackrO   ljust)
rP   rQ   r>   rI   new_finger_idenrolledtotal_attemptsattempts_doner/   colliding_fingers
             r?   r   r      s   6>*Dd1gE?wGH#Aw&M	xj
)*
&'vx6$q'"-d1gY787d?GE7#$lNM

(():(;1^<LANO++fm]TUVvx%@$q'"7a<GE7"Sa\N!45Aw$ 
( 656DAw!|7=>N=OPQ	
>?{{3(9 :;iGNNrSZ[G68W-DAw!|&'!$((3-12r2   c                      [        S5        [        U SSS9n[        US   5      nU(       a  [        U5        M9  [        SUS    35        US   $ )NrT   r   rU   rV   r   zRecognized finger: )rc   r   rG   )rP   r>   rI   s      r?   r   r      sT    
&'vx6$q'"%L#DG9-.Awr2   	finger_idc                      [        U SUR                  SS5      5      nUS   S:X  a  [        S5        [        U 5        M?  [	        U5      S:X  a  [        S[        US   5       35      eU$ )Nr   r   little   z0Sensor is angry, verify a finger to calm it downr   rW   )r   to_bytesrc   r   r4   rH   rG   )rP   rm   r>   s      r?   get_finger_inforr      sj    
v}i.@.@H.MN7d?DE6Nt9>GId1g$6#7899r2   fpidc           	          [        US/5      n[        U SU5      n[        US   5      nUS   S:w  a  [        SU S[	        US   5       S35        g [        S5        [        X5      n[        R                  " U5        g )Nr   r"   r   rW   r]   r^   Deleted, finger info:)rF   r   rG   rc   rO   rr   hexdump)rP   rs   r/   r>   rI   s        r?   delete_by_idrw      su    T1IG68W-Dd1gEAw!|wbT!Wa01%&v,r2   
finger_sidc           	          [        U SU5      n[        US   5      nUS   S:w  a  [        SU S[        US   5       S35        g [        S5        [	        X5      n[
        R
                  " U5        g )Nr!   r   r   rW   r]   r^   ru   )r   rG   rc   rO   rr   rv   )rP   rs   rx   r>   rI   s        r?   r"   r"      sg    6?J7Dd1gEAw!|wbT!Wa01%&v,r2   c                  *   [        [        R                  S[        R                  S   5      5      n [
        R                  " 5        n[         H  u  p#UR                  X#5      nU(       d  M    O   [        S5      eUR                  [        5          U S   (       a  UR                  5         GOU S   (       a  [        US5        [        S5        GOU S   (       a  UR                  5       n[        S	UR!                  5       5        [        S
UR#                  5       5        [        SUR%                  5       UR'                  5       4-  5        [        SUR)                  5       5        [        SUR+                  5       5        [        SUR-                  5       5        [        US5      n[        SUS    SUS    35        GOU S   (       a  [/        U5        GOU S   (       a%  [        US5      n[        SUS    SUS    35        GOU S   (       a<  [1        U S   5      n[3        XG5      n[        S5        [4        R4                  " U5        GOQU S   (       aD  [7        S5       H3  n[3        XG5      n[        SU S35        [4        R4                  " U5        M5     GOU S   (       a  [        US5      n[        SUS    35        GOU S   (       a  [9        X@S    R;                  5       5        GOU S!   (       a  [1        U S"   5      n[=        [?        S# U S$   5      5      n	[        S%[A        U	5       S&35        [4        R4                  " U	5        [        5         URC                  SU	S'S(9  [        S)5        URE                  US*S'S(9n[        S+[A        U5       S&35        [4        R4                  " U5        GOU S,   (       a  [1        U S   5      n[G        XG5        GOU S-   (       ax  [7        S5       Hg  n[3        XG5      nUS.   S/:X  a  [        S0U S135        M(  [H        RJ                  " S2S3US4-   -  5      US5S  -   RM                  S6S75      n	[O        XGU	5        Mi     GOEU S8   (       GaN  [        US95      nUS   S-   n
US5   S-   nURC                  S[=        SS:/5      S'S(9  URE                  S5S5U
-  U-  S'S(9n[P        RR                  " S;X4U5      nS<nSn[7        SU5       HA  n[7        SU
5       H.  nURU                  UU45      n[W        UU5      n[Y        UU5      nM0     MC     [P        RZ                  " S=X45      nX-
  n[7        SU5       HO  n[7        SU
5       H<  nURU                  UU45      nUR]                  UU4[1        UU-
  S>-  U-  5      5        M>     MQ     UR_                  U S?   S@5        OU SA   (       a?  [        SB5        [        USA5        [        SC5        [        USSDS(9n[        SUS    35        OU SE   (       a+  [1        U SF   5      n[        SGU SH[a        UU5      SI 35        OnU SJ   (       ad  [        SK5        [7        SL5       HJ  n[        U SM3SNSO9  [7        SL5       H!  n[        SP[a        UUSL-  U-   5      SQ 3SNSO9  M#     [        5         ML     S S S 5        S S S 5        g ! [b        [d        4 a4  n[        SR5        URC                  S[f        SS   R                  5        e S nAff = f! , (       d  f       N^= f! , (       d  f       g = f)TNARGV0r   zFailed to open USB device
soft_reset
hard_resetr   zDevice reset.infozBus:zAddress:zVID:PID: %04x:%04xzManufacturer:zProduct:zSerial number:r   zFirmware version: .r   r   z	Version: r   z<id>zFinger info:finger_info_all
   zFinger info :enrolled_countr   rS   r   z--userrawz--ep-inc                     [        U S5      $ )N   )int)xs    r?   <lambda>main.<locals>.<lambda>C  s
    #a*r2   z<hex>z	Sending [z]:rU   rV   zWaiting for response...i  z
Received [r"   
delete_allrp   zFinger z not enrolledr_   rM   r   r   r`   ra   capturer   	   zI;16Li   L   z<png>PNGr#   zWiping all fingersz.Checking if all fingers are wiped (~5 seconds)r\   read_regz<reg>z	Register rD   z#02x	dump_regsz$     x0  x1  x2  x3  x4  x5  x6  x7
r   zx  )endz  02xAbortingr   )4r   __doc__replacesysargvusb1
USBContextDEVICESopenByVendorIDAndProductIDOSErrorclaimInterfaceIFACEresetDevicer   rc   	getDevicegetBusNumbergetDeviceAddressgetVendorIDgetProductIDgetManufacturer
getProductgetSerialNumberr   r   rr   rv   ranger   encoderF   mapr4   r7   r8   rw   rd   re   rf   r"   r   
frombuffergetpixelminmaxnewputpixelsaverJ   	ExceptionKeyboardInterruptr3   )argscontextvidpidrP   devr>   rm   epr/   widthheightimgminvmaxvyr   vimg_8bdiffr@   ijes                           r?   mainr     s5   '//'388A;78D		gHC77AFv  
 566""5)z%&&(,'FN3/*&\*0*:*:*<C&#"2"2"45*c&:&:&<=.#//2CSEUEUEW1XXY/3+>+>+@A*cnn&67*C,?,?,AB"684D.tAwiqa	BC(^6N(^"684DId1gYaQy9:-( #DL 1I*6=D.)OOD)+,%*2Y	.vAYKq9:- &/
 *+"6>:D.tAwi89(^6>#8#8#:;%[T)_-B#C(<d7m$LMGIc'l^267OOG,G$$Q$>34!??2tT?BDJs4yk45OOD)(^ #DL 1I 3,'%*2Y	.vA8t+!GI;m"DE$#);;sDIM4J#KdSTSUh#V"]"]^`bi"jv': &/ )__"6=9D GaKE!!Wq[F$$QtTl(;T$J!??1a%i&.@$?OD**7UOTJC #DD"1f-!&q%A #aV 4A#&tQ<D#&q$<D "1 . #YYsUO<F;D"1f-!&q%A #aV 4A"OOQFCTS8H48O4PQ "1 .
 KKWu5*%./FJ/JK"6>5ID.tAwi89*%d7m,CIcU"]63-G,MNO+&AB"1X2hB/!&qA!B}VQUQY'G&M"NTVW "*	 &e * 
	@ 01 j!  HW$5$=$=>q *) 
	s  "\,$\[3Z,,[3.!Z,[3C+Z,<[3>Z,[3-Z,[3AZ,[3
AZ,[3'Z,?[3&Z,'[3)CZ,-[3/#Z,[3B Z,[3EZ,.[3/AZ,7[384Z,,[3-A.Z,\,[0</[++[00[33
\	=\
\__main__)r2   rU   ) r   rd   r   r5   collectionsr   typingr   rv   r   r   PILr   r   r3   rN   r   r   USBDeviceHandlestrrF   r   r   rJ   rG   r   r   rr   rw   r"   r   __name__ r2   r?   <module>r      sT  +X  
  "     
Y S
T NAq!T:k1aA.oq!Q2?Ar1a8OQ1a8[!Q15_aAq9_aAq1or1a3oq!Q2 'Aq! D_b!Q:oq!Q2Aq$7P $
&
!
%
"

"
6	

 	
%%  e \a &t++ # # $C HSM 034'' 03E 03f	4'' 	C 		D00 	S 	U 		-- 	S 	4'' s  FR zF r2   