summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/debug_menu.c202
-rw-r--r--apps/gui/list.h4
2 files changed, 206 insertions, 0 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index e602b713c3..2b9702299b 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -1507,6 +1507,205 @@ static int disk_callback(int btn, struct gui_synclist *lists)
1507#endif /* HAVE_ATA_DMA */ 1507#endif /* HAVE_ATA_DMA */
1508 return btn; 1508 return btn;
1509} 1509}
1510
1511#ifdef HAVE_ATA_SMART
1512static struct ata_smart_values *smart_data = NULL;
1513
1514static const char * ata_smart_get_attr_name(unsigned char id)
1515{
1516 switch (id)
1517 {
1518 case 1: return "Raw Read Error Rate";
1519 case 2: return "Throughput Performance";
1520 case 3: return "Spin-Up Time";
1521 case 4: return "Start/Stop Count";
1522 case 5: return "Reallocated Sector Count";
1523 case 7: return "Seek Error Rate";
1524 case 8: return "Seek Time Performance";
1525 case 9: return "Power-On Hours Count";
1526 case 10: return "Spin-Up Retry Count";
1527 case 12: return "Power Cycle Count";
1528 case 192: return "Power-Off Retract Count";
1529 case 193: return "Load/Unload Cycle Count";
1530 case 194: return "HDA Temperature";
1531 case 196: return "Reallocated Event Count";
1532 case 197: return "Current Pending Sector Count";
1533 case 198: return "Uncorrectable Sector Count";
1534 case 199: return "UltraDMA CRC Error Count";
1535 case 220: return "Disk Shift";
1536 case 222: return "Loaded Hours";
1537 case 223: return "Load/Unload Retry Count";
1538 case 224: return "Load Friction";
1539 case 226: return "Load-In Time";
1540 case 240: return "Transfer Error Rate"; /* Fujitsu */
1541 /*case 240: return "Head Flying Hours";*/
1542 default: return "Unknown Attribute";
1543 }
1544};
1545
1546static int ata_smart_get_attr_rawfmt(unsigned char id)
1547{
1548 switch (id)
1549 {
1550 case 3: /* Spin-up time */
1551 return RAWFMT_RAW16_OPT_AVG16;
1552
1553 case 5: /* Reallocated sector count */
1554 case 196: /* Reallocated event count */
1555 return RAWFMT_RAW16_OPT_RAW16;
1556
1557 case 190: /* Airflow Temperature */
1558 case 194: /* HDA Temperature */
1559 return RAWFMT_TEMPMINMAX;
1560
1561 default:
1562 return RAWFMT_RAW48;
1563 }
1564};
1565
1566static int ata_smart_attr_to_string(
1567 struct ata_smart_attribute *attr, char *str, int size)
1568{
1569 uint16_t w[3]; /* 3 words to store 6 bytes of raw data */
1570 char buf[size]; /* temp string to store attribute data */
1571 int len, slen;
1572 int id = attr->id;
1573
1574 if (id == 0)
1575 return 0; /* null attribute */
1576
1577 /* align and convert raw data */
1578 memcpy(w, attr->raw, 6);
1579 w[0] = letoh16(w[0]);
1580 w[1] = letoh16(w[1]);
1581 w[2] = letoh16(w[2]);
1582
1583 len = snprintf(buf, size, ": %u,%u ", attr->current, attr->worst);
1584
1585 switch (ata_smart_get_attr_rawfmt(id))
1586 {
1587 case RAWFMT_RAW16_OPT_RAW16:
1588 len += snprintf(buf+len, size-len, "%u", w[0]);
1589 if ((w[1] || w[2]) && (len < size))
1590 len += snprintf(buf+len, size-len, " %u %u", w[1],w[2]);
1591 break;
1592
1593 case RAWFMT_RAW16_OPT_AVG16:
1594 len += snprintf(buf+len, size-len, "%u", w[0]);
1595 if (w[1] && (len < size))
1596 len += snprintf(buf+len, size-len, " Avg: %u", w[1]);
1597 break;
1598
1599 case RAWFMT_TEMPMINMAX:
1600 len += snprintf(buf+len, size-len, "%u -/+: %u/%u", w[0],w[1],w[2]);
1601 break;
1602
1603 case RAWFMT_RAW48:
1604 default:
1605 /* shows first 4 bytes of raw data as uint32 LE,
1606 and the ramaining 2 bytes as uint16 LE */
1607 len += snprintf(buf+len, size-len, "%lu", letoh32(*((uint32_t*)w)));
1608 if (w[2] && (len < size))
1609 len += snprintf(buf+len, size-len, " %u", w[2]);
1610 break;
1611 }
1612 /* ignore trailing \0 when truncated */
1613 if (len >= size) len = size-1;
1614
1615 /* fill return string; when max. size is exceded: first truncate
1616 attribute name, then attribute data and finally attribute id */
1617 slen = snprintf(str, size, "%d ", id);
1618 if (slen < size) {
1619 /* maximum space disponible for attribute name,
1620 including initial space separator */
1621 int name_sz = size - (slen + len);
1622 if (name_sz > 1) {
1623 len = snprintf(str+slen, name_sz, " %s",
1624 ata_smart_get_attr_name(id));
1625 if (len >= name_sz) len = name_sz-1;
1626 slen += len;
1627 }
1628 snprintf(str+slen, size-slen, "%s", buf);
1629 }
1630
1631 return 1; /* ok */
1632}
1633
1634static bool ata_smart_dump(void)
1635{
1636 int fd;
1637
1638 fd = creat("/smart_data.bin", 0666);
1639 if(fd >= 0)
1640 {
1641 write(fd, smart_data, sizeof(struct ata_smart_values));
1642 close(fd);
1643 }
1644
1645 fd = creat("/smart_data.txt", 0666);
1646 if(fd >= 0)
1647 {
1648 int i;
1649 char buf[128];
1650 for (i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++)
1651 {
1652 if (ata_smart_attr_to_string(
1653 &smart_data->vendor_attributes[i], buf, sizeof(buf)))
1654 {
1655 write(fd, buf, strlen(buf));
1656 write(fd, "\n", 1);
1657 }
1658 }
1659 close(fd);
1660 }
1661
1662 return false;
1663}
1664
1665static int ata_smart_callback(int btn, struct gui_synclist *lists)
1666{
1667 (void)lists;
1668
1669 if (btn == ACTION_STD_CANCEL)
1670 {
1671 smart_data = NULL;
1672 return btn;
1673 }
1674
1675 /* read S.M.A.R.T. data only on first redraw */
1676 if (!smart_data)
1677 {
1678 int i;
1679 char buf[SIMPLELIST_MAX_LINELENGTH];
1680 smart_data = ata_read_smart();
1681 simplelist_set_line_count(0);
1682 simplelist_addline("Id Name: Current,Worst Raw");
1683 for (i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) {
1684 if (ata_smart_attr_to_string(
1685 &smart_data->vendor_attributes[i], buf, sizeof(buf)))
1686 simplelist_addline(buf);
1687 }
1688 }
1689
1690 if (btn == ACTION_STD_CONTEXT)
1691 {
1692 ata_smart_dump();
1693 splashf(HZ, "S.M.A.R.T. data dumped");
1694 }
1695
1696 return btn;
1697}
1698
1699static bool dbg_ata_smart(void)
1700{
1701 struct simplelist_info info;
1702 simplelist_info_init(&info, "S.M.A.R.T. Data [CONTEXT to dump]", 1, NULL);
1703 info.action_callback = ata_smart_callback;
1704 info.hide_selection = true;
1705 info.scroll_all = true;
1706 return simplelist_show_list(&info);
1707}
1708#endif /* HAVE_ATA_SMART */
1510#else /* No SD, MMC or ATA */ 1709#else /* No SD, MMC or ATA */
1511static int disk_callback(int btn, struct gui_synclist *lists) 1710static int disk_callback(int btn, struct gui_synclist *lists)
1512{ 1711{
@@ -2383,6 +2582,9 @@ static const struct {
2383 { "View disk info", dbg_disk_info }, 2582 { "View disk info", dbg_disk_info },
2384#if (CONFIG_STORAGE & STORAGE_ATA) 2583#if (CONFIG_STORAGE & STORAGE_ATA)
2385 { "Dump ATA identify info", dbg_identify_info}, 2584 { "Dump ATA identify info", dbg_identify_info},
2585#ifdef HAVE_ATA_SMART
2586 { "View/Dump S.M.A.R.T. data", dbg_ata_smart},
2587#endif
2386#endif 2588#endif
2387#endif 2589#endif
2388 { "Metadata log", dbg_metadatalog }, 2590 { "Metadata log", dbg_metadatalog },
diff --git a/apps/gui/list.h b/apps/gui/list.h
index 0f2f51a424..ef08a9e220 100644
--- a/apps/gui/list.h
+++ b/apps/gui/list.h
@@ -257,7 +257,11 @@ struct simplelist_info {
257}; 257};
258 258
259#define SIMPLELIST_MAX_LINES 32 259#define SIMPLELIST_MAX_LINES 32
260#ifdef HAVE_ATA_SMART
261#define SIMPLELIST_MAX_LINELENGTH 48
262#else
260#define SIMPLELIST_MAX_LINELENGTH 32 263#define SIMPLELIST_MAX_LINELENGTH 32
264#endif
261 265
262/** The next three functions are used if the text is mostly static. 266/** The next three functions are used if the text is mostly static.
263 These should be called in the action callback for the list. 267 These should be called in the action callback for the list.