From a7d9b97c9460f65a726b727e9eaee31ea5016538 Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Wed, 5 Jan 2022 20:17:55 +0100 Subject: [PATCH] udisksata: Move the low-level PM state call (cherry picked from commit 4588dbeecd23c17d1cb7f7fa60afd56702acd455) --- doc/udisks2-sections.txt.daemon.sections.in | 2 + src/udisksata.c | 62 +++++++++++++++++++++ src/udisksata.h | 13 +++++ 3 files changed, 77 insertions(+) diff --git a/doc/udisks2-sections.txt.daemon.sections.in b/doc/udisks2-sections.txt.daemon.sections.in index 12935c4d..9a2bfa03 100644 --- a/doc/udisks2-sections.txt.daemon.sections.in +++ b/doc/udisks2-sections.txt.daemon.sections.in @@ -270,6 +270,8 @@ UDisksAtaCommandProtocol UDisksAtaCommandInput UDisksAtaCommandOutput udisks_ata_send_command_sync +udisks_ata_get_pm_state +UDISKS_ATA_PM_STATE_AWAKE
diff --git a/src/udisksata.c b/src/udisksata.c index 9491af5e..e6da8c35 100644 --- a/src/udisksata.c +++ b/src/udisksata.c @@ -308,3 +308,65 @@ udisks_ata_send_command_sync (gint fd, out: return ret; } + +/** + * udisks_ata_get_pm_state: + * @device: ATA drive block device path. + * @error: Return location for error. + * @pm_state: Return location for the current power state value. + * + * Get the current power mode state. + * + * The format of @pm_state is the result obtained from sending the + * ATA command `CHECK POWER MODE` to the drive. + * + * Known values include: + * - `0x00`: Device is in PM2: Standby state. + * - `0x40`: Device is in the PM0: Active state, the NV Cache power mode is enabled, and the spindle is spun down or spinning down. + * - `0x41`: Device is in the PM0: Active state, the NV Cache power mode is enabled, and the spindle is spun up or spinning up. + * - `0x80`: Device is in PM1: Idle state. + * - `0xff`: Device is in the PM0: Active state or PM1: Idle State. + * + * Typically user interfaces will report "Drive is spun down" if @pm_state is + * 0x00 and "Drive is spun up" otherwise. + * + * Returns: %TRUE if the operation succeeded, %FALSE if @error is set. + */ +gboolean +udisks_ata_get_pm_state (const gchar *device, GError **error, guchar *count) +{ + int fd; + gboolean rc = FALSE; + /* ATA8: 7.8 CHECK POWER MODE - E5h, Non-Data */ + UDisksAtaCommandInput input = {.command = 0xe5}; + UDisksAtaCommandOutput output = {0}; + + g_warn_if_fail (device != NULL); + + fd = open (device, O_RDONLY|O_NONBLOCK); + if (fd == -1) + { + g_set_error (error, UDISKS_ERROR, UDISKS_ERROR_FAILED, + "Error opening device file %s while getting PM state: %m", + device); + goto out; + } + + if (!udisks_ata_send_command_sync (fd, + -1, + UDISKS_ATA_COMMAND_PROTOCOL_NONE, + &input, + &output, + error)) + { + g_prefix_error (error, "Error sending ATA command CHECK POWER MODE: "); + goto out; + } + /* count field is used for the state, see ATA8: table 102 */ + *count = output.count; + rc = TRUE; + out: + if (fd != -1) + close (fd); + return rc; +} diff --git a/src/udisksata.h b/src/udisksata.h index 1d4918f1..d652f3ab 100644 --- a/src/udisksata.h +++ b/src/udisksata.h @@ -73,6 +73,16 @@ struct _UDisksAtaCommandOutput guchar *buffer; }; +/** + * UDISKS_ATA_PM_STATE_AWAKE: + * @pm_state: The power state value. + * + * Decodes the power state value as returned by #udisks_ata_get_pm_state. + * + * Returns: %TRUE when the drive is awake, %FALSE when sleeping. +*/ +#define UDISKS_ATA_PM_STATE_AWAKE(pm_state) (pm_state >= 0x41) + gboolean udisks_ata_send_command_sync (gint fd, gint timeout_msec, UDisksAtaCommandProtocol protocol, @@ -80,6 +90,9 @@ gboolean udisks_ata_send_command_sync (gint fd, UDisksAtaCommandOutput *output, GError **error); +gboolean udisks_ata_get_pm_state (const gchar *device, + GError **error, + guchar *count); G_END_DECLS -- 2.38.1