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