+
     vi԰  c                   s~   R t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHtH	t	 ]P                  R8X  d   ^ RIHt ^ RIHtHt ^ RIHtHt ^ RIHtHtHtHtHtHtHt ]P6                  ! ]4      t^@t^@t^t Rt!R	t"R
t#Rt$Rt%Rt&R. RHO^^d3/t'R. RHO^^d3R. RIO^ ^d3/t(R. RJO^^d3R. RKO^ ^d3/t)^;t*R^R^R^R^/t+R^/t,/ t-R^/t.R^R^/t// RRLbRRMbRRNbRRObRRPbRRQbRRRbRRSbRRTbRRUbRRVbRRWbR RXbR!RYbR"RZbR#R[bR$R\b/ R%R]bR&R^bR'R_bR(R`bR)RabR*RbbR+RcbR,RdbR-RebR.RfbR/RgbR0RhbR1RibR2RPbR3RQbR4RRbR5RSbCR6RTR7RUR8RZR9R[R:R\R;R]R<RcR=RdR>Re/	Ct0^^(^^^^^^(/t1^ ^2^ .^2^ .^2^ .^2^ .^2^ .3^^P^ .^<^ .^(^ .^^ .^
^ .3^^^^.^,^.^^ .^^ .^P^ .3^^@^.^^.^^.^ ^.^X^.3^^ ^.^^.^^.^^.^,^.3^^^ .^^ .^^ .^^ .^^ .3^^(^ .^^ .^^ .^
^ .^^ .3^^2^ .^(^ .^^ .^^ .^
^ .3^^^ .^^ .^^ .^^ .^^ .3^	^ ^ .^ ^ .^ ^ .^ ^ .^ ^ .3^
^7^ .^(^ .^^ .^
^ .^ ^ .3^^n^ .^S^ .^9^ .^.^ .^ ^ .3/t2R?^ R@^RA^RB^RC^/t3 ! RD RE]4      t4 ! RF RG]44      t5R# )ja8  liquidctl drivers for fourth-generation NZXT Kraken X liquid coolers.

Supported devices:

- NZXT Kraken X (X53, X63 and X73)
- NZXT Kraken Z (Z53, Z63 and Z73)
- NZXT Kraken 2023
- NZXT Kraken 2023 Elite

Copyright Tom Frey, Jonas Malaco, Shady Nawara and contributors
SPDX-License-Identifier: GPL-3.0-or-later
N)ImageImageSequencewin32)WinUsbPy)PyUsbDeviceUsbHidDriver)NotSupportedByDeviceNotSupportedByDriver)LazyHexReprnormalize_profileinterpolate_profileclampHue2AccessoryHUE2_MAX_ACCESSORIES_IN_CHANNELmap_directioni _  zLiquid temperaturez
Pump speedz	Pump dutyz	Fan speedzFan dutyZpumpZfanZexternalZringZlogoZsyncZoffZfixedfadingsuper-fixedzspectrum-wavez	marquee-3z	marquee-4z	marquee-5z	marquee-6zcovering-marqueezalternating-3zalternating-4zalternating-5zalternating-6zmoving-alternating-3zmoving-alternating-4zmoving-alternating-5zmoving-alternating-6pulse	breathingsuper-breathingZcandlestarry-nightzrainbow-flowzsuper-rainbowzrainbow-pulseloadingtai-chiwater-coolerwingszbackwards-spectrum-wavezbackwards-marquee-3zbackwards-marquee-4zbackwards-marquee-5zbackwards-marquee-6zcovering-backwards-marqueezbackwards-moving-alternating-3zbackwards-moving-alternating-4zbackwards-moving-alternating-5zbackwards-moving-alternating-6zbackwards-rainbow-flowzbackwards-super-rainbowzbackwards-rainbow-pulseZslowestZslowernormalZfasterZfastestc            
       s   a a ] tR t^t oRtRRRR]R]R]/3RRRR]R]R]/3.tV 3R	 lt	RR
 lt
R tR tR tR tRR ltRR ltR tRR ltR tR tRR ltR tR tR tR tR tRtVtV ;t# )KrakenX3z)Fourth-generation Kraken X liquid cooler.q  i   zNZXT Kraken X (X53, X63 or X73)speed_channelscolor_channelshwmon_ctrl_mappingi   c                sX   < \         SV `  W4       W0n        W@n        WPn        R V n        R # N)super__init___speed_channels_color_channels_hwmon_ctrl_mapping_fw)selfdevicedescriptionr   r   r   kwargs	__class__s   &&&&&&,=/usr/lib/python3.14/site-packages/liquidctl/driver/kraken3.pyr!   ZKrakenX3.__init__   s+     	---#5     c           	     s$   V P                   P                  4        V P                  ^^.4       V P                  ^ ^.4       V P                  '       d4   V'       g,   \        P                  RV P                  P                  4       MnV P                  '       d+   \        P                  RV P                  P                  4       R ! R4      pV P                  ^p^^^V.4       V P                  ^p^.4       . V n        V P                  RV P                  RV P                  /4       V P                  P                  RV P                  ^ ,           RV P                  ^,           RV P                  ^,           2R	34       \        V P                  4      # )
  Initialize the device and the driver.

This method should be called every time the systems boots, resumes from
a suspended state, or if the device has just been (re)connected.  In
those scenarios, no other method, except `connect()` or `disconnect()`,
should be called until the device and driver has been (re-)initialized.

Returns None or a list of `(property, value, unit)` tuples, similarly
to `get_status()`.
=bound to %s kernel driver, assuming it is already initialized2forcing re-initialization despite %s kernel driverc                 B    ^\        V R,
          R,          4      ,           #          ?g      ?ZroundZsecs   &r+   <lambda>Z%KrakenX3.initialize.<locals>.<lambda>   s    AtczT6I0J,Jr,   r3         !Firmware version. )r'   clear_enqueued_reports_write_hwmon_LOGGERinfodriverwarning_status_read_untilparse_firm_infoparse_led_infoappendr%   sortedr&   direct_accessr)   Zupdate_interval   &&, r+   
initializeZKrakenX3.initialize   s;    	**,T4L!T4L! ;;;}LLOQUQ\Q\QcQc {{{H$++J\J\  KCPOKKtT4ABKKt%+t';';[$J]J]^_/DHHQK=$((1+aPTPXPXYZP[}1]_abcdll##r,   c                sD    V^,          V^,          V^,          3V n         R# )   N)r%   r&   msg   &&r+   rF   ZKrakenX3.parse_firm_info   s    Is4y#d)4r,   c                s  a S^,          pV3R lp\        \        4       F>  pV! ^ V4      pV'       g    M,V P                  P                  RV^,            2VR34       K@  	  \	        V P
                  4      ^8  d   V! ^^ 4      \        P                  8H  pV! ^^ 4      \        P                  8H  pV P                  P                  RV'       d   RMRR34       V P                  P                  RV'       d   RMRR34       R# R# )	   c                 st   < ^pSW \         ,          ,           V,           ,          pV'       d   \        V4      # R# )   N)r   r   )channel	accessoryZoffsetZacc_idrP   s   &&  r+   findZ%KrakenX3.parse_led_info.<locals>.find  s2    F,K"KKiWXF,2=(<<r,   zLED accessory r<   zPump Ring LEDsZdetectedZmissingzPump Logo LEDsN)	ranger   rD   rH   lenr#   r   ZKRAKENX_GEN4_RINGZKRAKENX_GEN4_LOGO)r&   rP   Zchannel_countrV   irU   Z
found_ringZ
found_logos   &f      r+   rG   ZKrakenX3.parse_led_info  s    B
	=
 67AQ
ILL>!a%!99b IJ	 8 t##$q(a}'F'FFJa}'F'FFJLL!1:QZ\^ _`LL!1:QZ\^ _`	 )r,   c                s   V P                   P                  4        V P                  4       pVR ,          ^^.8X  d@   \        P	                  R4       \        P	                  R4       \        P	                  R4       \
        V^,          V^,          ^
,          ,           R3\        V^,          ^,          V^,          ,          R3\        V^,          R3.# )rS   rN   N8unexpected temperature reading, possible firmware fault;1try resetting the device or updating the firmwarez7(see https://github.com/liquidctl/liquidctl/issues/172)   °Crpm%)r'   r=   _readr@   rC   _STATUS_TEMPERATURE_STATUS_PUMP_SPEED_STATUS_PUMP_DUTYrO      & r+   _get_status_directlyZKrakenX3._get_status_directly  s    **,jjlu:$%OOVWOOOPOOUV #b'CGbL"8%@RAB!7?B-
 	
r,   c                s   \         V P                  P                  R 4      R,          R3\        V P                  P                  R4      R3.pV P                  P	                  R4      '       dB   VP                  \        V P                  P                  R4      R,          ^,          R34       V# \        P                  RV P                  P                  4       V# )	temp1_inputMbP?r]   
fan1_inputr^   pwm1      Y@r_   z.pump duty cannot be read from %s kernel driver)
ra   r?   read_intrb   has_attributerH   rc   r@   rC   rB   )r&   Zstatus_readingsrd   r+   _get_status_from_hwmonZKrakenX3._get_status_from_hwmon'  s     $++"6"6}"E"LeT!5!5l!CUK

 ;;$$V,,"""DKK$8$8$@5$H3$NPST  OOLdkkN`N`ar,   c                sB   V P                   '       dC   V'       g;   \        P                  RV P                   P                  4       V P	                  4       # V P                   '       d+   \        P                  RV P                   P                  4       V P                  4       # )zJGet a status report.

Returns a list of `(property, value, unit)` tuples.
z4bound to %s kernel driver, reading status from hwmonz4directly reading the status despite %s kernel driver)r?   r@   rA   rB   rm   rC   re   )r&   rK   r)   s   &&,r+   
get_statusZKrakenX3.get_status7  so     ;;;}LLOQUQ\Q\QcQcd..00;;;OOFHZHZ ((**r,   c                sh   \        V P                  4      ^ 8X  d   \        4       hRV9   d*   \        P	                  R4       VP                  RR4      pRpV P                  V,          p\        V,          w    rp
V UUUu. uF	  w  rqW.NK  	  pppp\        V4      V	8  d   \        RV RV	 R24      hV
^ 8X  d%   V'       d   \        P	                  R	V4       . RO.pM+\        V4      V
8  d   \        P	                  R
W*4       VRV
 p\        V,          pV P                  WrW>V4       R# u upppi )z*Set the color mode for a specific channel.Z	backwardsz2deprecated mode, move to direction=backward optionz
backwards-r<   Zbackwardznot enough colors for mode=z, at least z	 requiredz(too many colors for mode=%s, none neededz+too many colors for mode=%s, dropping to %dN    rp   rp   )
rX   r#   r   r@   rC   Zreplace_COLOR_MODESZ
ValueError_ANIMATION_SPEEDS_write_colors)r&   rT   modecolorsZspeed	directionr)   cid_	mincolors	maxcolorsZrZgZbsvals   &&&&&&,        r+   	set_colorZKrakenX3.set_colorH  s    t##$)&(($OOPQ<<b1D"I""7+(4T(:%1aI-34V	qa)V4v;":4&I;V_`aa!^ JDQ[F[9$OOI4[JY'F '3fI> 5s    D-c                s4   V P                   V,          p\        V4       F?  w  rEV^,          ^d,          pV P                  P                  RV RV^,            R2V4       KA  	  \        P
                  ! R4       V P                  P                  RV R2^4       R# )i   tempZ_auto_pointZ_pwmg?pwm_enableN)r$   	enumerater?   	write_inttimeZsleep)r&   rT   interpZhwmon_ctrl_channelZidxdutypwm_dutys   &&&    r+   _set_speed_profile_hwmonZ!KrakenX3._set_speed_profile_hwmond  s    !55g> #6*ICczS(HKK!!D);(<KayPT"UW_` + 	

3 	$6#7w?Cr,   c           	     sx   V P                   V,          w  rVp^r.V,           p\        V\        4      p	\        \	        ^\        ^,           4      4      p
V
 Uu. uF  p\        \        W4      Wg4      NK  	  pp\        W4       F  w  r\        P                  RWV4       K  	  V P                  '       d   RV P                  V,           R2pV P                  P                  V4      '       d   V'       dB   \        P                  RV P                  P                  4       V P                  W,           4      # \        P                  RV P                  P                  4       V P!                  W4      # V'       g+   \        P                  RV P                  P                  4       V P                  W,           4      # u upi )z(Set channel to use a speed duty profile.u;   setting %s PWM duty to %d%% for liquid temperature >= %d°Cr~   r   zCdirectly writing duty curve despite %s kernel driver having supportz6bound to %s kernel driver, writing duty curve to hwmonzerequired duty curve functionality is not available in %s kernel driver, falling back to direct access)r"   r	   _CRITICAL_TEMPERATURElistrW   r   r
   Zzipr@   rA   r?   r$   rl   rC   rB   r>   r   )r&   rT   ZprofilerK   r)   rw   dmindmaxheaderZnormZstdtempsZtr   r}   r   hwmon_pwm_enable_names   &&&&,           r+   set_speed_profileZKrakenX3.set_speed_profilew  sc    ..w74# *?@b"7!";<=KST8a%+D4dA8Th/JDLLMw^b 0
 ;;;&)$*B*B7*K)LG$T! {{(()>?? OO]**  ;;v77LdkkN`N` 44WEE"{KK&&
 {{6?++; Us   F7c                sN    V P                  V^ V3\        ^,
          V3.R4       R# )rp   TN)r   r   )r&   rT   r   s   &&&r+   _set_fixed_speed_directlyZ"KrakenX3._set_fixed_speed_directly  s*    w!T5JQ5NPT4U(VX\]r,   c                s    R V P                   V,           2pV R2pV^,          ^d,          pV P                  P                  W54       V P                  P                  V^4       R# )r~   r   N)r$   r?   r   )r&   rT   r   hwmon_pwm_namer   r      &&&   r+   _set_fixed_speed_hwmonZKrakenX3._set_fixed_speed_hwmon  sc    t77@AB#1"2' : #:$ 	n7 	3Q7r,   c                s\   V P                   '       Ed
   V P                  V,          w  rVp\        W&V4      pRV P                  V,           2pV P                   P	                  V4      '       d   V'       d<   \
        P                  RV P                   P                  4       V P                  W4      # \
        P                  RV P                   P                  4       V P                  W4      # V'       g+   \
        P                  RV P                   P                  4       V P                  W4      # )z"Set channel to a fixed speed duty.r~   zDdirectly writing fixed speed despite %s kernel driver having supportz7bound to %s kernel driver, writing fixed speed to hwmonz^required PWM functionality is not available in %s kernel driver, falling back to direct access)r?   r"   r   r$   rl   r@   rC   rB   r   rA   r   )	r&   rT   r   rK   r)   rx   r   r   r   s	   &&&&,    r+   set_fixed_speedZKrakenX3.set_fixed_speed  s     ;;; 009MATT*D"4#;#;G#D"EFN {{((88 OO^**  99'HHMt{{OaOa 227AA"tKK&&
 --g<<r,   c                sD    V P                   P                  \        4      pV# r   )r'   Zread_READ_LENGTHr&   datard   r+   r`   ZKrakenX3._read  s    {{-r,   c                s    \        \        4       FR  pV P                  4       p\        VR ,          4      pVP	                  VR4      pV'       d	   V! V4       V'       d   KQ   R# 	  R# :rp      NNrW   _MAX_READ_ATTEMPTSr`   bytesZpopr&   Zparsersrx   rP   ZprefixZfunc   &&    r+   rE   ZKrakenX3._read_until  sL    )*A**,C3s8_F;;vt,DS	7 +r,   c                s    ^ .\         \        V4      ,
          ,          pV P                  P                  W,           4       R# )rp   N)_WRITE_LENGTHrX   r'   write)r&   r   Zpadding   && r+   r>   ZKrakenX3._write  s+    %=3t945$.)r,   c                s   \         V,          w  rgrp
\        V4      pR V8X  g   RV8X  d   \        \        P                  ! V!  4      . ROW,
          ,          ,           p\
        V,          V,          pV P                  ^"^V^ .V,           4       V P                  ^"^V^ .4       V P                  ^"^V^ V.V,           . RO,           4       R# VR8X  Edj   V P                  ^"^V.4       V P                  ^"^V.4       / pV^ ,          ^,          V^ &   V^ ,           Uu. uF  p\        VR,          4      NK  	  upV^&   V^,           Uu. uF  p\        V^,          4      NK  	  upV^&   ^ .^,          V^&   \
        V,          V,          p\        ^4       F  pVR9   d   ^M^pV^,          ^ 8X  d   ^^.M^^.p^"^ VV^.V,           V.,           ^ .^,          ,           ^.,           V,           ^ .^
,          ,           pV P                  VVV^,          ,          ,           4       K  	  V P                  ^"^V^.4       R# ^*^.pW.p\
        V,          V,          pVV,           V.,           V,           p\        \        P                  ! V!  4      . RO^V,
          ,          ,           pRV9   d   ^pMVR8X  g   RV9   d   ^pM^ pV\        V^ ^4      ,          pVR8X  g   VR8X  g   VR	8X  d   ^pM"VR
8X  d   ^pMVR8X  d   ^p^pMVR8X  d   ^pM^ p\        V,          pV^8X  g   V^8X  d   TM^pVVVVV.pV P                  VV,           V,           4       R# u upi u upi )r   r   r   g      @Zmarqueer   zmoving-alternatingr   r   r   r   r   r   Nro   )	   rp   rp   i   rp   2   rp   rp   r2   )      )rq   rX   r   	itertoolsZchain_SPEED_VALUEr>   intrW   r   _STATIC_VALUE)r&   rw   rt   ru   r{   rv   ZmvalZsize_variantZspeed_scalery   rz   Zcolor_countZcolorZspeed_valueZcolor_listsZxrY   ZmodZaltrP   ZopcodeZaddressr   Zbackward_byteZmode_relatedZstatic_byteZled_sizeZfooters   &&&&&&                      r+   rs   ZKrakenX3._write_colors  sM   @LT@R=KI&kD $5$=&125G9Kb5ccE&{3D9KKKtS$/%78KKtS$/0KKtS$-HI W_KKtS)*KKtS)*K#AY]KN5@^D^c!s(m^DKN3>q>B>ac!q&k>BKN"VaZKN&{3D9K1X6kdt&'1fktTld|4a.!"e fqj! f	
  frk"  C+a!e"445  KKtS$/0 D\FjG&{3D9Kg%.<F&12Y"{BR5SSED  $'+?4+G $ $]9a>>Mx47?dk6I#"#'#""##',K'+t|tt||H#[,XVFKK/0g EBs   MMc                s    \        4       h)zNot supported by this device.)r   )r&   rT   rt   valuer)   s   &&&&,r+   
set_screenZKrakenX3.set_screen(  s    "$$r,   )r#   r%   r$   r"   rD   F)r   Zforward)__name__
__module____qualname____firstlineno____doc___SPEED_CHANNELS_KRAKENX_COLOR_CHANNELS_KRAKENX_HWMON_CTRL_MAPPING_KRAKENX_MATCHESr!   rM   rF   rG   re   rm   rn   r|   r   r   r   r   r   r`   rE   r>   rs   r   __static_attributes____classdictcell____classcell__r*   Z__classdict__   @@r+   r   r      s     3 - "9 "9$&A			
 - "9 "9$&A			
H.#$J5X0
 +"?8D&$,L^8=>	b*G1R% %r,   r   c                   sf  a a ] tR tRt oRtRRRR]R]R]R	R
RR-/3RRRR]R]	R]R	R.RR//3RRRR]R]	R]R	R.RR0/3RRRR]R]	R]R	R.RR//3RRRR]R]	R]R	R.RR0/3.t
V 3R ltR tR1R ltR2R ltR tR tR tR tR tR tR tR tR  tR! tR" tR# tR$ tR% tR& tR' tR( tR) t R3R* lt!R+ t"R,t#Vt$V ;t%# )4KrakenZ3i-  z)Fourth-generation Kraken Z liquid cooler.r   i0  zNZXT Kraken Z (Z53, Z63 or Z73)r   r   r   bulk_buffer_sizei   lcd_resolutioni0  zNZXT Kraken 2023 Elite (broken)0  zNZXT Kraken 2023i0  zNZXT Kraken 2024 Elite RGBi0  zNZXT Kraken 2024 Plusc                s$  <a  \         S	S `  ! WW43/ VB  \        P                  R 8X  d[   \	        4       S n        S P                  VP                  VP                  S P                  P                  4      pV'       g   RS n        Mp\        V 3R l\        P                  ! S P                  S P                  4       4       R4      S n        S P
                  '       d   S P
                  P                  4        VS n        VS n        ^ S n        ^2S n        R# )r   Nc              3   sv   <"   T F.  pVP                   SP                  P                   8X  g   K*  Vx  K0  	  R # 5ir   )serial_numberr'   )Z.0Zhandler&   s   & r+   Z	<genexpr>Z$KrakenZ3.__init__.<locals>.<genexpr>  s2      "X++t{{/H/HH F"Xs   '9
9)r    r!   sysplatformr   bulk_device_find_winusb_deviceZ	vendor_id
product_idr'   r   nextr   r   openr   r   orientation
brightness)
r&   r'   r(   r   r   r   r   r)   Zfound_devicer*   s
   f&&&&&&, r+   r!   ZKrakenZ3.__init__o  s     	nWPVW<<7"'zD33  &"3"3T[[5N5NL  #' #"-"7"7"X
  D   %%' 0,r,   c                sn   V P                   P                  R R R R7      pV F  pVP                  P                  RP	                  W4      4      R8w  g   K4  VP
                  '       g   KH  VP
                  P                  V4      R8w  g   Kj  V P                   P                  VP                  4        R # 	  R# )T)ZdeviceinterfaceZpresentZ
findparentzvid_{:x}&pid_{:x}F)r   Zlist_usb_devicespathrV   formatZparentZinit_winusb_device_with_path)r&   ZvidZpidZserialZwinusb_devicesr'   s   &&&&  r+   r   ZKrakenZ3._find_winusb_device  s    )):: $4 ; 
 %F  !4!;!;C!EF"LMMMMM&&v."4  ==fkkJ % r,   c                s    V P                   e   R # V'       d   V P                  P                  4        V P                  ^^.4       V P	                  RV P
                  /4       R # )Nr8   )r%   r'   r=   r>   rE   rF   )r&   clear_reportsrQ   r+   _get_fw_versionZKrakenZ3._get_fw_version  sK    88KK..0T4L!+t';';<=r,   c           	     s   V P                   P                  4        V P                  '       d4   V'       g,   \        P	                  RV P                  P
                  4       M<V P                  '       d+   \        P                  RV P                  P
                  4       R ! R4      pV P                  ^p^^^V.4       V P                  ^p^.4       . V n        V P                  RR7       V P                  P                  RV P                  ^ ,           RV P                  ^,           RV P                  ^,           2R	34       V P                  ^0^.4       V P                  R
V P                  /4       \        V P                  4      ^ 8  d1   V P                  ^ ^.4       V P                  RV P                   /4       \#        V P                  4      # )r-   r.   r/   c                 r0   r1   r4   r5   r6   r+   r7   Z%KrakenZ3.initialize.<locals>.<lambda>  s    E4#:2E,F(Fr,   r3   F)r   r:   r;   r<      1r9   )r'   r=   r?   r@   rA   rB   rC   r>   rD   r   rH   r%   rE   parse_lcd_inforX   r#   rG   rI   rJ   rL   r+   rM   ZKrakenZ3.initialize  sp    	**, ;;;}LLOQUQ\Q\QcQc {{{H$++J\J\ GLT4t_=>T4L! 	51/DHHQK=$((1+aPTPXPXYZP[}1]_abcT4L!+t':':;<t##$q(KKt%k4+>+>?@dll##r,   c                s    V^,          V n         V^,          V n        V P                  P                  RV P                   R34       V P                  P                  RV P                  ^Z,          R34       R# )   zLCD Brightnessr_   zLCD Orientationt   °N)r   r   rD   rH   rO   rQ   r+   r   ZKrakenZ3.parse_lcd_info  s\    d)t9-tDE.0@0@20EtLMr,   c                s   V P                   P                  4        V P                  ^t^.4       V P                  4       pVR,          ^^.8X  d+   \        P                  R4       \        P                  R4       \        V^,          V^,          ^
,          ,           R3\        V^,          ^,          V^,          ,          R3\        V^,          R3\        V^,          ^,          V^,          ,          R3\        V^,          R3.# )it   rZ   r[   r\   r]   r^   r_   )r'   r=   r>   r`   r@   rC   ra   rb   rc   _STATUS_FAN_SPEED_STATUS_FAN_DUTYrO   rd   r+   re   ZKrakenZ3._get_status_directly  s    **,T4L!jjlu:$%OOVWOOOP #b'CGbL"8%@RAB!7?B-B1s2w 6>s2w,
 	
r,   c                s   \         V P                  P                  R 4      R,          R3\        V P                  P                  R4      R3\        V P                  P                  R4      R,          ^,          R3\
        V P                  P                  R4      R3\        V P                  P                  R	4      R,          ^,          R3.# )
rf   rg   r]   rh   r^   ri   rj   r_   Z
fan2_inputZpwm2)ra   r?   rk   rb   rc   r   r   )r&   r6   r+   rm   ZKrakenZ3._get_status_from_hwmon  s     $++"6"6}"E"LeT!5!5l!CUK 4 4V <u Ds JCP 4 4\ BEJt{{33F;eCcI3O
 	
r,   c                s    \        \        4       FT  pV P                  4       p\        VR ,          4      pVP	                  VR4      pV'       d   V! V4      u # V'       d   KS   R# 	  R# r   r   r   r   r+   _read_until_first_matchZ KrakenZ3._read_until_first_match  sO    )*A**,C3s8_F;;vt,DCy 7 +r,   c                sD    V P                  V4       V P                  4       # r   )r>   r`   r   rQ   r+   _write_then_readZKrakenZ3._write_then_read  s    Dzz|r,   c                s    \         P                  R 8X  d5   \        P                  R\	        V4      \        V4      4       \        V4      pV P                  P                  ^V4       R# )r   zwriting %d bytes: %rN)	r   r   r@   ZdebugrX   r   r   r   r   r   rQ   r+   _bulk_writeZKrakenZ3._bulk_write  sG    <<7"MM0#d)[=NO;DsD)r,   c                s  a  VR8w  d   S P                  ^0^.4       V 3R lpV 3R lpS P                  RV/4       VR8X  d1   \        V4      pS P                  ^0^^V^ ^ ^S P                  .4       R# VR8X  dA   \        V4      pS P                  ^0^^S P                  ^ ^ ^\        V^Z,          4      .4       R# VR8X  Ed   V! 4       '       d   S P                  VS P                  4      pS P                  V. RO\        \        V4      P                  ^R	4      4      ,           4       S P                  V. RO\        \        V4      P                  ^R	4      4      ,           4       R# S P                  VS P                  4      pS P                  V. RO\        \        V4      P                  ^R	4      4      ,           4       R# VR
8X  dt   V! 4       '       d   \        R4      hS P                  VS P                  4      pS P                  V. RO\        \        V4      P                  ^R	4      4      ,           4       R# VR8X  d   S P                  ^ ^4       R# S P                  '       dY   VR8X  g   VR
8X  dK   \         P"                  R8X  d   S P                  P%                  4        MS P                  P'                  4        \)        R4      h)u`  Set the screen mode and content.

Unstable.

Supported channels, modes and values:

| Channel | Mode | Value |
| --- | --- | --- |
| `lcd` | `liquid` | — |
| `lcd` | `brightness` | int between `0` and `100` (%) |
| `lcd` | `orientation` | `0`, `90`, `180` or `270` (°) |
| `lcd` | `static` | path to image |
| `lcd` | `gif` | path to animated GIF |
Zliquidc                 s@   < V ^,          Sn         V ^,          Sn        R# )r   N)r   r   )rP   r&   s   &r+   r   Z+KrakenZ3.set_screen.<locals>.parse_lcd_info$  s    !$iDO"4yDr,   c                  s   < SP                   P                  p V R 8X  d'   SP                  4        SP                  ^ ,          ^8H  # R# )r   F)r'   r   r   r%   )Zdevice_product_idr&   s    r+   _is_2023_fw_version2Z1KrakenZ3.set_screen.<locals>._is_2023_fw_version2(  s=     $ 6 6 F*$$&xx{a''r,   r   r   Nr   ZstaticlittleZgifzEgif images are not supported on firmware 2.X.Y, please see issue #631r   zInvalid mode)   rp   rp   rp   )r   rp   rp   rp   )r2   rp   rp   rp   )r>   rE   r   r   r   _prepare_static_file_rgb16_send_2023_data_fw2r   rX   to_bytes_prepare_static_file
_send_datar   _prepare_gif_file_switch_bucketr   r   r   Zclose_winusb_deviceZreleaseZ	TypeError)	r&   rT   rt   r   r)   r   r   Z	value_intr   s	   f&&&,    r+   r   ZKrakenZ3.set_screen  si   & 8 	T4L!	)	 	+~67<E
IKKtT9c3TEUEUVW]"E
I KKtT4??Cc3y[]~K^_`X#%%66ud>N>NO((/$s4y7I7I!X7V2WW ((/$s4y7I7I!X7V2WW  008H8HI&;d3t9CUCUVWYaCb>c&cdU]#%%*[  ))%1A1ABD OOD"7$s4y?Q?QRSU]?^:_"_`X1% !1TU]||w&  446  ((*''r,   c                s   \         P                  ! V4      P                  V P                  4      P	                  VR,          4      P                  R4      P                  4       p. p^ p\        ^ \        V4      4       Fn  pVP                  W5,          ^ ,          4       VP                  W5,          ^,          4       VP                  W5,          ^,          4       VP                  ^ 4       Kp  	  V# z~
path is the path to any image file
Rotation is expected as 0 = no rotation, 1 = 90 degrees, 2 = 180 degrees, 3 = 270 degrees
ZRGB
r    r   resizer   rotateZconvertZgetdatarW   rX   rH   )r&   r   rotationr   resultpixelDataIndexr   r+   r   ZKrakenZ3._prepare_static_filee  s     JJtVD''(VHsN#WU^WY 	 #As4y1NMM$.q12MM$.q12MM$.q12MM!	 2
 r,   c                s&   \         P                  ! V4      P                  V P                  4      P	                  VR,          4      P                  R4      P                  4       p. p^ p\        ^ \        V4      4       F  pW5,          ^ ,          ^,	          pW5,          ^,          ^,	          pW5,          ^,          ^,	          pVP                  V^,          V^,	          ,           4       VP                  V^,          ^,          V,           4       K  	  V# r   r   )	r&   r   r   r   r   r   ZdrZdgZdbs	   &&&      r+   r   Z#KrakenZ3._prepare_static_file_rgb16z  s     JJtVD''(VHsN#WU^WY 	 #As4y1N%a(A-B%a(A-B%a(A-BMM27rQw/0MMBH?b01 2 r,   c           	     s>  a a \         P                  ! V4      p\        P                  ! V4      pVV 3R lpV! V4      p\	        V4      pVP
                  Vn        \        P                  ! 4       pVP                  VRRR\        V4      ^ R7       VP                  4       # )z
path is the path of the gif file
Rotation is expected as 0 = no rotation, 1 = 90 degrees, 2 = 180 degrees, 3 = 270 degrees
Gifs are resized to LCD resolution and rotated to match the desired orientation
result is a bytesIo stream
c              3   s   <"   V  FF  pVP                  4       P                  SP                  4      P                  SR,          4      pVx  KH  	  R# 5i)iZ   Nr   )Zcopyr   r   r   )framesZframeZresizedr   r&   s   &  r+   prepare_framesZ2KrakenZ3._prepare_gif_file.<locals>.prepare_frames  sA     **,--d.A.ABII(UX.Y  s   AAZGIFFT)r   Z	interlaceZsave_allZappend_imagesZloop)r    r   r   ZIteratorr   rA   ioZBytesIOZsaver   Zgetvalue)r&   r   r   Zimgr   r   Z
result_imgZresult_bytess   f&f     r+   r   ZKrakenZ3._prepare_gif_file  s     jj'',	
  '&\
((
zz|v, 	 	
 $$&&r,   c           	     s0   V P                  . RO4       . ROV,           pV P                  V4       \        ^ \        V4      V P                  4       F/  pV P                  \        WW@P                  ,            4      4       K1  	  V P                  ^6^.4       R# )z
This method is intended for Kraken 2023 firmware version 2.X.Y
sends image or gif to device
data is an array of bytes to write
bulk info contains info about the transfer
N)i6   r2   rp   r2   r   i   i   r2   i   i   i   i   i   iv   iT   r      )r   r   rW   rX   r   r   )r&   r   bulkInfor   rY   s   &&&  r+   r   ZKrakenZ3._send_2023_data_fw2  s     	<=
  	 q#d)T%:%:;AT$1/D/D+D"EFG < 	tTl+r,   c           	     s   V P                  ^6^.4       V P                  4       pV P                  V4      pT P                  VR8w  d   TM^ VR8H  4      p. ROV,           p\        P
                  ! \        V4      \        V4      ,           R,          4      p\        VP                  ^R4      4      pV P                  W4V4      pVR8X  d   V P                  4        ^ p^ ^ .pV P                  WD^,           W4      '       g   \        P                  R4       V P                  ^6^V.4       V P                  V4       \        ^ \        V4      V P                   4       F/  p	V P                  \        WWP                   ,            4      4       K1  	  V P#                  ^6^.4       V P%                  V4      '       g   \        P                  R4       R# R# )zl
sends image or gif to device
data is an array of bytes to write
bulk info contains info about the transfer
i   r   z(Failed to setup bucket for data transferzFailed to switch active bucketNr   r   )r   _query_buckets_find_next_unoccupied_bucket_prepare_bucketmathZceilrX   r   r   _get_bucket_memory_offset_delete_all_buckets_setup_bucketr@   Zerrorr   rW   r   r>   r   )
r&   r   r   bucketsbucketIndexr   dataSizeZdataSizeBytesZbucketMemoryStartrY   s
   &&&       r+   r   ZKrakenZ3._send_data  s    	tTl+%%'77
 **&",K![B5F


  99c&kCI5=>a*
 !::(
 "$$&K!$c
 !!+Q@QaaMMDEtT;78 q#d)T%:%:;AT$1/D/D+D"EFG < 	T4L!"";//MM:; 0r,   c                s^    / p\        ^4       F  pV P                  ^0^V.4      pW1V&   K  	  V# )a  
Queries all 16 buckets and stores their response
Response in structures as follow:
- standard part (14 bytes) - unknown
---- following is all 0x0 if bucket is unoccupied
- bucket index (1 byte)
- asset index (1 byte) - same as bucket index + 1
- 0x2 (1 byte) - unknown
- starting memory address (2 bytes) - address sometimes changes so must be read from here
- memory size (2 bytes) - size sometimes changes so must be read from here
- 0x1 (1 byte) - unknown
- 0x0|0x1 (1 byte) - most likely used/unused but could also be something else
)rW   r   )r&   r   bIresponses   &   r+   r   ZKrakenZ3._query_buckets  s<     )B,,dD"-=>H"BK  r,   c                sp    VP                  4        F!  w  r#\        VR,          4      '       d   K  Vu # 	  R# )z
finds the first available unoccupied bucket
buckets are unoccupied when bytes 14 onward are 0x0
returns -1 if unoccupied buckets are found
:rS   NNr   )ZitemsZany)r&   r   r   Z
bucketInfos   &&  r+   r   Z%KrakenZ3._find_next_unoccupied_bucket#  s3     (/}}#Kz#''"" (7 	r,   c                s   W,          p\         P                  V^,          V^,          .R4      p\         P                  V^,          V^,          .R4      pW68:  d   V^,          V^,          .# Tp^ pRp	V F  p
W,          p\         P                  V^,          V^,          .R4      pV\         P                  V^,          V^,          .R4      ,           pW8  d   TpW8  d   TpW8  d   WV,           8  g   W8  d   W8  g   W8X  g   K  W8w  g   K  Rp	K  	  V	'       g   V^,          V^,          .# W,           \        8  d   \        VP	                  ^R4      4      # W78  d   ^ ^ .# R# )aF  
returns the memory start address for the selected bucket
memory offset is calculated by first checking if the bucket can already
accommodate the new data, this avoids any additional calculations if uploading the same or smaller image
otherwise, we check if we can expand the current bucket without overlapping the memory space of any other bucket
otherwise, we set the offset after max utilized memory if there is space left on the device
otherwise, we check if there is space at the beginning of the memory space
finally, if all else fails then we clear the device and start over
r   FTr   )r   Z
from_bytes_LCD_TOTAL_MEMORYr   r   )r&   r   r   r   ZcurrentBucketZcurrentBucketOffsetZcurrentBucketSizeZminOccupiedByteZmaxOccupiedByteZexistingBucketWithinRanger   ZbucketZ	startByteZendBytes   &&&&          r+   r   Z"KrakenZ3._get_bucket_memory_offset.  si     ,!nnmB.?rAR-SU]^NNM",=}R?P+QS[\ (!"%}R'899 .$)!B[Fr
F2J'?JI#..&*fRj1I8"TTG(")*"+0YW_A_5_38K49J,0)   )!"%}R'899 %(9900H=>> %: 	r,   c                s    V P                  V4      pV'       g   V P                  V^,           R4      # V'       d   V P                  VR4      # V# )ze
if a bucket delete returns 0x9 then try next bucket
if bucket already had data then delete it twice
TF)_delete_bucketr   )r&   r   ZbucketFilledZdelete_response   &&& r+   r   ZKrakenZ3._prepare_bucketc  sJ     --k:''a>>++K??r,   c                sV    V P                  ^2^V.4       R pV P                  RV/4      # )z=
deletes bucket, returns true if successful, false otherwise
c                 s    V ^,          ^8H  # )rR    )rP   r6   r+   parse_delete_resultZ4KrakenZ3._delete_bucket.<locals>.parse_delete_resultw  s    r7c>!r,   s   3)r>   r   )r&   r   r   r   r+   r   ZKrakenZ3._delete_bucketq  s5     	T3,-	" ++[:M,NOOr,   c                sp    V P                  ^ ^4       \        ^4       F  pV P                  V4       K  	  R# )z2
Switches to liquid mode then deletes all buckets
N)r   rW   r   )r&   r   rd   r+   r   ZKrakenZ3._delete_all_buckets|  s0     	Aq!)B# r,   c                sB    V P                  ^8^W!.4      pV^,          ^8H  # )zE
switches active bucket, returns true if successful, false otherwise
r   )r&   r   rt   r   r   r+   r   ZKrakenZ3._switch_bucket  s*     (($T)GH|s""r,   c                s    V P                  ^2^VVV^ ,          V^,          V^ ,          V^,          ^.	4      pV^,          ^8H  # )zK
sets bucket for transmission, returns true if successful, false otherwise
r   )r&   ZstartBucketIndexZendBucketIndexZstartingMemoryAddressZ
memorySizer   s   &&&&& r+   r   ZKrakenZ3._setup_bucket  sW     (( %a(%a(11

 |s""r,   )rD   r   r   r   r   r   )@  r   i    )  r   )   r   )Tr   )   )&r   r   r   r   r   _SPEED_CHANNELS_KRAKENZ_COLOR_CHANNELS_KRAKENZ_HWMON_CTRL_MAPPING_KRAKENZ_SPEED_CHANNELS_KRAKEN2023_COLOR_CHANNELS_KRAKEN2023r   r!   r   r   rM   r   re   rm   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r+   r   r   -  s    3 - "9 "9$&A"C *		
 - "< "<$&A"O *		
  "< "<$&A"O *		
 ( "< "<$&A"O *		
 # "< "<$&A"O *		
c=H~#J>*$XN

	b*X(t*,'B,:?<B(	3j	P$## #r,   r   )r2   rp   rp   )r   rp   rp   )r2   r2   rp   )r   r2   r2   )rp   rp   rp   rp   rp   )rp   rp   rp   r2   r2   )r2   rp   r2   r2   r   )r2   r2   	   r2   (   )r   rp   r   rp   rp   )r   r   r   r2   r2   )r   r  r   r2   r2   )r      r   r2   r2   )r   r   r   r2   r2   )r  rp   r   r2   r   )r	  r   r   r2   r   )r	  r  r   r2   r   )r	  r	  r   r2   r   )r	  r   r   r2   r   )r	  r   r  r2   r   )r	  r  r  r2   r   )r	  r	  r  r2   r   )r	  r   r  r2   r   )r   rp   r	  r2   r   )r   rp   r   r2   r   )r   rp   i
   r2   r  )r   rp   rp   r2   r2   )r  rp   r	  r2   r2   )   rp   r   rp   rp   )i   rp   r   rp   rp   )i   rp   r   rp   rp   )r   rp   r   r2   r2   )rR   rp   r   r2   r   )rS   rp   r   r   r   )Nrp   r
  r2   r2   )6r   r   r   r   Zloggingr   r   ZPILr    r   r   Z	winusbcdcr   Zliquidctl.driver.usbr   r   Zliquidctl.errorr   r   Zliquidctl.utilr   r	   r
   r   r   r   r   Z	getLoggerr   r@   r   r   r   r   ra   rb   rc   r   r   r   r  r  r   r   r  r  r   r  rq   r   r   rr   r   r   r   r,   r+   <module>r     sR    	   
  $<<7" : F   

H
%  * !     _b#&  _b#&	OQ$  _b#&	OQ$ 
   &ufeVUFTYZ   
   %qk %q%3 -	 -"- #- )	-
 *- &- &- &- &- -- *- *- *- *- 1-  1!-" 1#-$ 1%-& "'-( &)-* .+-, #--. )/-0 )1-2 *3-4 *5-6 $7-8 $9-: );-< #=-@ 4A-B 0C-D 0E-F 0G-H 0 "7$&;$&;$&;$&;344Y-f 
2	1	1	2	 ttTlT4L4,tMttTlT4L4,tMttTlT4L4,tMttTlT4L4,tMttTlT4L4,tMttTlT4L4,tMttTlT4L4,tMttTlT4L4,tMttTlT4L4,tMttTlT4L4,tM$d|dD\D$<$N$d|dD\D$<$N  scccs v%| v%ro	#x o	#r,   