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