devices/sys/linux/
acpi.rs

1// Copyright 2022 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use base::error;
6use base::info;
7use base::AcpiNotifyEvent;
8use base::NetlinkGenericSocket;
9
10use crate::acpi::ACPIPMError;
11use crate::IrqLevelEvent;
12
13pub(crate) fn get_acpi_event_sock() -> Result<Option<NetlinkGenericSocket>, ACPIPMError> {
14    // Get group id corresponding to acpi_mc_group of acpi_event family
15    let nl_groups: u32;
16    match get_acpi_event_group() {
17        Some(group) if group > 0 => {
18            nl_groups = 1 << (group - 1);
19            info!("Listening on acpi_mc_group of acpi_event family");
20        }
21        _ => {
22            return Err(ACPIPMError::AcpiMcGroupError);
23        }
24    }
25
26    match NetlinkGenericSocket::new(nl_groups) {
27        Ok(acpi_sock) => Ok(Some(acpi_sock)),
28        Err(e) => Err(ACPIPMError::AcpiEventSockError(e)),
29    }
30}
31
32fn get_acpi_event_group() -> Option<u32> {
33    // Create netlink generic socket which will be used to query about given family name
34    let netlink_ctrl_sock = match NetlinkGenericSocket::new(0) {
35        Ok(sock) => sock,
36        Err(e) => {
37            error!("netlink generic socket creation error: {}", e);
38            return None;
39        }
40    };
41
42    let nlmsg_family_response = netlink_ctrl_sock
43        .family_name_query("acpi_event".to_string())
44        .unwrap();
45    nlmsg_family_response.get_multicast_group_id("acpi_mc_group".to_string())
46}
47
48pub(crate) fn acpi_event_run(
49    _sci_evt: &IrqLevelEvent,
50    acpi_event_sock: &Option<NetlinkGenericSocket>,
51) {
52    let acpi_event_sock = acpi_event_sock.as_ref().unwrap();
53    let nl_msg = match acpi_event_sock.recv() {
54        Ok(msg) => msg,
55        Err(e) => {
56            error!("recv returned with error {}", e);
57            return;
58        }
59    };
60
61    for netlink_message in nl_msg.iter() {
62        let _acpi_event = match AcpiNotifyEvent::new(netlink_message) {
63            Ok(evt) => evt,
64            Err(e) => {
65                error!("Received netlink message is not an acpi_event, error {}", e);
66                continue;
67            }
68        };
69    }
70}