1 /* 2 * Copyright (c) 2016-2021 Chuck Tuffli <chuck@tuffli.net> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 #ifndef _LIBSMART_H 17 #define _LIBSMART_H 18 19 #include <inttypes.h> 20 #include <stdbool.h> 21 22 /* 23 * libsmart uses a common model for SMART data (a.k.a. "attributes") across 24 * storage protocols. Each health value consists of: 25 * - The identifier of the log page containing this attribute 26 * - The attribute's identifier 27 * - A description of the attribute 28 * - A pointer to the raw data 29 * - The attribute's size in bytes 30 * 31 * This model most closely resembles SCSI's native representation, but it 32 * can represent ATA and NVMe with the following substitutions: 33 * - ATA : use the Command Feature field value for the log page ID 34 * - NVMe : use the field's starting byte offset for the attribute ID 35 * 36 * libsmart returns a "map" to the SMART/health data read from a device 37 * in the smart_map_t structure. The map consists of: 38 * - A variable-length array of attributes 39 * - The length of the array 40 * - The raw data read from the device 41 * 42 * Consumers of the map will typically iterate through the array of attributes 43 * to print or otherwise process the health data. 44 */ 45 46 /* 47 * A smart handle is an opaque reference to the device 48 */ 49 typedef void * smart_h; 50 51 typedef enum { 52 SMART_PROTO_AUTO, 53 SMART_PROTO_ATA, 54 SMART_PROTO_SCSI, 55 SMART_PROTO_NVME, 56 SMART_PROTO_MAX 57 } smart_protocol_e; 58 59 /* 60 * A smart buffer contains the raw data returned from the protocol-specific 61 * health command. 62 */ 63 typedef struct { 64 smart_protocol_e protocol; 65 void *b; // buffer of raw data 66 size_t bsize; // buffer size 67 uint32_t attr_count; // number of SMART attributes 68 } smart_buf_t; 69 70 struct smart_map_s; 71 72 /* 73 * A smart attribute is an individual health data element 74 */ 75 typedef struct smart_attr_s { 76 uint32_t page; 77 uint32_t id; 78 const char *description; /* human readable description */ 79 uint32_t bytes; 80 uint32_t flags; 81 #define SMART_ATTR_F_BE 0x00000001 /* Attribute is big-endian */ 82 #define SMART_ATTR_F_STR 0x00000002 /* Attribute is a string */ 83 #define SMART_ATTR_F_ALLOC 0x00000004 /* Attribute description dynamically allocated */ 84 void *raw; 85 struct smart_map_s *thresh; /* Threshold values (if any) */ 86 } smart_attr_t; 87 88 /* 89 * A smart map is the collection of health data elements from the device 90 */ 91 typedef struct smart_map_s { 92 smart_buf_t *sb; 93 uint32_t count; /* Number of attributes */ 94 smart_attr_t attr[]; /* Array of attributes */ 95 } smart_map_t; 96 97 #define SMART_OPEN_F_HEX 0x1 /* Print values in hexadecimal */ 98 #define SMART_OPEN_F_THRESH 0x2 /* Print threshold values */ 99 #define SMART_OPEN_F_DESCR 0x4 /* Print textual description */ 100 101 /* SMART attribute to match */ 102 typedef struct smart_match_s { 103 int32_t page; 104 int32_t id; 105 } smart_match_t; 106 107 /* List of SMART attribute(s) to match */ 108 typedef struct smart_matches_s { 109 uint32_t count; 110 smart_match_t m[]; 111 } smart_matches_t; 112 113 /** 114 * Connect to a device to read SMART data 115 * 116 * @param p The desired protocol or "auto" to automatically detect it 117 * @param devname The device name to open 118 * 119 * @return An opaque handle or NULL on failure 120 */ 121 smart_h smart_open(smart_protocol_e p, char *devname); 122 /** 123 * Close device connection 124 * 125 * @param handle The handle returned from smart_open() 126 * 127 * @return None 128 */ 129 void smart_close(smart_h); 130 /** 131 * Does the device support SMART/health data? 132 * 133 * @param handle The handle returned from smart_open() 134 * 135 * @return true / false 136 */ 137 bool smart_supported(smart_h); 138 /** 139 * Read SMART/health data from the device 140 * 141 * @param handle The handle returned from smart_open() 142 * 143 * @return a pointer to the SMART map or NULL on failure 144 */ 145 smart_map_t *smart_read(smart_h); 146 /** 147 * Free memory associated with the health data read from the device 148 * 149 * @param map Pointer returned from smart_read() 150 * 151 * @return None 152 */ 153 void smart_free(smart_map_t *); 154 /** 155 * Print health data matching the desired attributes 156 * 157 * @param handle The handle returned from smart_open() 158 * @param map Pointer returned from smart_read() 159 * @param which Pointer to attributes to match or NULL to match all 160 * @param flags Control display of attributes (hexadecimal, description, ... 161 * 162 * @return None 163 */ 164 void smart_print(smart_h, smart_map_t *, smart_matches_t *, uint32_t); 165 /** 166 * Print high-level device information 167 * 168 * @param handle The handle returned from smart_open() 169 * 170 * @return None 171 */ 172 void smart_print_device_info(smart_h); 173 174 #endif 175