xref: /freebsd/contrib/smart/libsmart.h (revision 7419d6e463fee40f0f52cd5bc46a93cbb7ac6114)
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