diff -uNr hddtemp-0.3-beta15.old/src/hddtemp.c hddtemp-0.3-beta15/src/hddtemp.c --- hddtemp-0.3-beta15.old/src/hddtemp.c 2020-02-03 14:23:19.781566750 +0200 +++ hddtemp-0.3-beta15/src/hddtemp.c 2020-02-03 14:31:03.526209746 +0200 @@ -61,6 +61,7 @@ #include "utf8.h" #include "sata.h" #include "scsi.h" +#include "nvme.h" #include "db.h" #include "hddtemp.h" #include "backtrace.h" @@ -87,6 +88,7 @@ bus[BUS_SATA] = &sata_bus; bus[BUS_ATA] = &ata_bus; bus[BUS_SCSI] = &scsi_bus; + bus[BUS_NVME] = &nvme_bus; } /******************************************************* @@ -130,6 +132,8 @@ return BUS_ATA; else if(bus[BUS_SCSI]->probe(dsk->fd)) return BUS_SCSI; + else if (bus[BUS_NVME]->probe(dsk->fd)) + return BUS_NVME; else return BUS_UNKNOWN; } diff -uNr hddtemp-0.3-beta15.old/src/hddtemp.h hddtemp-0.3-beta15/src/hddtemp.h --- hddtemp-0.3-beta15.old/src/hddtemp.h 2020-02-03 14:23:19.781566750 +0200 +++ hddtemp-0.3-beta15/src/hddtemp.h 2020-02-03 08:50:34.755411875 +0200 @@ -35,7 +35,7 @@ #define F_to_C(val) (int)(((double)(val)-32.0)/1.8) #define C_to_F(val) (int)(((double)(val)*(double)1.8) + (double)32.0) -enum e_bustype { ERROR = 0, BUS_UNKNOWN, BUS_SATA, BUS_ATA, BUS_SCSI, BUS_TYPE_MAX }; +enum e_bustype { ERROR = 0, BUS_UNKNOWN, BUS_SATA, BUS_ATA, BUS_SCSI, BUS_NVME, BUS_TYPE_MAX }; enum e_gettemp { GETTEMP_ERROR, /* Error */ GETTEMP_NOT_APPLICABLE, /* */ diff -uNr hddtemp-0.3-beta15.old/src/Makefile.am hddtemp-0.3-beta15/src/Makefile.am --- hddtemp-0.3-beta15.old/src/Makefile.am 2005-03-15 02:23:13.000000000 +0200 +++ hddtemp-0.3-beta15/src/Makefile.am 2020-02-03 08:50:34.737411657 +0200 @@ -13,7 +13,7 @@ scsi.c scsi.h \ scsicmds.c scsicmds.h \ backtrace.c backtrace.h \ - utf8.c utf8.h + utf8.c utf8.h nvme.o hddtemp_CFLAGS = -Wall -W -rdynamic #hddtemp_CFLAGS = -Wall -fomit-frame-pointer -rdynamic diff -uNr hddtemp-0.3-beta15.old/src/Makefile.in hddtemp-0.3-beta15/src/Makefile.in --- hddtemp-0.3-beta15.old/src/Makefile.in 2005-10-17 21:20:28.000000000 +0200 +++ hddtemp-0.3-beta15/src/Makefile.in 2020-02-03 08:50:34.790412300 +0200 @@ -157,7 +157,7 @@ scsi.c scsi.h \ scsicmds.c scsicmds.h \ backtrace.c backtrace.h \ - utf8.c utf8.h + utf8.c utf8.h nvme.c hddtemp_CFLAGS = -Wall -W -rdynamic @@ -180,7 +180,7 @@ hddtemp-hddtemp.$(OBJEXT) hddtemp-sata.$(OBJEXT) \ hddtemp-satacmds.$(OBJEXT) hddtemp-scsi.$(OBJEXT) \ hddtemp-scsicmds.$(OBJEXT) hddtemp-backtrace.$(OBJEXT) \ - hddtemp-utf8.$(OBJEXT) + hddtemp-utf8.$(OBJEXT) hddtemp-nvme.$(OBJEXT) hddtemp_OBJECTS = $(am_hddtemp_OBJECTS) hddtemp_DEPENDENCIES = hddtemp_LDFLAGS = @@ -195,6 +195,7 @@ @AMDEP_TRUE@ ./$(DEPDIR)/hddtemp-db.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/hddtemp-hddtemp.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/hddtemp-sata.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/hddtemp-nvme.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/hddtemp-satacmds.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/hddtemp-scsi.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/hddtemp-scsicmds.Po \ @@ -257,6 +258,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hddtemp-db.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hddtemp-hddtemp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hddtemp-sata.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hddtemp-nvme.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hddtemp-satacmds.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hddtemp-scsi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hddtemp-scsicmds.Po@am__quote@ @@ -416,6 +418,28 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hddtemp_CFLAGS) $(CFLAGS) -c -o hddtemp-sata.obj `if test -f 'sata.c'; then $(CYGPATH_W) 'sata.c'; else $(CYGPATH_W) '$(srcdir)/sata.c'; fi` +hddtemp-nvme.o: nvme.c +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hddtemp_CFLAGS) $(CFLAGS) -MT hddtemp-nvme.o -MD -MP -MF "$(DEPDIR)/hddtemp-nvme.Tpo" \ +@am__fastdepCC_TRUE@ -c -o hddtemp-nvme.o `test -f 'nvme.c' || echo '$(srcdir)/'`nvme.c; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/hddtemp-nvme.Tpo" "$(DEPDIR)/hddtemp-nvme.Po"; \ +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/hddtemp-nvme.Tpo"; exit 1; \ +@am__fastdepCC_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nvme.c' object='hddtemp-nvme.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/hddtemp-nvme.Po' tmpdepfile='$(DEPDIR)/hddtemp-nvme.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hddtemp_CFLAGS) $(CFLAGS) -c -o hddtemp-nvme.o `test -f 'nvme.c' || echo '$(srcdir)/'`nvme.c + +hddtemp-nvme.obj: nvme.c +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hddtemp_CFLAGS) $(CFLAGS) -MT hddtemp-nvme.obj -MD -MP -MF "$(DEPDIR)/hddtemp-nvme.Tpo" \ +@am__fastdepCC_TRUE@ -c -o hddtemp-nvme.obj `if test -f 'nvme.c'; then $(CYGPATH_W) 'nvme.c'; else $(CYGPATH_W) '$(srcdir)/nvme.c'; fi`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/hddtemp-nvme.Tpo" "$(DEPDIR)/hddtemp-nvme.Po"; \ +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/hddtemp-nvme.Tpo"; exit 1; \ +@am__fastdepCC_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nvme.c' object='hddtemp-nvme.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/hddtemp-nvme.Po' tmpdepfile='$(DEPDIR)/hddtemp-nvme.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hddtemp_CFLAGS) $(CFLAGS) -c -o hddtemp-nvme.obj `if test -f 'nvme.c'; then $(CYGPATH_W) 'nvme.c'; else $(CYGPATH_W) '$(srcdir)/nvme.c'; fi` + hddtemp-satacmds.o: satacmds.c @am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hddtemp_CFLAGS) $(CFLAGS) -MT hddtemp-satacmds.o -MD -MP -MF "$(DEPDIR)/hddtemp-satacmds.Tpo" \ @am__fastdepCC_TRUE@ -c -o hddtemp-satacmds.o `test -f 'satacmds.c' || echo '$(srcdir)/'`satacmds.c; \ diff -uNr hddtemp-0.3-beta15.old/src/nvme.c hddtemp-0.3-beta15/src/nvme.c --- hddtemp-0.3-beta15.old/src/nvme.c 1970-01-01 02:00:00.000000000 +0200 +++ hddtemp-0.3-beta15/src/nvme.c 2020-02-03 15:36:20.217181895 +0200 @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2020 Constantine Gavrilov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "hddtemp.h" +#include +#include +#include +#include +#include + +struct nvme_smart_log { + unsigned char critical_warning; + unsigned char temperature[2]; + unsigned char avail_spare; + unsigned char spare_thresh; + unsigned char percent_used; + unsigned char rsvd6[26]; + unsigned char data_units_read[16]; + unsigned char data_units_written[16]; + unsigned char host_reads[16]; + unsigned char host_writes[16]; + unsigned char ctrl_busy_time[16]; + unsigned char power_cycles[16]; + unsigned char power_on_hours[16]; + unsigned char unsafe_shutdowns[16]; + unsigned char media_errors[16]; + unsigned char num_err_log_entries[16]; + unsigned int warning_temp_time; + unsigned int critical_comp_time; + unsigned short temp_sensor[8]; + unsigned int thm_temp1_trans_count; + unsigned int thm_temp2_trans_count; + unsigned int thm_temp1_total_time; + unsigned int thm_temp2_total_time; + unsigned char rsvd232[280]; +}; + +struct nvme_id_power_state { + unsigned short max_power; // centiwatts + unsigned char rsvd2; + unsigned char flags; + unsigned int entry_lat; // microseconds + unsigned int exit_lat; // microseconds + unsigned char read_tput; + unsigned char read_lat; + unsigned char write_tput; + unsigned char write_lat; + unsigned short idle_power; + unsigned char idle_scale; + unsigned char rsvd19; + unsigned short active_power; + unsigned char active_work_scale; + unsigned char rsvd23[9]; +}; + +struct nvme_id_ctrl { + unsigned short vid; + unsigned short ssvid; + char sn[20]; + char mn[40]; + char fr[8]; + unsigned char rab; + unsigned char ieee[3]; + unsigned char cmic; + unsigned char mdts; + unsigned short cntlid; + unsigned int ver; + unsigned int rtd3r; + unsigned int rtd3e; + unsigned int oaes; + unsigned int ctratt; + unsigned char rsvd100[156]; + unsigned short oacs; + unsigned char acl; + unsigned char aerl; + unsigned char frmw; + unsigned char lpa; + unsigned char elpe; + unsigned char npss; + unsigned char avscc; + unsigned char apsta; + unsigned short wctemp; + unsigned short cctemp; + unsigned short mtfa; + unsigned int hmpre; + unsigned int hmmin; + unsigned char tnvmcap[16]; + unsigned char unvmcap[16]; + unsigned int rpmbs; + unsigned short edstt; + unsigned char dsto; + unsigned char fwug; + unsigned short kas; + unsigned short hctma; + unsigned short mntmt; + unsigned short mxtmt; + unsigned int sanicap; + unsigned char rsvd332[180]; + unsigned char sqes; + unsigned char cqes; + unsigned short maxcmd; + unsigned int nn; + unsigned short oncs; + unsigned short fuses; + unsigned char fna; + unsigned char vwc; + unsigned short awun; + unsigned short awupf; + unsigned char nvscc; + unsigned char rsvd531; + unsigned short acwu; + unsigned char rsvd534[2]; + unsigned int sgls; + unsigned char rsvd540[228]; + char subnqn[256]; + unsigned char rsvd1024[768]; + unsigned int ioccsz; + unsigned int iorcsz; + unsigned short icdoff; + unsigned char ctrattr; + unsigned char msdbd; + unsigned char rsvd1804[244]; + struct nvme_id_power_state psd[32]; + unsigned char vs[1024]; +}; + +#include + +static int nvme_probe(int fd) +{ + return (ioctl(fd, NVME_IOCTL_ID, NULL) > 0); +} + +static bool nvme_read_smart_log(int fd, struct nvme_smart_log *smart_log) +{ + unsigned int size = sizeof(*smart_log); + struct nvme_passthru_cmd pt = { 0 }; + + memset(smart_log, 0, size); + pt.opcode = 0x02; + pt.nsid = 0xffffffff; + pt.addr = (uint64_t)smart_log; + pt.data_len = size; + pt.cdw10 = 0x02 | (((size / 4) - 1) << 16); + if (ioctl(fd, NVME_IOCTL_ADMIN_CMD, &pt) < 0) + return false; + return true; +} + +static bool nvme_read_id_ctrl(int fd, struct nvme_id_ctrl *id) +{ + memset(id, 0, sizeof(*id)); + struct nvme_passthru_cmd pt = { 0 }; + pt.opcode = 0x06; + pt.nsid = 0; + pt.addr = (uint64_t)id; + pt.data_len = sizeof(*id); + pt.cdw10 = 0x01; + if (ioctl(fd, NVME_IOCTL_ADMIN_CMD, &pt) < 0) + return false; + return true; +} + + +const char *nvme_model(int fd) +{ + struct nvme_id_ctrl id; + unsigned int i; + char *p; + const unsigned int name_len = sizeof(id.mn); + + if (nvme_read_id_ctrl(fd, &id) == false) + return "NVME Disk"; + id.mn[name_len-1] = '\0'; + for (i = name_len - 2; i > 0; i--) { + if (id.mn[i] == ' ') + id.mn[i] = '\0'; + else + break; + } + p = id.mn; + for (i = 0; i < name_len; i++) { + if (id.mn[i] == ' ') + id.mn[i] = '\0'; + else + break; + } + p = strdup(p); + if (!p || strlen(p) == 0) + return "NVME Disk"; + for (i = 0; p[i]; i++) { + if (p[i] < 0x20 || p[i] > 0x7e) + p[i] = '?'; + } + return p; +} + +enum e_gettemp nvme_get_temperature(struct disk *disk) +{ + struct nvme_smart_log smart_log; + if (nvme_read_smart_log(disk->fd, &smart_log) == false) + return GETTEMP_UNKNOWN; + disk->value = smart_log.temperature[0] + (smart_log.temperature[1] << 8) - 273; + return GETTEMP_KNOWN; +} + +struct bustype nvme_bus = { + "NVME", + nvme_probe, + nvme_model, + nvme_get_temperature +}; + + diff -uNr hddtemp-0.3-beta15.old/src/nvme.h hddtemp-0.3-beta15/src/nvme.h --- hddtemp-0.3-beta15.old/src/nvme.h 1970-01-01 02:00:00.000000000 +0200 +++ hddtemp-0.3-beta15/src/nvme.h 2020-02-03 08:08:03.708300652 +0200 @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2020 Constnatine Gavrilov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _HDDTEMP_NVME_H_ +#define _HDDTEMP_NVME_H_ + +extern struct bustype nvme_bus; + +#endif +