Re: [PATCH v2] platform/x86: ideapad-laptop: Report camera switch as SW_CAMERA_LENS_COVER

From: Rong Zhang

Date: Tue Sep 22 2026 - 14:50:15 EST


Hi Mark,

Thanks for your information.


于 2026年9月23日 GMT+08:00 01:32:41,Mark Pearson <mpearson-lenovo@xxxxxxxxx> 写道:
> Hi Rong
>
> On Tue, Sep 22, 2026, at 12:42 PM, Rong Zhang wrote:
> > Hi Mark,
> >
> > On Tue, 2026-09-22 at 23:58 +0800, Rong Zhang wrote:
> >> Hi Mark,
> >>
> >> On Tue, 2026-09-22 at 11:52 -0400, Mark Pearson wrote:

[...]

> >> > I'm way behind on my emails and trying to get through my inbox a bit...so apologies if I've missed subtleties as I skim read this a bit
> >> >
> >> > Reading the internal spec - there are some WMI calls I can see that return C status:
> >> > LENOVO_OTHER_METHOD (GUID dc2a8805-3a8c-41ba-a6f7-092e0089cd3b)
> >> > Get CV DSP Camera Shutter Status - Input ID 0x00200000 - returns 0 (closed) or 1 (open)
> >> > Get Normal Camera Shutter Status - Input ID 0x00201000 - returns 0 (closed) or 1 (open)
> >> >
> >> > I can't find the Utility GUIDs mentioned at all I'm afraid. Is the above useful?
> >>
> >> Thanks for the information. It's useful! I will cross-check with the DSL
> >> code of the correlated WMI method.
> >
> > I just checked a DSDT dump from 83JR [1], and it does implement
> > 0x00200000!
> >
> > In detail, LENOVO_CAPABILITY_DATA_00 exposes 0x00200000 as
> > valid+read+write conditionally, while LENOVO_OTHER_METHOD can be used to
> > get/set the camera shutter.
> >
> > Still, I have three questions. Could you kindly check the internal
> > specification and shed some light?
> >
> > What's the difference between "CV DSP Camera Shutter" and the "Normal"
> > one? I guess the former is a firmware switch while the latter is a
> > hardware switch, am I correct?
> >
> The Normal ID is new and was just added in the latest version of the spec.
> It's possible it is on a not-released platform yet.
> As a note - the 'Normal" entry is get only.

Got it. The latter being get-only really makes it sound like a hardware switch. But yeah, we will see when the relevant platform is released.

>
> Afraid my hooks into the Yoga and Legion team are still quite new and we're figuring out some of the pieces needed at the moment :)
> The WMI spec seems to cover a lot of different platforms that I've not had much experience with too.
>
> > The device does not implement LENOVO_CAPABILITY_DATA_01 at all. Is it
> > possible to determine its existence programmatically using
> > LENOVO_CAPABILITY_DATA_00? Missing the former is fatal in the current
> > lenovo-wmi-capdata and lenovo-wmi-other implementations, resulting in
> > both driver non-functional. We need a programmatic way to tolerate its
> > non-existence so that we can bind the two drivers via the component
> > framework in any case.
> >
> It should be under CAPABILITY DATA_00, at least from what I'm seeing (pasting a table in text....):
>
> CV DSP Camera Shutter
> uint32 IDs //0x00200000
> uint32 Capability // 7 :by project
> bit 2: 0: not support SetFeatureValue(), 1: support SetFeatureValue()
> bit 1: 0: not support GetFeatureValue(), 1: support GetFeatureValue()
> bit 0: 0: not support CV DSP Camera Shutter, 1: support CV DSP Camera Shutter
> uint32 DefaultValue // 0 : by project
>
> Normal Camera Shutter Status
> uint32 IDs //0x00201000
> uint32 Capability // 3 :by project
> bit 2: 0: not support SetFeatureValue(), 1: support SetFeatureValue()
> bit 1: 0: not support GetFeatureValue(), 1: support GetFeatureValue()
> bit 0: 0: not support Normal Camera Shutter Status, 1: support Normal Camera Shutter Status
> uint32 DefaultValue // 1 : by project

While the information is also useful, it seems that I didn't express the question well in the last reply. Sorry for causing the misunderstanding.

I was asking about:

Is it possible to determine the existence of LENOVO_CAPABILITY_DATA_*01* using *00*?

Full story:

The two drivers (wmi-capdata and wmi-other) make a strong assumption that both 00 and 01 must be present. Missing anyone causes the two drivers non-functional.

Some platforms stub 01. The two drivers still work properly on these platforms, as the WMI GUID of 01 is still there.

Some platforms don't support 01 at all, but somehow forgot to stub it. The two drivers become non-functional in this case. It's easy to fix as the WMI GUID of 01 is still there, too. I've sent a series to fix that (it hasn't received any review yet, hint hint ;-P), see https://lore.kernel.org/all/20260914-lwmi-wmi-new-api-v1-0-7a400f2f69f8@xxxxxxxx/

Not until the last reply did I realize that 01 could be completely missing. Unfortunately, it becomes very tricky as the use of wmi_has_guid() is strongly discouraged, so we need to figure out an approach to determine the existence of 01 using other capability data, e.g. 00.

>
> > There is an WMI query in the DSDT dump that looks like
> > LENOVO_CAPABILITY_DATA_03. What is it?
> >
> No idea - my spec sheet doesn't have 03 defined.
> Scanning through my doc I'm not spotting anything that looks like a match for WQC either

Fine, it's not a big deal. I am just curious about how many capability data GUIDs have been defined.

Thanks,
Rong

>
> Mark
>
>
> > [1]: I never have such a device. I got the dump when fixing
> > https://bugzilla.kernel.org/show_bug.cgi?id=221065
> >
> > Appendix (DSDT snippet):
> >
> > Device (GZFD)
> > {
> > Name (_HID, "PNP0C14" /* Windows Management
> > Instrumentation Device */) // _HID: Hardware ID
> > Name (_UID, "GMZN") // _UID: Unique ID
> > [..]
> > /* This is LENOVO_OTHER_METHOD. */
> > Method (WMAE, 3, NotSerialized)
> > {
> > Local0 = Arg1
> > CreateDWordField (Arg2, Zero, SIDS)
> > CreateDWordField (Arg2, 0x04, SVAL)
> > [..]
> > If ((Arg1 == 0x11))
> > {
> > [..]
> > /* Get 0x00200000. */
> > If ((SIDS == 0x00200000))
> > {
> > Local0 = ^^PCI0.LPC0.EC0.DCSS /*
> > \_SB_.PCI0.LPC0.EC0_.DCSS */
> > Return (Local0)
> > }
> > [..]
> > }
> >
> > If ((Arg1 == 0x12))
> > {
> > [..]
> > /* Set 0x00200000. */
> > If ((SIDS == 0x00200000))
> > {
> > Local0 = ToInteger (SVAL)
> > ^^PCI0.LPC0.EC0.DCSS = Local0
> > Return (Zero)
> > }
> > }
> > [..]
> > }
> > /* The device has no LENOVO_CAPABILITY_DATA_01. */
> >
> > /* Is this something like LENOVO_CAPABILITY_DATA_03? */
> > Method (WQC3, 1, NotSerialized)
> > {
> > If ((Arg0 == Zero))
> > {
> > Return (Buffer (0x10)
> > {
> > /* 0000 */ 0x01, 0x00, 0x00, 0x00,
> > 0x01, 0x00, 0x00, 0x00, // ........
> > /* 0008 */ 0x10, 0x27, 0x00, 0x00,
> > 0xDC, 0x05, 0x00, 0x00 // .'......
> > })
> > }
> > }
> > [..]
> > /* This is LENOVO_CAPABILITY_DATA_00. */
> > Name (CPD0, Buffer (0x0C)
> > {
> > 0x00
> > // .
> > })
> > CreateDWordField (CPD0, Zero, C0ID)
> > CreateDWordField (CPD0, 0x04, C0CP)
> > CreateDWordField (CPD0, 0x08, C0DV)
> > Method (WQC0, 1, NotSerialized)
> > {
> > If ((Arg0 == Zero))
> > {
> > Return (Buffer (0x0C)
> > {
> > /* 0000 */ 0x00, 0x00, 0x05, 0x04,
> > 0x07, 0x00, 0x00, 0x00, // ........
> > /* 0008 */ 0x00, 0x00, 0x00, 0x00
> > // ....
> > })
> > }
> >
> > If ((Arg0 == One))
> > {
> > /* 0x00200000 is exposed conditionally. */
> > C0ID = 0x00200000
> > C0DV = Zero
> > If ((^^PCI0.LPC0.EC0.CVSP == One))
> > {
> > C0CP = 0x07
> > }
> > Else
> > {
> > C0CP = Zero
> > }
> > }
> >
> > Return (CPD0) /* \_SB_.GZFD.CPD0 */
> > }
> > [..]
> > }
> >
> > Thanks,
> > Rong
> >
> >>
> >> >
> >> > When I get a chance I'll check this out on a Legion platform I have that has this switch and confirm....but it might take a little while.
> >>
> >> Take your time and don't worry :-)
> >>
> >> Thanks,
> >> Rong
> >>
> >> >
> >> > Mark