
    g>                     \   d Z ddlmZ ddlmZ ddlZddlZddlZddlZddlZddl	m
Z
 ddlmZ  ej                  d      ZdZdZd	Zd
ZdZdZdZdZdZdZ G d dej2                        Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z  ejB                  e      Z" ejB                  e      Z# ejB                  e      Z$ ejB                  e      Z%ejL                  Z' ejB                  e       Z(ejR                  Z*ejV                  Z,ejZ                  Z.ej^                  Z0ej^                  Z1ej^                  Z2ej^                  Z3ejh                  Z5e2Z6e2Z7 ejB                  e      Z8 ejB                  e      Z9 ejt                  dejv                  e0ejx                  e1ejz                   ejB                  ej|                        e,      Z?dZ@d ZAdZBd!ZCdZDd"ZEdZFd#ZGdZHd$ZIej                  j                  ej                  j                  d%            ZNej                  j                  ej                  j                  d&            ZOej                  j                  d'      rje#j                  eOd(      ZSdeOj                  _U        e" ejB                  ejx                        geOj                  _V        e#eOj                  _U        ejx                  ejh                  ejz                  geOj                  _V        ej                  eOj                  _U        e#ejh                  e,ejz                  geOj                  _V        e,eOj                  _U        e#geOj                  _V        e*eOj                  _U        e$geOj                  _V        e*eOj                  _U        ej                  eOj                  _U        deOj                  _U        e$geOj                  _V        e%eOj                  _U        g eOj                  _`        e'eOj                  _U        e#e.ej                  geOj                  _V        e2geNj                  _V        e8eNj                  _U        e"eNj                  _U        e8geNj                  _V        deNj                  _U        e8e$geNj                  _V        e$eNj                  _U        e9e#geNj                  _V        deNj                  _U        e9 ejB                  ej|                        e,e?ejv                  geNj                  _V        e7eNj                  _U        e3e5geNj                  _V        e9eNj                  _U        e(e6geNj                  _V        deNj                  _U        e9e%e#geNj                  _V        deNj                  _U        e9e%e#geNj                  _V        e0eNj                  _U        e9e1e, ejB                  ej|                        e,geNj                  _V        nej                  d)       d* Zod+ Zpd, Zqd- Zrd. Zs e?es      Ztd/ Zu G d0 d1ej                        Zwy)2zDImplements HID device interface on MacOS using IOKit and HIDManager.    )queue)rangeN)errors)basezpyu2f.macosi   VendorId	ProductIDProductPrimaryUsagePrimaryUsagePageMaxInputReportSizeMaxOutputReportSizeReportIDc                       e Zd Zy)_CFTypeN__name__
__module____qualname__     "lib/third_party/pyu2f/hid/macos.pyr   r   ,       r   r   c                       e Zd Zy)	_CFStringNr   r   r   r   r   r   0   r   r   r   c                       e Zd Zy)_CFSetNr   r   r   r   r   r   4   r   r   r   c                       e Zd Zy)_IOHIDManagerNr   r   r   r   r   r   8   r   r   r   c                       e Zd Zy)_IOHIDDeviceNr   r   r   r   r    r    <   r   r   r    c                       e Zd Zy)
_CFRunLoopNr   r   r   r   r"   r"   @   r   r   r"   c                       e Zd Zy)_CFAllocatorNr   r   r   r   r$   r$   D   r   r   r$      i  s	   IOService         IOKitCoreFoundationdarwinkCFRunLoopDefaultModezNot running on MacOSc                 L    t         j                  d| j                         d      S )zBuilds a CFString from a python string.

  Args:
    s: source string

  Returns:
    CFStringRef representation of the source string

  Resulting CFString must be CFReleased when no longer needed.
  Nr   )cfCFStringCreateWithCStringencode)ss    r   CFStrr2      s     
	%	%dAHHJ	::r   c                    t        |      }t        j                  | |      }t        j	                  |       |syt        j                  |      t        j                         k7  r7t        j                  dj                  t        j                  |                  t        j                         }t        j                  |t        t        j                  |            }|sy|j                  S )z'Reads int property from the HID device.NzExpected number type, got {})r2   iokitIOHIDDeviceGetPropertyr.   	CFReleaseCFGetTypeIDCFNumberGetTypeIDr   
OsHidErrorformatctypesc_int32CFNumberGetValueK_CF_NUMBER_SINT32_TYPEbyrefvaluedev_refkeycf_keytype_refoutrets         r   GetDeviceIntPropertyrH      s    :&))'6:(,,v	^^H!5!5!77


:AA
x " # # 	#
H&="LL-	/#		r   c                    t        |      }t        j                  | |      }t        j	                  |       |syt        j                  |      t        j                         k7  r7t        j                  dj                  t        j                  |                  t        j                  |t              }t        j                  t              }t        j                  ||t        t               }|sy|j"                  j%                  d      S )z*Reads string property from the HID device.NzExpected string type, got {}utf8)r2   r4   r5   r.   r6   r7   CFStringGetTypeIDr   r9   r:   r;   castCF_STRING_REFcreate_string_buffer"DEVICE_STRING_PROPERTY_BUFFER_SIZECFStringGetCStringK_CF_STRING_ENCODING_UTF8r@   decoderA   s         r   GetDeviceStringPropertyrS      s    :&))'6:(,,v	^^H!5!5!77


:AA
x " # # [[=1(##$FG#
h-O7	9#				&	!!r   c                     t         j                  |       }t        j                  t              }t         j                  |t        |       |j                  S )zObtains the unique path for the device.

  Args:
    device_handle: reference to the device

  Returns:
    A unique path for the device, obtained from the IO Registry

  )r4   IOHIDDeviceGetServicer;   rN   DEVICE_PATH_BUFFER_SIZEIORegistryEntryGetPathK_IO_SERVICE_PLANEr@   )device_handleio_service_obj
str_buffers      r   GetDevicePathr\      sD     ..}=.**+BC*~/A:N			r   c                 n    ~~~~t        |      D cg c]  }||   	 }}| j                  |       yc c}w )z+Handles incoming IN report from HID device.N)r   put)	
read_queueresultsenderreport_type	report_idreportreport_lengthiincoming_bytess	            r   HidReadCallbackrh      s=     fk9',]';<';!F1I';.<..  =s   2c                    t         j                         | _        | j                  st        j	                  d       yt
        j                  | j                  | j                  t               t        }|t        k(  s	|t        k(  r/t         j                  t        dd      }|t        k(  r%|t        k(  r/|t        k7  rt        j	                  d|       t
        j                  | j                  | j                  t               y)zBinds a device to the thread's run loop, then starts the run loop.

  Args:
    hid_device: The MacOsHidDevice object

  The HID manager requires a run loop to handle Report reads. This thread
  function serves that purpose.
  zFailed to get current run loopNi  Fz!Unexpected run loop exit code: %d)r.   CFRunLoopGetCurrentrun_loop_refloggererrorr4   IOHIDDeviceScheduleWithRunLooprY   K_CF_RUNLOOP_DEFAULT_MODEK_CF_RUN_LOOP_RUN_TIMED_OUT K_CF_RUN_LOOP_RUN_HANDLED_SOURCECFRunLoopRunInModeK_CF_RUN_LOOP_RUN_STOPPED IOHIDDeviceUnscheduleFromRunLoop)
hid_devicerun_loop_run_results     r   DeviceReadThreadrw     s     224*		 	 
LL12
&&z'?'?'1'>'>'@B
 4	 ;	;	 @	@//! 
 ;	;	 @	@ 55
LL46IJ (()A)A)3)@)@)BDr   c                   D    e Zd ZdZed        Zd Zd Zd Zd Z	d Z
d Zy	)
MacOsHidDevicezaImplementation of HID device for MacOS.

  Uses IOKit HID Manager to interact with the device.
  c                  <   t         j                  dd      } | st        j                  d      t         j	                  | d       t         j                  |       }|st        j                  d      t         j                  |      }t        |z         }t         j                  ||       g }|D ]  }t        j                         }t        |t              |_        t        |t              |_        t!        |t"              |_        t        |t&              |_        t        |t*              |_        t        |t.              |_        t3        |      |_        |j7                  |j9                                 t:        j=                  |       t:        j=                  |        |S )See base class.Nz&Unable to obtain HID manager referencez)Failed to obtain devices from HID manager)r4   IOHIDManagerCreater   r9   IOHIDManagerSetDeviceMatchingIOHIDManagerCopyDevicesCFSetGetCountIO_HID_DEVICE_REFCFSetGetValuesr   DeviceDescriptorrH   HID_DEVICE_PROPERTY_VENDOR_ID	vendor_idHID_DEVICE_PROPERTY_PRODUCT_ID
product_idrS   HID_DEVICE_PROPERTY_PRODUCTproduct_string!HID_DEVICE_PROPERTY_PRIMARY_USAGEusage&HID_DEVICE_PROPERTY_PRIMARY_USAGE_PAGE
usage_pageHID_DEVICE_PROPERTY_REPORT_IDrc   r\   pathappendToPublicDictr.   r6   )hid_mgrdevice_set_refnumdevicesdescriptorsdevds          r   	EnumeratezMacOsHidDevice.Enumerate9  sP    &&tT2GFGG	''6 227;NIJJ


n
-C 3&)G	1 K



!a(.KLak)#/MNal01LNa$S*KLag)
57al(.KLakS!af)*  LL LLr   c           	         t         j                  t        |      }|st        j                  d      t         j                  t        |      | _        | j                  st        j                  d      t         j                  |       || _	        t         j                  | j                  d      }|t        k7  r$t        j                  dj                  |            t        j                         | _        d | _        t#        j$                  t&        | f      | _        d| j(                  _        | j(                  j-                          t/        | j                  t0              | _        | j2                  st        j                  d      t/        | j                  t4              | _        | j6                  st        j                  d      t9        j:                  | j2                  z         | _        t         j?                  | j                  | j<                  | j2                  t@        t9        jB                  | j                               y )	Nz7Device path does not match any HID device on the systemz2Failed to obtain device handle from registry entryr   z+Failed to open device for communication: {})targetargsTz#Unable to obtain max in report sizez$Unable to obtain max out report size)"r4   IORegistryEntryFromPathK_IO_MASTER_PORT_DEFAULTr   r9   IOHIDDeviceCreateK_CF_ALLOCATOR_DEFAULTrY   IOObjectReleasedevice_pathIOHIDDeviceOpenK_IO_RETURN_SUCCESSr:   r   Queuer_   rk   	threadingThreadrw   read_threaddaemonstartrH   )HID_DEVICE_PROPERTY_MAX_INPUT_REPORT_SIZEinternal_max_in_report_len*HID_DEVICE_PROPERTY_MAX_OUTPUT_REPORT_SIZEinternal_max_out_report_lenr;   c_uint8in_report_buffer&IOHIDDeviceRegisterInputReportCallbackREGISTERED_READ_CALLBACK	py_object)selfr   device_entryr`   s       r   __init__zMacOsHidDevice.__init__`  s   001I4PL + , , 001G1=?D & ' '	,'D ""4#5#5q9F$$K%vf~/ / kkmDO D ''/?.2W6D"D ';1'3D# **CDD';2(4D$ ++DEE $^^d.M.MMPD	00'' )+r   c                     | j                   S r{   )r   r   s    r   GetInReportDataLengthz$MacOsHidDevice.GetInReportDataLength  s    ***r   c                     | j                   S r   )r   r   s    r   GetOutReportDataLengthz%MacOsHidDevice.GetOutReportDataLength  s    +++r   c                     d}t        j                  | j                  z         }|dd |dd t        j	                  | j
                  t        ||| j                        }|t        k7  rt        j                  d      y)r{   r   Nz Failed to write report to device)
r;   r   r   r4   IOHIDDeviceSetReportrY   K_IO_HID_REPORT_TYPE_OUTPUTr   r   r9   )r   packetrc   out_report_bufferr`   s        r   WritezMacOsHidDevice.Write  s{    I$*J*JJM!!9a''(:(:(C(1(9(,(H(H	JF $$@AA %r   c                     d}| 	 | j                   j                  d      }| |S # t        j                  $ r Y 9w xY w)r{   N<   )timeout)r_   getr   Empty)r   r`   s     r   ReadzMacOsHidDevice.Read  sP     F
.	__(((4F . M {{ 		s   ' ==c                 .   t        | d      r7t        j                  | j                  | j                  | j
                  d d        t        | d      rt        j                  | j                         t        | d      r| j                  j                          y y )Nr   rk   r   )hasattrr4   r   rY   r   r   r.   CFRunLoopStoprk   r   joinr   s    r   __del__zMacOsHidDevice.__del__  s    t'(44!!++	 t^$
**+ t]# $r   N)r   r   r   __doc__staticmethodr   r   r   r   r   r   r   r   r   r   ry   ry   3  s<    
 $ $L4+l+,B 
 r   ry   )xr   	six.movesr   r   r;   ctypes.utilloggingsysr   pyu2fr   	pyu2f.hidr   	getLoggerrl   rV   rO   r   r   r   r   r   r   r   r   	Structurer   r   r   r   r    r"   r$   POINTER
CF_SET_REFrM   CF_TYPE_REFCF_RUN_LOOP_REFr<   CF_RUN_LOOP_RUN_RESULTCF_ALLOCATOR_REFc_ulong
CF_TYPE_IDc_longCF_INDEXc_doubleCF_TIME_INTERVALc_uint	IO_RETURNIO_HID_REPORT_TYPEIO_OBJECT_TMACH_PORT_Tc_char_pIO_STRING_TIO_SERVICE_TIO_REGISTRY_ENTRY_TIO_HID_MANAGER_REFr   	CFUNCTYPEr   c_void_pc_uint32r   IO_HID_REPORT_CALLBACKr>   rQ   r   rX   r   r   r   rs   rp   rq   cdllLoadLibraryutilfind_libraryr4   r.   platform
startswithin_dllro   r   restypeargtypesr/   c_intrP   CFStringGetLengthr7   r8   r=   r6   rj   argTypesrr   c_boolr   r|   r~   r}   r5   r   r   r   rn   rt   r   warningr2   rH   rS   r\   rh   r   rw   	HidDevicery   r   r   r   <module>r      s   K      
   			=	)  %( " * !, ' $2 !); &,@ )-B * * f  W G 7  7 
 V^^F#
y)fnnW% &.., !6>>,/ ^^
==?? MM	]] mmmmoo! #V^^M2 "FNN<0 )))$0@0@)*0//;M*0//*8&..*H*2	4   &  !      #$   	 8 8 AB[[V[[556FGH <<8$+2227NO #" *NFNN6??,KL")6"&+1??FOO+1??+<"'"(,,"$16??H$*OO$5" !)"#0/"%"..(M"..!+" &"",,&-",,#2" $&"!"8"$13C$*MM$3"  %0=% %7%"*4%',>+?%(04%%%-2D2=2?%%%.)4%&+<m*L%'9=%..67f..;0%..7 +>%',7+E%($5%!&6%E%"15%&&.3D3B3@3B%&&/ 48%((05F5D5B5D%((1 (1%$):<N)1)7)G)1)3%%
 	..'(;*",$! 2/B $DNW T^^ W r   