From 1787b1cf23096cf4a6ebc0acacff812d9e1eb5e1 Mon Sep 17 00:00:00 2001
From: chrfranke <chrfranke@4ea69e1a-61f1-4043-bf83-b5c94c648137>
Date: Thu, 12 Mar 2009 20:31:12 +0000
Subject: [PATCH] Add function get_usb_dev_type_by_id() to map USB IDs to '-d
 type' names.

git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@2755 4ea69e1a-61f1-4043-bf83-b5c94c648137
---
 sm5/CHANGELOG       |  7 +++++-
 sm5/dev_interface.h | 14 ++++++++++--
 sm5/scsiata.cpp     | 54 ++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 71 insertions(+), 4 deletions(-)

diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG
index 5fd6fe793..dcd390cda 100644
--- a/sm5/CHANGELOG
+++ b/sm5/CHANGELOG
@@ -1,6 +1,6 @@
 CHANGELOG for smartmontools
 
-$Id: CHANGELOG,v 1.783 2009/03/09 20:26:04 chrfranke Exp $
+$Id: CHANGELOG,v 1.784 2009/03/12 20:31:12 chrfranke Exp $
 
 The most recent version of this file is:
 http://smartmontools.cvs.sourceforge.net/smartmontools/sm5/CHANGELOG?view=markup
@@ -41,6 +41,11 @@ NOTES FOR FUTURE RELEASES: see TODO file.
 
 <DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE>
 
+  [CF] Add function smart_interface::get_usb_dev_type_by_id() to map
+       USB vendor:product IDs to '-d type' names. Can be used by
+       platform dependent layer to autodetect USB devices if ID of
+       USB bridge is known.
+
   [CF] smartd: Log changes of self-test execution status if
        '-l selftest'is specified.
 
diff --git a/sm5/dev_interface.h b/sm5/dev_interface.h
index 95efc2a58..7550c3aa3 100644
--- a/sm5/dev_interface.h
+++ b/sm5/dev_interface.h
@@ -3,7 +3,7 @@
  *
  * Home page of code is: http://smartmontools.sourceforge.net
  *
- * Copyright (C) 2008 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2008-9 Christian Franke <smartmontools-support@lists.sourceforge.net>
  *
  * 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
@@ -18,7 +18,7 @@
 #ifndef DEV_INTERFACE_H
 #define DEV_INTERFACE_H
 
-#define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h,v 1.8 2009/02/27 22:42:52 chrfranke Exp $\n"
+#define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h,v 1.9 2009/03/12 20:31:12 chrfranke Exp $\n"
 
 #include <stdarg.h>
 #include <string>
@@ -691,6 +691,12 @@ public:
     const unsigned char * inqdata, unsigned inqsize);
   //{ implemented in scsiata.cpp }
 
+  /// Get type name for USB device with known VENDOR:PRODUCT ID.
+  /// Return name if device known and supported, otherwise 0.
+  virtual const char * get_usb_dev_type_by_id(int vendor_id, int product_id,
+                                              int version = -1);
+  //{ implemented in scsiata.cpp }
+
 protected:
   /// Set interface to use, must be called from init().
   static void set(smart_interface * intf)
@@ -702,6 +708,10 @@ private:
 
   friend smart_interface * smi(); // below
   static smart_interface * s_instance; ///< Pointer to the interface object.
+
+  // Prevent copy/assigment
+  smart_interface(const smart_interface &);
+  void operator=(const smart_interface &);
 };
 
 
diff --git a/sm5/scsiata.cpp b/sm5/scsiata.cpp
index ddcf4e912..02c441e6f 100644
--- a/sm5/scsiata.cpp
+++ b/sm5/scsiata.cpp
@@ -51,7 +51,7 @@
 #include "dev_ata_cmd_set.h" // ata_device_with_command_set
 #include "dev_tunnelled.h" // tunnelled_device<>
 
-const char *scsiata_c_cvsid="$Id: scsiata.cpp,v 1.24 2009/03/06 22:23:04 chrfranke Exp $"
+const char *scsiata_c_cvsid="$Id: scsiata.cpp,v 1.25 2009/03/12 20:31:12 chrfranke Exp $"
 CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID SCSICMDS_H_CVSID SCSIATA_H_CVSID UTILITY_H_CVSID;
 
 /* for passing global control variables */
@@ -1132,3 +1132,55 @@ ata_device * smart_interface::autodetect_sat_device(scsi_device * scsidev,
 
   return 0;
 }
+
+
+/////////////////////////////////////////////////////////////////////////////
+// USB device type detection
+
+struct usb_id_entry {
+  int vendor_id, product_id, version;
+  const char * type;
+};
+
+const char d_sat[]     = "sat";
+const char d_jmicron[] = "usbjmicron";
+const char d_cypress[] = "usbcypress";
+const int  d_unsup = 0;
+
+// Map USB IDs -> '-d type' string
+const usb_id_entry usb_ids[] = {
+  { 0x04b4, 0x6830, 0x0001, d_unsup   }, // Cypress CY7C68300A
+//{ 0x04b4,     -1,     -1, d_cypress }, // Cypress CY7C68300B/C ?
+  { 0x0c0b, 0xb159, 0x0103, d_unsup   }, // Dura Micro ?
+  { 0x0d49, 0x7310, 0x0125, d_sat     }, // Maxtor OneTouch 4
+//{ 0x0d49,     -1,     -1, d_sat     }, // Maxtor Basics Desktop
+  { 0x1058, 0x1001, 0x0104, d_sat     }, // WD Elements Desktop
+  { 0x13fd, 0x1240, 0x0104, d_sat     }, // Initio ? (USB->SATA)
+  { 0x13fd, 0x1340, 0x0208, d_sat     }, // Initio ? (USB+SATA->SATA)
+  { 0x152d, 0x2336, 0x0100, d_jmicron }, // JMicron JM20336 (USB+SATA->SATA, USB->2xSATA)
+  { 0x152d, 0x2338, 0x0100, d_jmicron }, // JMicron JM20337/8 (USB->SATA+PATA, USB+SATA->PATA)
+  { 0x152d, 0x2339, 0x0100, d_jmicron }  // JMicron JM20339 (USB->SATA)
+};
+
+const unsigned num_usb_ids = sizeof(usb_ids)/sizeof(usb_ids[0]);
+
+
+// Get type name for USB device with known VENDOR:PRODUCT ID.
+// Version not checked yet.
+const char * smart_interface::get_usb_dev_type_by_id(int vendor_id, int product_id,
+                                                     int /*version = -1*/)
+{
+  for (unsigned i = 0; i < num_usb_ids; i++) {
+    const usb_id_entry & e = usb_ids[i];
+    if (vendor_id == e.vendor_id && product_id == e.product_id) {
+      if (e.type == d_unsup) {
+        set_err(ENOSYS, "Unsupported USB bridge (0x%04x:0x%04x)", vendor_id, product_id);
+        return 0;
+      }
+      return e.type;
+    }
+  }
+
+  set_err(EINVAL, "Unknown USB bridge (0x%04x:0x%04x)", vendor_id, product_id);
+  return 0;
+}
-- 
GitLab