/ src / core / mmc.cc
mmc.cc
  1  #include "version.h"
  2  #include "hw.h"
  3  #include "sysfs.h"
  4  #include "osutils.h"
  5  #include "mmc.h"
  6  #include "disk.h"
  7  #include "heuristics.h"
  8  
  9  #include <vector>
 10  #include <iostream>
 11  
 12  __ID("@(#) $Id$");
 13  
 14  /*
 15   * Standard SDIO Function Interfaces
 16   */
 17  
 18  #define SDIO_CLASS_NONE		0x00	/* Not a SDIO standard interface */
 19  #define SDIO_CLASS_UART		0x01	/* standard UART interface */
 20  #define SDIO_CLASS_BT_A		0x02	/* Type-A BlueTooth std interface */
 21  #define SDIO_CLASS_BT_B		0x03	/* Type-B BlueTooth std interface */
 22  #define SDIO_CLASS_GPS		0x04	/* GPS standard interface */
 23  #define SDIO_CLASS_CAMERA	0x05	/* Camera standard interface */
 24  #define SDIO_CLASS_PHS		0x06	/* PHS standard interface */
 25  #define SDIO_CLASS_WLAN		0x07	/* WLAN interface */
 26  #define SDIO_CLASS_ATA		0x08	/* Embedded SDIO-ATA std interface */
 27  #define SDIO_CLASS_BT_AMP	0x09	/* Type-A Bluetooth AMP interface */
 28  
 29  /*
 30   * Vendors and devices.  Sort key: vendor first, device next.
 31   */
 32  #define SDIO_VENDOR_ID_BROADCOM			0x02d0
 33  #define SDIO_DEVICE_ID_BROADCOM_43143		0xa887
 34  #define SDIO_DEVICE_ID_BROADCOM_43241		0x4324
 35  #define SDIO_DEVICE_ID_BROADCOM_4329		0x4329
 36  #define SDIO_DEVICE_ID_BROADCOM_4330		0x4330
 37  #define SDIO_DEVICE_ID_BROADCOM_4334		0x4334
 38  #define SDIO_DEVICE_ID_BROADCOM_43340		0xa94c
 39  #define SDIO_DEVICE_ID_BROADCOM_43341		0xa94d
 40  #define SDIO_DEVICE_ID_BROADCOM_4335_4339	0x4335
 41  #define SDIO_DEVICE_ID_BROADCOM_4339		0x4339
 42  #define SDIO_DEVICE_ID_BROADCOM_43362		0xa962
 43  #define SDIO_DEVICE_ID_BROADCOM_43364		0xa9a4
 44  #define SDIO_DEVICE_ID_BROADCOM_43430		0xa9a6
 45  #define SDIO_DEVICE_ID_BROADCOM_4345		0x4345
 46  #define SDIO_DEVICE_ID_BROADCOM_43455		0xa9bf
 47  #define SDIO_DEVICE_ID_BROADCOM_4354		0x4354
 48  #define SDIO_DEVICE_ID_BROADCOM_4356		0x4356
 49  #define SDIO_DEVICE_ID_BROADCOM_4359		0x4359
 50  #define SDIO_DEVICE_ID_CYPRESS_4373		0x4373
 51  #define SDIO_DEVICE_ID_CYPRESS_43012		43012
 52  #define SDIO_DEVICE_ID_CYPRESS_89359		0x4355
 53  
 54  #define SDIO_VENDOR_ID_INTEL			0x0089
 55  #define SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX	0x1402
 56  #define SDIO_DEVICE_ID_INTEL_IWMC3200WIFI	0x1403
 57  #define SDIO_DEVICE_ID_INTEL_IWMC3200TOP	0x1404
 58  #define SDIO_DEVICE_ID_INTEL_IWMC3200GPS	0x1405
 59  #define SDIO_DEVICE_ID_INTEL_IWMC3200BT		0x1406
 60  #define SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX_2G5	0x1407
 61  
 62  #define SDIO_VENDOR_ID_MARVELL			0x02df
 63  #define SDIO_DEVICE_ID_MARVELL_LIBERTAS		0x9103
 64  #define SDIO_DEVICE_ID_MARVELL_8688WLAN		0x9104
 65  #define SDIO_DEVICE_ID_MARVELL_8688BT		0x9105
 66  #define SDIO_DEVICE_ID_MARVELL_8797_F0		0x9128
 67  #define SDIO_DEVICE_ID_MARVELL_8887WLAN	0x9134
 68  
 69  #define SDIO_VENDOR_ID_MEDIATEK			0x037a
 70  
 71  #define SDIO_VENDOR_ID_SIANO			0x039a
 72  #define SDIO_DEVICE_ID_SIANO_NOVA_B0		0x0201
 73  #define SDIO_DEVICE_ID_SIANO_NICE		0x0202
 74  #define SDIO_DEVICE_ID_SIANO_VEGA_A0		0x0300
 75  #define SDIO_DEVICE_ID_SIANO_VENICE		0x0301
 76  #define SDIO_DEVICE_ID_SIANO_NOVA_A0		0x1100
 77  #define SDIO_DEVICE_ID_SIANO_STELLAR 		0x5347
 78  
 79  #define SDIO_VENDOR_ID_TI			0x0097
 80  #define SDIO_DEVICE_ID_TI_WL1271		0x4076
 81  #define SDIO_VENDOR_ID_TI_WL1251		0x104c
 82  #define SDIO_DEVICE_ID_TI_WL1251		0x9066
 83  
 84  #define SDIO_VENDOR_ID_STE			0x0020
 85  #define SDIO_DEVICE_ID_STE_CW1200		0x2280
 86  
 87  
 88  using namespace std;
 89  
 90  static string strip0x(string s)
 91  {
 92    if(s.length()<2) return s;
 93    if(s.substr(0, 2) == "0x") return s.substr(2, string::npos);
 94    return s;
 95  }
 96  
 97  static string manufacturer(unsigned long n)
 98  {
 99    switch(n)
100    {
101      case 0x0:
102              return "";
103      case 0x2:
104  	    return "Kingston";
105      case 0x3:
106  	    return "SanDisk";
107      default:
108              return "Unknown ("+tostring(n)+")";
109    }
110  }
111  
112  static hwNode sdioNode(unsigned long long c, unsigned long long vendor = 0, unsigned long long device = 0)
113  {
114    hwNode result("interface");
115  
116    switch(c)
117    {
118      case SDIO_CLASS_UART:
119        result = hwNode("serial", hw::communication);
120        result.setDescription("UART interface");
121        break;
122      case SDIO_CLASS_BT_A:
123      case SDIO_CLASS_BT_B:
124      case SDIO_CLASS_BT_AMP:
125        result = hwNode("bt", hw::communication);
126        result.setDescription("BlueTooth interface");
127        result.addCapability("wireless");
128        result.addCapability("bluetooth");
129        result.setConfig("wireless", "BlueTooth");
130        break;
131      case SDIO_CLASS_GPS:
132        result = hwNode("gps");
133        result.setDescription("GPS interface");
134        break;
135      case SDIO_CLASS_CAMERA:
136        result = hwNode("camera");
137        result.setDescription("Camera interface");
138        break;
139      case SDIO_CLASS_PHS:
140        result = hwNode("phs");
141        result.setDescription("PHS interface");
142        break;
143      case SDIO_CLASS_WLAN:
144        result = hwNode("wifi", hw::network);
145        result.setDescription("Wireless interface");
146        result.addCapability("wireless");
147        result.setConfig("wireless", "IEEE 802.11");
148        break;
149      case SDIO_CLASS_ATA:
150        result = hwNode("ata");
151        result.setDescription("SDIO-ATA interface");
152        break;
153    }
154  
155    switch(vendor)
156    {
157      case SDIO_VENDOR_ID_BROADCOM:
158        result.setVendor("Broadcom");
159        switch(device)
160        {
161          case SDIO_DEVICE_ID_BROADCOM_43143:
162            result.setProduct("43143");
163            break;
164          case SDIO_DEVICE_ID_BROADCOM_43241:
165            result.setProduct("43241");
166            break;
167          case SDIO_DEVICE_ID_BROADCOM_4329:
168            result.setProduct("4329");
169            break;
170          case SDIO_DEVICE_ID_BROADCOM_4330:
171            result.setProduct("4330");
172            break;
173          case SDIO_DEVICE_ID_BROADCOM_4334:
174            result.setProduct("4334");
175            break;
176          case SDIO_DEVICE_ID_BROADCOM_43340:
177            result.setProduct("43340");
178            break;
179          case SDIO_DEVICE_ID_BROADCOM_43341:
180            result.setProduct("43341");
181            break;
182          case SDIO_DEVICE_ID_BROADCOM_4335_4339:
183            result.setProduct("4335/4339");
184            break;
185          case SDIO_DEVICE_ID_BROADCOM_4339:
186            result.setProduct("4339");
187            break;
188          case SDIO_DEVICE_ID_BROADCOM_43362:
189            result.setProduct("43362");
190            break;
191          case SDIO_DEVICE_ID_BROADCOM_43364:
192            result.setProduct("43364");
193            break;
194          case SDIO_DEVICE_ID_BROADCOM_43430:
195            result.setProduct("43430");
196            break;
197          case SDIO_DEVICE_ID_BROADCOM_4345:
198            result.setProduct("4345");
199            break;
200          case SDIO_DEVICE_ID_BROADCOM_43455:
201            result.setProduct("43455");
202            break;
203          case SDIO_DEVICE_ID_BROADCOM_4354:
204            result.setProduct("4354");
205            break;
206          case SDIO_DEVICE_ID_BROADCOM_4356:
207            result.setProduct("4356");
208            break;
209          case SDIO_DEVICE_ID_BROADCOM_4359:
210            result.setProduct("4359");
211            break;
212          case SDIO_DEVICE_ID_CYPRESS_4373:
213            result.setVendor("Cypress");
214            result.setProduct("4373");
215            break;
216          case SDIO_DEVICE_ID_CYPRESS_43012:
217            result.setVendor("Cypress");
218            result.setProduct("43012");
219            break;
220          case SDIO_DEVICE_ID_CYPRESS_89359:
221            result.setVendor("Cypress");
222            result.setProduct("89359");
223            break;
224        }
225        break;
226      case SDIO_VENDOR_ID_INTEL:
227        result.setVendor("Intel");
228        switch(device)
229        {
230          case SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX:
231            result.setProduct("IWMC3200WIMAX");
232            break;
233          case SDIO_DEVICE_ID_INTEL_IWMC3200WIFI:
234            result.setProduct("IWMC3200WIFI");
235            break;
236          case SDIO_DEVICE_ID_INTEL_IWMC3200TOP:
237            result.setProduct("IWMC3200TOP");
238            break;
239          case SDIO_DEVICE_ID_INTEL_IWMC3200GPS:
240            result.setProduct("IWMC3200GPS");
241            break;
242          case SDIO_DEVICE_ID_INTEL_IWMC3200BT:
243            result.setProduct("IWMC3200BT");
244            break;
245          case SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX_2G5:
246            result.setProduct("IWMC3200WIMAX 2G5");
247            break;
248        }
249        break;
250      case SDIO_VENDOR_ID_MARVELL:
251        result.setVendor("Marvell");
252        break;
253      case SDIO_VENDOR_ID_MEDIATEK:
254        result.setVendor("MediaTek");
255        break;
256      case SDIO_VENDOR_ID_SIANO:
257        result.setVendor("Siano");
258        switch(device)
259        {
260          case SDIO_DEVICE_ID_SIANO_NOVA_B0:
261            result.setProduct("NOVA B0");
262            break;
263          case SDIO_DEVICE_ID_SIANO_NICE:
264            result.setProduct("NICE");
265            break;
266          case SDIO_DEVICE_ID_SIANO_VEGA_A0:
267            result.setProduct("VEGA A0");
268            break;
269          case SDIO_DEVICE_ID_SIANO_VENICE:
270            result.setProduct("VENICE");
271            break;
272          case SDIO_DEVICE_ID_SIANO_NOVA_A0:
273            result.setProduct("NOVA A0");
274            break;
275          case SDIO_DEVICE_ID_SIANO_STELLAR:
276            result.setProduct("STELLAR");
277            break;
278        }
279        break;
280      case SDIO_VENDOR_ID_TI:
281        result.setVendor("Texas Instruments");
282        switch(device)
283        {
284          case SDIO_DEVICE_ID_TI_WL1271:
285            result.setProduct("WL1271");
286            break;
287          case SDIO_VENDOR_ID_TI_WL1251:
288          case SDIO_DEVICE_ID_TI_WL1251:
289            result.setProduct("WL1251");
290            break;
291        }
292        break;
293      case SDIO_VENDOR_ID_STE:
294        result.setVendor("ST Ericsson");
295        switch(device)
296        {
297          case SDIO_DEVICE_ID_STE_CW1200:
298            result.setProduct("CW1200");
299            break;
300        }
301        break;
302    }
303  
304    return result;
305  }
306  
307  bool scan_mmc(hwNode & n)
308  {
309    vector < sysfs::entry > entries = sysfs::entries_by_class("mmc_host");
310  
311    if (entries.empty())
312      return false;
313  
314    for (vector < sysfs::entry >::iterator it = entries.begin();
315        it != entries.end(); ++it)
316    {
317      const sysfs::entry & e = *it;
318  
319      hwNode *device = n.findChildByBusInfo(e.leaf().businfo());
320      if(!device)
321        device = n.addChild(hwNode(e.name(), hw::bus));
322      else
323        device->setClass(hw::bus);
324  
325      device->claim();
326      device->setLogicalName(e.name());
327      device->setDescription("MMC Host");
328      device->setModalias(e.modalias());
329  
330      vector < sysfs::entry > devices = e.devices();
331      for(vector < sysfs::entry >::iterator i = devices.begin(); i != devices.end(); ++i)
332      {
333        const sysfs::entry & d = *i;
334  
335        hwNode card("device");
336        card.claim();
337        string prod = d.string_attr("name");
338        if(prod != "00000") card.setProduct(prod);
339        card.addCapability(d.string_attr("type"));
340        card.setVendor(manufacturer(d.hex_attr("manfid")));
341        card.setBusInfo(guessBusInfo(d.name()));
342        card.setPhysId(strip0x(d.string_attr("rca")));
343        card.setSerial(tostring(d.hex_attr("serial")));
344        if(unsigned long hwrev = d.hex_attr("hwrev")) {
345  	card.setVersion(tostring(hwrev)+"."+tostring(d.hex_attr("fwrev")));
346        }
347        card.setDate(d.string_attr("date"));
348        card.setDescription("SD/MMC Device");
349        if(card.isCapable("sdio"))
350          card.setDescription("SDIO Device");
351        if(d.string_attr("scr")!="")
352        {
353  	card.setDescription("SD Card");
354          card.setClass(hw::disk);
355        }
356  
357        vector < sysfs::entry > devices = d.devices();
358        for(unsigned long i=0;i<devices.size();i++)
359        {
360          hwNode *subdev;
361          if(devices.size()>1)
362          {
363            subdev = card.addChild(sdioNode(devices[i].hex_attr("class"), devices[i].hex_attr("vendor"), devices[i].hex_attr("device")));
364            subdev->setPhysId(tostring(i+1));
365          }
366          else
367            subdev = &card;
368  
369          subdev->setLogicalName(devices[i].name());
370          subdev->setModalias(devices[i].modalias());
371          subdev->setBusInfo(guessBusInfo(devices[i].name()));
372          if(devices[i].hex_attr("removable"))
373            subdev->addCapability("removable");
374          scan_disk(*subdev);
375        }
376  
377        device->addChild(card);
378      }
379  
380    }
381  
382    return true;
383  }