I know USBs are very complex things, but I've looked everywhere and still can't connect to a USB storage device with C++. I want the program to tell whether there is a new USB stick plugged in and with hard drive name it is.
Thanks
This is a discussion on Simple USB help within the C++ Programming forums, part of the General Programming Boards category; I know USBs are very complex things, but I've looked everywhere and still can't connect to a USB storage device ...
I know USBs are very complex things, but I've looked everywhere and still can't connect to a USB storage device with C++. I want the program to tell whether there is a new USB stick plugged in and with hard drive name it is.
Thanks
My C++ skills aren't good, but can you post some sample code? Some users here might know if you're headed in the right direction.
Ubuntu Linux / Vista Home Premium (for games)
SCiTE text editor, G++ compiler
Posting the code would help.
It would also help if you told us which OS you are using (I expect it's Windows, since you talk of "drive letter", but it could be several other OS's too).
Interacting with USB devices in general is non-trivial - modern OS's make life both easier and harder by providing a generic interface for different levels of usage, e.g. USB low-level (communicating with the device itself), USB high-level (such as detecting device type, connecting to the right type of devices, block read/write for memory type devices, etc), and for example file-system drivers to interface to the block-level interface in the same way they would a hard-disk or CD-ROM device.
There are also services within the system that deals with hotplug behaviour, such as detecting a new device has been plugged in, figuring and loading drivers that it needs (assuming it's already been recognized once before - if it's a new device, then it will pop up a dialog asking if you want to install the drivers).
I don't know much about how you would go about writing software for this, but I may be able to figure out what you are doing wrong if you post the code.
--
Mats
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
For Windows:
Be sure to check the drive-type. If auto-play is enabled at the driver level, then the ejection and insertion of a CDROM/DVDROM disc will show as a Volume removal and arrival.Code:#define _WIN32_WINNT 0x0501 #include <windows.h> #include <dbt.h> #include <string> #include <algorithm> #include <iostream> #include <iomanip> using namespace std; // uncomment to listen for device interface changes //#define LISTEN_TO_DEVICEINTERFACE_CHANGES // uncomment to listen for a specific device interface // leave commented to listen for all interfaces //#define DEVICEINTERFACE_TO_LISTEN4 usbDevIntGuid //----------------------------------------------------------------------------- const GUID volumeDevIntGuid = {0x53F5630D, 0xB6BF, 0x11D0, {0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B}}; const GUID diskDevIntGuid = {0x53f56307, 0xb6bf, 0x11d0, {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b}}; const GUID partitionDevIntGuid = {0x53f5630a, 0xb6bf, 0x11d0, {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b}}; const GUID usbDevIntGuid = {0xa5dcbf10, 0x6530, 0x11d2, {0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51, 0xed}}; struct DevIntGuidNamePair { const GUID *pguid; const char *name; };//DevIntGuidNamePair const DevIntGuidNamePair knownGUIDs[] = { {&volumeDevIntGuid, "Volume"}, {&diskDevIntGuid, "Disk"}, {&partitionDevIntGuid, "Partition"}, {&usbDevIntGuid, "USB"}, };//knownGUIDs const size_t num_knownGUIDs = sizeof(knownGUIDs) / sizeof(*knownGUIDs); //----------------------------------------------------------------------------- void PrintVolumeChange(DEV_BROADCAST_VOLUME *pbv, bool bArrival) { size_t mask = 1; char c = 'A'; for (; c <= 'Z'; ++c, mask <<= 1) { if (!(mask & pbv->dbcv_unitmask)) continue; if (bArrival) cout << "New media, drive "; else cout << "Removed media, drive "; char path[] = "x:\\"; path[0] = c; cout << path << ' '; switch (GetDriveTypeA(path)) { case DRIVE_REMOVABLE: cout << "[Removable Media]"; break; case DRIVE_FIXED: cout << "[Fixed Media]"; break; case DRIVE_REMOTE: cout << "[Network Drive]"; break; case DRIVE_CDROM: cout << "[CD-ROM Drive]"; break; case DRIVE_RAMDISK: cout << "[RAM Disk]"; break; case DRIVE_UNKNOWN: cout << "[Unknown Type]"; break; case DRIVE_NO_ROOT_DIR: cout << "[No Root]"; break; }//switch cout << endl; }//for cout << endl; }//PrintVolumeChange //----------------------------------------------------------------------------- void PrintDevIntNames(DEV_BROADCAST_DEVICEINTERFACE_A *pbdi) { string name = pbdi->dbcc_name; string::size_type pos = name.rfind('#'); if (pos == string::npos) { cout << "\n Error"; return; }//if // device interface guid follows last # // this is the text representation of pbdi->dbcc_classguid string devint_guid = name.substr(pos + 1); // remove trailing guid and leading "\\?\" name.erase(pos); name.erase(0, 4); // replace remaining # to \ to form the full PNP enumerator name replace(name.begin(), name.end(), '#', '\\'); for (size_t n = 0; n < num_knownGUIDs; ++n) { if (*knownGUIDs[n].pguid == pbdi->dbcc_classguid) { cout << "\n Device Interface Name = " << knownGUIDs[n].name; break; }//if }//for cout << "\n Device Interface GUID = " << devint_guid << "\n Device PNP Enum Name = " << name; }//PrintDevIntNames //----------------------------------------------------------------------------- LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (msg == WM_DEVICECHANGE) { if ((wParam == DBT_DEVICEARRIVAL) || (wParam == DBT_DEVICEREMOVECOMPLETE)) { bool bArrival = wParam == DBT_DEVICEARRIVAL; DEV_BROADCAST_HDR *pbh = (DEV_BROADCAST_HDR*)lParam; if (pbh->dbch_devicetype == DBT_DEVTYP_VOLUME) { PrintVolumeChange((DEV_BROADCAST_VOLUME*)pbh, bArrival); }//if else { if (bArrival) cout << "Arrival of "; else cout << "Removal of "; if (pbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) PrintDevIntNames((DEV_BROADCAST_DEVICEINTERFACE_A*)pbh); else cout << "devicetype " << pbh->dbch_devicetype; cout << '\n' << endl; }//else }//if else if (wParam == DBT_DEVNODES_CHANGED) { // ignore }//else if else cout << "WM_DEVICECHANGE, wParam = 0x" << setw(4) << hex << setfill('0') << int(wParam) << dec << endl; }//if else { /* cout << "Got msg " << msg << ", " << int(wParam) << ", " << int(lParam) << endl; */ }//else return 1; }//WinProc //----------------------------------------------------------------------------- int main() { const char * const className = "DevNotifyTest"; WNDCLASSA wincl = {0}; wincl.hInstance = GetModuleHandleA(0); wincl.lpszClassName = className; wincl.lpfnWndProc = WinProc; if (!RegisterClassA(&wincl)) { DWORD le = GetLastError(); cout << "RegisterClassA() failed, le = " << le << endl; return 1; }//if HWND hwnd = CreateWindowExA(0, className, className, 0, 0, 0, 0, 0, 0, 0, 0, 0); if (!hwnd) { DWORD le = GetLastError(); cout << "CreateWindowExA() failed, le = " << le << endl; return 1; }//if #ifdef LISTEN_TO_DEVICEINTERFACE_CHANGES DEV_BROADCAST_DEVICEINTERFACE_A notifyFilter = {0}; notifyFilter.dbcc_size = sizeof(notifyFilter); notifyFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; #ifdef DEVICEINTERFACE_TO_LISTEN4 notifyFilter.dbcc_classguid = DEVICEINTERFACE_TO_LISTEN4; #endif HDEVNOTIFY hDevNotify = RegisterDeviceNotificationA(hwnd, ¬ifyFilter, #ifndef DEVICEINTERFACE_TO_LISTEN4 DEVICE_NOTIFY_ALL_INTERFACE_CLASSES | #endif DEVICE_NOTIFY_WINDOW_HANDLE); if (!hDevNotify) { DWORD le = GetLastError(); cout << "RegisterDeviceNotificationA() failed, le = " << le << endl; return 1; }//if #endif //ifdef LISTEN_TO_DEVICEINTERFACE_CHANGES cout << "Waiting for device change notifications, " "Ctrl-C to exit.\n" << endl; for (;;) { MSG msg; BOOL bRet = GetMessage(&msg, hwnd, 0, 0); if ((bRet == 0) || (bRet == -1)) break; TranslateMessage(&msg); DispatchMessage(&msg); }//while return 0; }//main
gg