+
     vi   c                   s    R t ^ RIt^ RIt^ RIHt ^ RIHt ^ RIHt ]P                  ! ]
4      t^t^tR. ROR. ROR. ROR. ROR	. RO/t^At ! R
 R]4      t ! R R]4      tR tR# )aq  liquidctl drivers for Lian Li Uni hubs.

Supported devices:

- Lian Li Uni SL
- Lian Li Uni SL v2
- Lian Li Uni AL
- Lian Li Uni AL v2
- Lian Li Uni SL-Infinity

Acknowledgements:

- EightB1ts for finding IDs, PWM Commands and speed byte calculation
  https://github.com/EightB1ts/uni-sync

Copyright BlafKing and contributors
SPDX-License-Identifier: GPL-3.0-or-later
N)Enum)UsbHidDriver)clampSLALSLISLV2ALV2c                   s    ] tR t^-tRtRtRtR# )ChannelModeZautoZfixed N)__name__
__module____qualname____firstlineno__AUTOFIXED__static_attributes__r	       @/usr/lib/python3.14/site-packages/liquidctl/driver/lianli_uni.pyr   r   -   s    DEr   r   c                   s   a a ] tR t^2t oRtRRRRR/3RRRRR/3RRR	RR
/3RRRRR/3RRRRR/3RRRRR/3RRRRR/3.tV 3R ltR tR tR t	R t
R tR tRtVtV ;t# )	LianLiUniz'Driver for Lian Li Uni fan controllers.i  iPw  zLian Li Uni SLdevice_typer   i   i  zLian Li Uni ALr   i  zLian Li Uni SL-Infinityr   i  zLian Li Uni SL V2r   i  zLian Li Uni AL V2r   i  c                s   < \         SV `  ! W3/ VB  VP                  R4      V n        V P                  '       g(   Q R\	        V P
                  P                  4       24       hRV n        R# )z"Initialize the Lian Li Uni driver.r   zunexpected device with PID TN)Zsuper__init__getr   ZhexdeviceZ
product_idsupports_cooling)selfr   Zdescriptionkwargs	__class__s   &&&,r   r   ZLianLiUni.__init__?   s]    77!::m4\#>s4;;CYCY?Z>[!\\ $r   c                s    \        \        \        ^,           4       F9  pV P                  V\        P
                  4       \        P                  ! R4       K;  	  R# )zEInitialize the device and enable PWM synchronization on all channels.g?N)range_MIN_CHANNEL_MAX_CHANNELset_fan_control_moder   r   timesleep)r   r   channels   &, r   
initializeZLianLiUni.initializeF   s@     \<!+;<G%%g{/?/?@JJsO = r   c                s    . p\        \        \        ^,           4       F;  pV P                  V4      pVf   ^ pVP	                  RV R2\        V4      R34       K=  	  V# )zHReturns queried speed from controller,
if nothing is returned, returns 0zFan z speedZrpm)r   r   r   _query_current_speedZappendint)r   r   Zstatusr"   Zcurrent_speeds   &,   r   
get_statusZLianLiUni.get_statusP   sb     \<!+;<G 55g>M$ !MMT'&13}3EuMN	 = r   c                sV   \        V4      pV\        P                  J d   Rp^V^,
          ,          pMRp^V^,
          ,          p\        P	                  V P
                  4      pV'       g   Q hWT.,           p\        P                  RW1V4       V P                  P                  V4       R# )u  Toggles or explicitly sets PWM synchronization for manual speed control.

Unstable

Parameters:
    channel: str or (unstable) int - channel name or number ([fan]1–4);
    desired_state: ChannelMode - set AUTO to enable Auto PWM mode, FIXED to set be able to set fixed/manual speed.
ZenablingZ	disablingz&%s PWM sync for channel %d: command %sN)
_parse_channelr   r   _PWM_COMMANDSr   r   _LOGGERdebugr   write)r   r"   Zdesired_stateZdebug_stringZchannel_byteZcommand_prefixcommands   &&&    r   r   ZLianLiUni.set_fan_control_mode]   s     !)K,,,%LGaK0L&LGaK0L '**4+;+;<~ >1>W^_'"r   c                s@   \        V4      p\        V^ ^d4      pV P                  V\        P                  4       V P                  V4      p^V^,           ^ V.p\        P                  RW4       V P                  P                  V4       \        P                  ! R4       R# )u   Set a fixed speed for the specified channel.

Parameters:
    channel: str or (unstable) int - channel name or number ([fan]1–4);
    duty: int - the desired speed percentage (0-100).
zsetting fan%d PWM duty to %d%%g?N)r'   r   r   r   r   _calculate_speed_byter)   Zinfor   r+   r    r!   )r   r"   Zdutyr   
speed_byter,   s   &&&,  r   set_fixed_speedZLianLiUni.set_fixed_speedx   s     !)T1c"!!';+<+<=//5
"a45wE'"

3r   c                s   \         Tu;8:  d   \        8:  g   Q h Q hV P                  R9   d   ^pM,V P                  R	9   d   ^pM\        RV P                   24      hV P                  P                  ^^A4      pW!^,
          ^,          ,           p\        P                  RV4       W4V^,            p\        V4      ^8  d   \        RV RV 24      h\        P                  VRR7      p\        P                  RVVV4       V# )
u  
Query the actual fan speed from the device for a given channel by reading the
controller's input report.

For device types:
  - 'SL', 'AL', 'SLI': speed data begins at offset 1.
  - 'SLV2', 'ALV2': speed data begins at offset 2.

Each channel's speed occupies 2 bytes and is the current RPM

Parameters:
    channel (int): channel number (1–4).

Returns:
    int: The fan speed value as reported by the device, or raises an Assert if the read fails.
z+unsupported device type for reading speed: zstart_index: %sz report is too short for channel z: Zbig)Z	byteorderz0channel %d: extracted bytes %s -> speed value %d)r   r   r   r   r   )r   r   r   AssertionErrorr   Zget_input_reportr)   r*   Zlenr%   Z
from_bytes)r   r"   ZoffsetZreportZstart_indexZspeed_bytesZspeed_values   &&     r   r$   ZLianLiUni._query_current_speed   s    " w6,66666 22F!11F #NtO_O_N`!abb--c26 !q00'5;?;{a #CG9Bvh!WXXnn[EnB>		
 r   c                s   V P                   R9   d4   V^ 8X  d   ^(# \        R^V,          ,           ^,          4      ^,          p V# V P                   R8X  d4   V^ 8X  d   ^
# \        ^RV,          ,           ^,          4      ^,          p V# V P                   R9   d4   V^ 8X  d   ^# \        ^^V,          ,           ^,          4      ^,          p V# \        RV P                    24      h)zCalculate the speed byte based on the device type and desired speed.

Parameters:
    speed: int - The desired speed percentage (0-100)

Returns:
    int - The calculated speed byte to send to the device
i   r   g     1@zunsupported device type: )r   r   r0   )r   r%   r1   )r   Zspeedr.   s   && r   r-   ZLianLiUni._calculate_speed_byte   s     |+z #e"4!:;dB
  &z #"6"!<=D
  !11z #e"4!:;dB
  !#<T=M=M<N!OPPr   )r   r   )r
   r   r   r   __doc__Z_MATCHESr   r#   r&   r   r/   r$   r-   r   Z__classdictcell__Z__classcell__)r   Z__classdict__s   @@r   r   r   2   s     1 
)M4+@A	)M4+@A	)M4+@A	2]E4JK	,}f.EF	,}f.EF	,}f.EFH%#6$-^ r   r   c           	     s@   Rp\        V \        4      '       d3   V P                  R4      '       d   \        V P	                  R4      4      pM\        V \        4      '       d   T pVe   \
        Tu;8:  d   \        8:  g!   M \        RV : R\
         R\         R24      hV# )a  Parse a channel name-or-number spec into a channel number.

Note that passing channel numbers to the public driver APIs is an unstable feature, that may
very well be removed.

>>> _parse_channel("fan1")
1

>>> _parse_channel(1)
1

>>> _parse_channel("1")
Traceback (most recent call last):
    ...
ValueError: invalid channel '1', available channels are 'fan1'...'fan4'

>>> _parse_channel("fan5")
Traceback (most recent call last):
    ...
ValueError: invalid channel 'fan5', available channels are 'fan1'...'fan4'

>>> _parse_channel(5)
Traceback (most recent call last):
    ...
ValueError: invalid channel 5, available channels are 'fan1'...'fan4'
NZfanzinvalid channel z, available channels are 'fanz'...'fanZ')Z
isinstanceZstrZ
startswithr%   Zremoveprefixr   r   Z
ValueError)Zname_or_numberr"   s   & r   r'   r'      s    6 G.#&&>+D+DU+K+Kn11%89	NC	(	( |wF,F~0 1**6x~QP
 	

 Nr   )      i1   )r3   r4   iB   )r3   r4   ib   )r2   Zloggingr    Zenumr    Zliquidctl.driver.usbr   Zliquidctl.utilr   Z	getLoggerr
   r)   r   r   r(   Z_REPORT_LENGTHr   r   r'   r	   r   r   <module>r5      s   &    -  


H
%  	--	=
M
M $ 
a aH(r   