Thread: Simple USB help

  1. #1
    Registered User
    Join Date
    Jun 2008
    Posts
    2

    Simple USB help

    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

  2. #2
    Beginner in C++
    Join Date
    Dec 2007
    Posts
    34
    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

  3. #3
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    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.

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    For Windows:
    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, &notifyFilter,
    #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
    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.

    gg

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 03:00 PM
  2. Building a SIMPLE computer device
    By Coder87C in forum Windows Programming
    Replies: 0
    Last Post: 05-09-2004, 10:39 PM
  3. USB Drives???
    By khpuce in forum Tech Board
    Replies: 14
    Last Post: 12-12-2003, 09:01 AM
  4. Usb 2.0
    By ober in forum Tech Board
    Replies: 6
    Last Post: 09-06-2003, 10:14 AM
  5. Programming for USB communications
    By minesweeper in forum Windows Programming
    Replies: 2
    Last Post: 11-05-2002, 06:33 PM