DEVICE ID的用途和读取方法

1    用途概述

DEVICE ID可唯一标识一个存储设备,这对于多盘掉电等功能非常重要,因为无论是判定一个盘是否已掉盘还是已上盘都必须知道是哪一个盘。利用这个唯一标识,可以做的事情就很多,包括定位。

一个典型的USB设备的DEVICE ID格式如下:

一个典型的SATA设备的DEVICE ID 格式如下:

2    读取的方法

//

const std::string CUSBPort::GetDeviceID(U32 _phyDevNO, std::string& _strHubID)

{

DEVINST devInst = GetDeviceInst(_phyDevNO);

if (0 == devInst)

{

return "";

}

char szBuff[512] = {0};

CONFIGRET cr = CM_Get_Device_ID(devInst, szBuff, 512, 0);

if (cr != CR_SUCCESS)

{

return "";

}

// 再¨´向¨°上¦?查¨¦找¨°一°?级?即¡ä为aHUBID

DEVINST hubDevInst = 0;

cr = CM_Get_Parent(&hubDevInst, devInst, 0);

if (cr != CR_SUCCESS)

{

return "";

}

char szHubBuff[512] = {0};

cr = CM_Get_Device_ID(hubDevInst, szHubBuff, 512, 0);

if (cr != CR_SUCCESS)

{

return "";

}

_strHubID = szHubBuff;

return std::string(szBuff);

}

U32 CUSBPort::GetDeviceInst(U32 _phyDevNO)

{

// Get device interface info set handle

// for all devices attached to system

GUID* pGUID = (GUID*)&GUID_DEVINTERFACE_DISK;

HDEVINFO hDevInfo = SetupDiGetClassDevs(pGUID, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

if ( hDevInfo == INVALID_HANDLE_VALUE )

{

return 0;

}

// Retrieve a context structure for a device interface

// of a device information set.

U32 dwIndex = 0;

BOOL bRet = FALSE;

BYTE bBuff[1024] = {0};

PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)bBuff;

SP_DEVICE_INTERFACE_DATA spdid = {0};

SP_DEVINFO_DATA spdd = {0};

U32 dwSize = 0;

spdid.cbSize = sizeof(spdid);

while (TRUE, TRUE)

{

bRet = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, pGUID, dwIndex, &spdid);

if (!bRet)

{

break;

}

dwSize = 0;

SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, NULL, 0, &dwSize, NULL);

if (dwSize!=0 && dwSize<=sizeof(bBuff))

{

pspdidd->cbSize = sizeof(*pspdidd); // 5 Bytes!

ZeroMemory((PVOID)&spdd, sizeof(spdd));

spdd.cbSize = sizeof(spdd);

bRet = SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, pspdidd, dwSize, &dwSize, &spdd);

if (bRet)

{

//TRACE("DevicePath: %s \n", pspdidd->DevicePath);

HANDLE hDrive = CreateFile(pspdidd->DevicePath,0,

FILE_SHARE_READ | FILE_SHARE_WRITE,

NULL, OPEN_EXISTING, 0, NULL);

if ( hDrive != INVALID_HANDLE_VALUE )

{

STORAGE_DEVICE_NUMBER sdn;

U32 dwBytesReturned = 0;

bRet = DeviceIoControl(hDrive,

IOCTL_STORAGE_GET_DEVICE_NUMBER,

NULL, 0, &sdn, sizeof(sdn),

&dwBytesReturned, NULL);

if (bRet)

{

if (_phyDevNO == sdn.DeviceNumber)

{

CloseHandle(hDrive);

SetupDiDestroyDeviceInfoList(hDevInfo);

return spdd.DevInst;

}

}

CloseHandle(hDrive);

}

}

}

dwIndex++;

}

SetupDiDestroyDeviceInfoList(hDevInfo);

return 0;

}

3    更多方法

实际上对于SATA盘而言,我们还可以通过SATA端口号来唯一标识一个盘。什么是端口号,可以从intel快速存储技术软件界面中看到例子:

这个端口号也是唯一不变的,在BUSHOUND中也可以找到,只不过其名字不一样:

其读取方法如下:

BOOL    CDiskInfo::GetTargetID(int    hDriver,                 //驱y动¡¥器¡Â句?柄À¨²

PVOID     pCBD, //CBD指?令¢?码?

DWORD     CBDLen,   //CBD指?令¢?码?的Ì?长¡è度¨¨

DWORD     DataTransferLength ,     //数ºy据Y传ä?送¨ª长¡è度¨¨

PVOID     pBuff ,   //数ºy据Y指?针?,ê?无T数ºy据Y为aNULL

BYTE      DataIn ,                //数ºy据Y传ä?输º?方¤?向¨° SCSI_IOCTL_DATA_OUT OR SCSI_IOCTL_DATA_IN

//数ºy据Y由®¨¦设¦¨¨备À?传ä?输º?到Ì?程¨¬序¨°,ê?为aSCSI_IOCTL_DATA_IN

PDWORD    RetLength             //实º¦Ì际¨º返¤¦Ì回?数ºy据Y的Ì?长¡è度¨¨;ê?

)

{

USES_CONVERSION;

char sFilePath[64]={0};

sprintf(sFilePath,"\\\\.\\PHYSICALDRIVE%d",hDriver);

HANDLE hFile = INVALID_HANDLE_VALUE;

hFile = ::CreateFile(sFilePath,

GENERIC_READ | GENERIC_WRITE,

FILE_SHARE_READ | FILE_SHARE_WRITE,

NULL, OPEN_EXISTING,

0, NULL);

if (hFile == INVALID_HANDLE_VALUE) return -1;

DWORD       RetLen;

PDWORD       pRetLen = NULL;

if (NULL == RetLength)

{

pRetLen = &RetLen;

}

else

{

pRetLen = RetLength;

}

ULONG length = 0;//returned = 0;

SCSI_PASS_THROUGH_WITH_BUFFERS  sptwb;

ZeroMemory(&sptwb,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));

sptwb.spt.Length    = sizeof(SCSI_PASS_THROUGH);

sptwb.spt.PathId    = 0;

sptwb.spt.TargetId  = 0;

sptwb.spt.Lun   = 0;

sptwb.spt.SenseInfoLength   = 24;

sptwb.spt.TimeOutValue  = 10;

sptwb.spt.CdbLength = (BYTE)CBDLen;

sptwb.spt.DataIn    = DataIn;

sptwb.spt.DataTransferLength= DataTransferLength;

memcpy(sptwb.spt.Cdb, pCBD, CBDLen);

if ((SCSI_IOCTL_DATA_OUT == DataIn) && (NULL != pBuff))

{

memcpy(sptwb.ucDataBuf , pBuff, DataTransferLength);

}

sptwb.spt.DataBufferOffset =   offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);

sptwb.spt.SenseInfoOffset  =    offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);

length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) + sptwb.spt.DataTransferLength;

bool status = DeviceIoControl(

hFile,

IOCTL_SCSI_PASS_THROUGH,

&sptwb,

sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS),

&sptwb,

length,

pRetLen,

NULL);

return sptwb.spt.TargetId;

}

但在实际操作中并不使用此种方法,因为此方法带有明显的协议性质,USB中并没有这个端口号,PCIE中可能更加没有,而DEVICE ID则不管什么磁盘都有,且目前发现USB连接的设备和SATA设备都可以用相同的函数获取,与协议无关,PCIE应该也可以通过此方法获取DEVICE ID(条件限制还未尝试)。CBD[0] = 0x12是获取TargetID的唯一需要指定的参数信息。

另外切忌,万不得已的情况下对于SSD盘还可以通过序列号&型号名来唯一标示一个盘,序列号和型号名如下图所示:

但鉴于这两个信息量产时可以任意指定,因此可能会重复,如果两个盘同时进行测试就无法区分。但鉴于重复的概率很小,也不失为一种标识磁盘的备选方式。

Device ID的用处和读取方法相关推荐

  1. STM32唯一ID(Unique Device ID)的读取方法

    每一个STM32微控制器都自带一个96位的唯一ID,也就是Unique Device ID或称为UID,这个唯一ID在任何情况下都是唯一的且不允许修改.     在开发过程中,可能需要用到这个UID, ...

  2. 浅谈 iOS Device ID 的修改

    Dark side of the Force 最近有一篇 文章 介绍了如何实现 AppStore App 自动下载,笔者看后收获良多.不过文中只介绍了如何去模拟用户的操作来完成下载,并没有涉及抹机.I ...

  3. ASP.Net全局变量的设置和读取方法

    ASP.Net全局变量的设置和读取方法 本文介绍两种ASP.Net项目中全局变量使用的方式.web.config文件 和 Gloab文件.以下分别说明: 方法一:web.config文件 --设置: ...

  4. AssertionError: Invalid device id 和RuntimeError: CUDA error: invalid device ordinal

    我在使用torch多卡并行时出现了这个两个问题. ##问题一:AssertionError: Invalid device id,即无效的设备id 出现的原因:结合代码解释: import ...os ...

  5. 事件 ID 3001错误的解决方法

    事件 ID: 3001错误的解决方法 事件类型: 错误 事件来源: LoadPerf 事件种类: 无 事件 ID: 3001 日期:  2009-1-23 事件:  12:10:08 用户:  N/A ...

  6. android 有哪些设备id,Android之设备ID(Device ID)

    有时,Android应用程序开发过程中需要得到基于Android智能手机设备的唯一ID .特别是在需要唯一标识设备注册的情况下,Device ID就非常有用.今天我就整理一下Device ID有哪些方 ...

  7. Matlab之netCDF格式文件读取方法

    Matlab之netCDF格式文件读取方法 目录 一.netCDF格式文件 1.简介 2.NetCDF的数据结构 二.Matlab读取netCDF使用到的函数 1.ncdisp() 2.ncinfo( ...

  8. ICD3 Target Device ID (00000000)

    ICD3 Target Device ID (00000000) MPLAB IDE v8.92软件 用的ICD3,圆盘 连线直接跳这个,列举一下几种方法: 1.线松了或者断了,有概率还是亮灯,能识别 ...

  9. COCO目标检测数据集的读取方法与Python工具脚本

    COCO (Common Objects in COntext) 是一个大型的图像数据集,提供了目标检测.分割.看图说话等多个任务的标签.COCO的标注文件是用json格式编写的,初次接触时需要花十来 ...

  10. 掌握R语言文件读取方法

    目标 掌握 R语言文件读取方法 学习笔记 utils包内Date Input用法 base包内readLines用法 stringi包内stri_read_lines xlsx包内Date Input ...

最新文章

  1. [翻译]Joomla 1.5架构(十一) model 包
  2. 概率链接nbu 2416 奇怪的散步
  3. a7100换电池_动动手你也行 篇十四:冲动是魔鬼——单反电池换芯失败记
  4. Hadoop部署方式-高可用集群部署(High Availability)
  5. 中国癌症大数据出来了!每年126万例癌症死亡本可避免
  6. 112_Power Pivot 销售订单按 sku 订单类型特殊分类及占比相关
  7. 计算机视觉中的人类感知、理解和生成 (ICCV 2019 Workshop)
  8. os.path.join()函数用法
  9. linux 清空history以及记录原理
  10. LINUX下载编译OpenH264
  11. cad卸载工具_使用感极好的5款软件分享,款款高逼格,下载之后就没舍得卸载...
  12. 未明学院:云计算热门机器学习项目来袭!收割亚马逊、阿里等一众巨头都看重的实操技能与项目经历!
  13. 计算机机房需要装排烟风机不,送风机房和排烟机房的作用分别是什么
  14. iMazing中IPA文件的介绍与管理
  15. 3DMax软件有什么方法调节摄像机
  16. 2016传智web前端_2016年的10个Web预测
  17. json 的几种格式
  18. 如何用panda3d写一个游戏
  19. 解析json格式请求返回500状态码的异常
  20. [经验教程]支付宝好友被删除了怎么知道及支付宝好友删除是单向还是双向?

热门文章

  1. 智慧养老之智慧养老解决方案-新导智能
  2. 记录在训练深度学习算法过程中遇到的问题及解决办法。持续更新中....
  3. 读《不能承受的生命之轻》 的思考
  4. R3LIVE调试记录
  5. window系统谷歌图标显示异常之IconCache.db(图片缓存文件)
  6. 4.6 linux文件系统-虚拟文件系统VFS
  7. Win11小键盘无法使用怎么办?
  8. 大咖访谈丨金星分享2020年直播数据,助农产品如何走上产销快车道
  9. 一个人最顶级的修养,不与烂人烂事纠缠
  10. JZOJ 3337. 【NOI2013模拟】wyl8899的TLE【暴力】