C++ - WinAPI get list of all connected USB devices - c++

I'm trying to create a program that will categorize all the connected USB devices and their port GUID.
I found an example of how to get all the information from connected input devices:
#include <windows.h>
#include <iostream>
// Namespace
using namespace std;
// Main
int main()
{
// Program
cout << "USB Device Lister." << endl;
// Get Number Of Devices
UINT nDevices = 0;
GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST));
// Got Any?
if (nDevices < 1)
{
// Exit
cout << "ERR: 0 Devices?";
cin.get();
return 0;
}
// Allocate Memory For Device List
PRAWINPUTDEVICELIST pRawInputDeviceList;
pRawInputDeviceList = new RAWINPUTDEVICELIST[sizeof(RAWINPUTDEVICELIST) * nDevices];
// Got Memory?
if (pRawInputDeviceList == NULL)
{
// Error
cout << "ERR: Could not allocate memory for Device List.";
cin.get();
return 0;
}
// Fill Device List Buffer
int nResult;
nResult = GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST));
// Got Device List?
if (nResult < 0)
{
// Clean Up
delete[] pRawInputDeviceList;
// Error
cout << "ERR: Could not get device list.";
cin.get();
return 0;
}
// Loop Through Device List
for (UINT i = 0; i < nDevices; i++)
{
// Get Character Count For Device Name
UINT nBufferSize = 0;
nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice, // Device
RIDI_DEVICENAME, // Get Device Name
NULL, // NO Buff, Want Count!
&nBufferSize); // Char Count Here!
// Got Device Name?
if (nResult < 0)
{
// Error
cout << "ERR: Unable to get Device Name character count.. Moving to next device." << endl << endl;
// Next
continue;
}
// Allocate Memory For Device Name
WCHAR* wcDeviceName = new WCHAR[nBufferSize + 1];
// Got Memory
if (wcDeviceName == NULL)
{
// Error
cout << "ERR: Unable to allocate memory for Device Name.. Moving to next device." << endl << endl;
// Next
continue;
}
// Get Name
nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice, // Device
RIDI_DEVICENAME, // Get Device Name
wcDeviceName, // Get Name!
&nBufferSize); // Char Count
// Got Device Name?
if (nResult < 0)
{
// Error
cout << "ERR: Unable to get Device Name.. Moving to next device." << endl << endl;
// Clean Up
delete[] wcDeviceName;
// Next
continue;
}
// Set Device Info & Buffer Size
RID_DEVICE_INFO rdiDeviceInfo;
rdiDeviceInfo.cbSize = sizeof(RID_DEVICE_INFO);
nBufferSize = rdiDeviceInfo.cbSize;
// Get Device Info
nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice,
RIDI_DEVICEINFO,
&rdiDeviceInfo,
&nBufferSize);
// Got All Buffer?
if (nResult < 0)
{
// Error
cout << "ERR: Unable to read Device Info.. Moving to next device." << endl << endl;
// Next
continue;
}
// Mouse
if (rdiDeviceInfo.dwType == RIM_TYPEMOUSE)
{
// Current Device
cout << endl << "Displaying device " << i + 1 << " information. (MOUSE)" << endl;
wcout << L"Device Name: " << wcDeviceName << endl;
cout << "Mouse ID: " << rdiDeviceInfo.mouse.dwId << endl;
cout << "Mouse buttons: " << rdiDeviceInfo.mouse.dwNumberOfButtons << endl;
cout << "Mouse sample rate (Data Points): " << rdiDeviceInfo.mouse.dwSampleRate << endl;
if (rdiDeviceInfo.mouse.fHasHorizontalWheel)
{
cout << "Mouse has horizontal wheel" << endl;
}
else
{
cout << "Mouse does not have horizontal wheel" << endl;
}
}
// Keyboard
else if (rdiDeviceInfo.dwType == RIM_TYPEKEYBOARD)
{
// Current Device
cout << endl << "Displaying device " << i + 1 << " information. (KEYBOARD)" << endl;
wcout << L"Device Name: " << wcDeviceName << endl;
cout << "Keyboard mode: " << rdiDeviceInfo.keyboard.dwKeyboardMode << endl;
cout << "Number of function keys: " << rdiDeviceInfo.keyboard.dwNumberOfFunctionKeys << endl;
cout << "Number of indicators: " << rdiDeviceInfo.keyboard.dwNumberOfIndicators << endl;
cout << "Number of keys total: " << rdiDeviceInfo.keyboard.dwNumberOfKeysTotal << endl;
cout << "Type of the keyboard: " << rdiDeviceInfo.keyboard.dwType << endl;
cout << "Subtype of the keyboard: " << rdiDeviceInfo.keyboard.dwSubType << endl;
}
// Some HID
else // (rdi.dwType == RIM_TYPEHID)
{
// Current Device
cout << endl << "Displaying device " << i + 1 << " information. (HID)" << endl;
wcout << L"Device Name: " << wcDeviceName << endl;
cout << "Vendor Id:" << rdiDeviceInfo.hid.dwVendorId << endl;
cout << "Product Id:" << rdiDeviceInfo.hid.dwProductId << endl;
cout << "Version No:" << rdiDeviceInfo.hid.dwVersionNumber << endl;
cout << "Usage for the device: " << rdiDeviceInfo.hid.usUsage << endl;
cout << "Usage Page for the device: " << rdiDeviceInfo.hid.usUsagePage << endl;
}
// Delete Name Memory!
delete[] wcDeviceName;
}
// Clean Up - Free Memory
delete[] pRawInputDeviceList;
// Exit
cout << endl << "Finnished.";
cin.get();
return 0;
}
I tried to convert this code to get all the connected USB devices but failed.
So my question is what is the best way to collect the data I'm looking for?

If you want all USB devices, not just "input" devices, then you need to use the same APIs that Device Manager does.
For example, all devices shown by Device Manager can be listed with the help of the SetupDiGetClassDevs function.
For listing USB devices, you'll want to use the enumerator parameter set to "USB" (the enumerator is the bus where the device is attached, for example it can be "PCI", "PCMCIA", "USB" for the main computer busses, and it can also be a secondary bus provided by an expansion device, e.g. "SCSI", "FTDIBUS", and so on). You may sometimes find that you're more interested in child devices than the USB-attached parent device itself.

Keep in mind that it is not enough just to comment // (rdi.dwType == RIM_TYPEHID) as you did in following sequence, since it will print only rdiDeviceInfo.hid.SOMETHING info. If device is not HID, I would expect some junk, or similar to be printed.
else // (rdi.dwType == RIM_TYPEHID)
{
// Current Device
cout << endl << "Displaying device " << i + 1 << " information. (HID)" << endl;
wcout << L"Device Name: " << wcDeviceName << endl;
cout << "Vendor Id:" << rdiDeviceInfo.hid.dwVendorId << endl;
cout << "Product Id:" << rdiDeviceInfo.hid.dwProductId << endl;
cout << "Version No:" << rdiDeviceInfo.hid.dwVersionNumber << endl;
cout << "Usage for the device: " << rdiDeviceInfo.hid.usUsage << endl;
cout << "Usage Page for the device: " << rdiDeviceInfo.hid.usUsagePage << endl;
}
I would recommend you to add some logging and breakpoints (to print number of devices, to print all device names etc.). If you don't solve it, please paste the code that you use for testing with precise issue explanation.
UPDATE:
GetRawInputDeviceList function
Remarks
The devices returned from this function are the mouse, the keyboard, and other Human Interface Device (HID) devices.
If your device is not HID don't expect to see it in a list.

Related

How to successfully write to a .DAT file contents in a vector using C++?

I'm trying to write to a .DAT file my list of saved patients that are stored in a vector named PatientsInSystem. However, it won't work for some reason. Does anyone know what I might be doing wrong?
if (!PatientsInSystem.empty()) {
cout << "Error. There are still patients checked in. They must be checked out before quitting." << endl;
cout << "Printing remaining patients in the system... " << endl;
for (int i = 0; i < PatientsInSystem.size(); i++) {
cout << "Patient's ID: " << PatientsInSystem.at(i)->getID() << endl;
cout << "Patient's Name: " << PatientsInSystem.at(i)->getFirstName() << " " << PatientsInSystem.at(i)->getLastName() << endl;
cout << "Patient's Birthday: " << PatientsInSystem.at(i)->getBirthDate() << endl;
cout << "Patient's Primary Doctor's ID: " << PatientsInSystem.at(i)->getPrimaryDoctorID() << endl;
}
}
else {
outFile.open("CurrentPatients.dat", ios::out | ios::binary);
if (!outFile.is_open()) {
cout << "File not open." << endl;
}
else {
cout << "Binary file open, saving patients now...\n";
cout << "----------------------------------------\n";
for (int i = 0; i < PatientsInSystem.size(); i++) {
Patient * p;
p = PatientsInSystem.at(i);
outFile.write(reinterpret_cast<char *> (&p), sizeof(p));
}
}
outFile.close();
[This next section of code is the same as above only edited after the first amount of help received]
Here is the edited version of the code...
PatientList is my temporary vector which must be emptied for PatientsInSystem vector to write to the file
case 'q': {
if (!PatientList.empty()) {
cout << "Error. There are still patients checked in. They must be checked out before quitting." << endl;
cout << "Printing remaining patients in the system... " << endl;
for (int i = 0; i < PatientList.size(); i++) {
cout << "Patient's ID: " << PatientList.at(i)->getID() << endl;
cout << "Patient's Name: " << PatientList.at(i)->getFirstName() << " " << PatientList.at(i)->getLastName() << endl;
cout << "Patient's Birthday: " << PatientList.at(i)->getBirthDate() << endl;
cout << "Patient's Primary Doctor's ID: " << PatientList.at(i)->getPrimaryDoctorID() << endl;
}
}
else {
outFile.open("CurrentPatients.dat", ios::out | ios::binary);
if (!outFile.is_open()) {
cout << "File not open." << endl;
}
else {
cout << "Binary file open, saving patients now...\n";
cout << "----------------------------------------\n";
for (int i = 0; i < PatientsInSystem.size(); i++) {
outFile.write(reinterpret_cast<char *> (PatientsInSystem.at(i)), sizeof(Patient));
}
}
outFile.close();
Is there a reason you are using an array of pointers vs a flat array of structs?
You are writing the local pointer variable p, instead of the Patient data. You would just pass p instead of &p (or just pass .at() directly), and the bytes parameter should be sizeof(Patient).
If these are pointers to different sized derived classes, this has issues.
Also, the loop won't every be entered, because its in the block entered when .empty() is true.

Accessing array pointer in Header file?

By attempting to access the TCPSocket inside my "clientArray" I get a Access Violation error. How would I access it properly?
My header file holds the TCPSocket *clientArray.
public:
TCPsocket *clientArray;
SDLNet_SocketSet aSocketSet;
bool serverOn;
It is defined within my constructor:
clientArray = new TCPsocket[maxsockets];
aSocketSet = SDLNet_AllocSocketSet(maxsockets);
It is accessible within another function of mine (it works here without issue):
void ServerSocket::waitingForConnection() {
std::cout << '\r' << flush << "Players connected: " << playersConnected << ". Listening for connection... ";
TCPsocket newsocket = SDLNet_TCP_Accept(serverSocket);
SDL_Delay(1000);
if (!newsocket){
//std::cout << '\r' << flush << "Listening for connection. ";
//std::cout << SDLNet_GetError() << std::endl;
}
else{
std::cout << '\r' << flush << "Socket (client " << slotnum + 1 << ") created successfully. " << std::endl;
clientArray[slotnum] = newsocket;
int n = SDLNet_TCP_AddSocket(aSocketSet, newsocket);
if (n < 0){
std::cout << "Client " << slotnum + 1 << " failed to connect. " << std::endl;
}
else{
char text[10];
std::cout << "Client " << slotnum + 1 << " added to client array successfully." << std::endl;
serverMessage(slotnum, "2 You are successfully connected to the server.");
std::cout << "Sent connection validation to Client " << slotnum + 1 << "." << endl;
std::cout << "Allocating player " << slotnum + 1 << " with player number ." << endl;
serverData(slotnum, '5', slotnum+1);
//ACCESSING IT HERE WITHOUT ISSUE
SDLNet_TCP_Recv(clientArray[slotnum], text, 10);
std::cout << "received text = " << text << endl;
interpretData(text);
slotnum++;
}
//SDLNet_TCP_Close(newsocket);
//SDLNet_TCP_Close(serverSocket);
//code here
}
}
However later on when I try to access it via another function, I get an Access Violation Error :
Unhandled exception at 0x00AED839 in Server.exe: 0xC0000005: Access violation reading location 0x0000000C.
I am calling the problematic function from my Game's Update function as following:
void Game::Update(){
while (g_playersConnected == 2)
{
printGrid();
serverSocket->waitForPlayer((playerTurn-1));
changeTurn();
system("pause");
}
//cout << "Game's Update is running" << endl;
};
This is my other function that is attempting to access the array :
void ServerSocket::waitForPlayer(int playerNum)
{
cout << "Waiting for player " << playerNum + 1 << " (In array : " << playerNum << ")." << endl;
char text[10];
SDLNet_TCP_Recv(clientArray[playerNum], text, 10);
std::cout << "received text = " << text << endl;
interpretData(text);
}
I have not set up Copy constructors or assignment operators and my destructors are just empty blocks at the moment.
ServerSocket::~ServerSocket(){}
Which direction should I go towards solving this issue?
All the best

Libusb - ubuntu - Psoc5. libusb_open_device_with_vid_pid return 0

I am working on a power engineering project on 4th semester, and programming isn't my strong side. I've been working on using libusb for communication between a PSoC 5 and a Linux terminal program written in C++. The terminal code is:
The problem is that libusb_open_device_with_vid_pid(NULL, 0x1111, 0x2222) returns 0 every time, even though the device is recognized by the Linux OS. OS is Ubuntu if that is relevant.
#include <iostream>
#include "libusb-1.0/libusb.h"
#include "usb.h"
#include <time.h>
using namespace std;
union USB_DATA
{
unsigned char USB_ARRAY[1200];
int DirectionOfPower;
int menu;
float Voltage;
float Current;
float Temperature;
float PowerFactor;
float DistortionPowerFactor;
float Amplitude_Of_Harmonics[1001];
float Regulate_To;
};
union USB_DATA USB_;
/*
void error(string s, int err)
{
cout << s " ERROR: " << libusb_error_name(err) << endl;
exit(err);
}
*/
int main()
{
int transfer_size;
int err;
float Reg_To;
// Device Handle
libusb_device_handle* dev;
// Initialize libusb with default context
libusb_init(NULL);
// Open Device VID = 0x1111, PID = 0x2222 with the default libusb context
dev = libusb_open_device_with_vid_pid( NULL, 0x1111, 0x2222 );
// If device is null, we didn't find it
/*
if (dev == NULL)
{
cout << "Device not found, exiting." << endl;
return -1;
}
int k = 0;
while (dev == NULL)
{
cout << "Device not found, trying again." << " " << k << endl;
//sleep(1);
k = k+1;
}
*/
// Claim interface 0 on the device. Here we te the operation system that wewan this device
libusb_claim_interface(dev, 0);
libusb_detach_kernel_driver(dev, 0);
// Set alternate setting 0 on interface 0
libusb_set_interface_alt_setting(dev, 0, 0);
while(true)
{
cout << "Welcome to Spaendingsregulering!" << endl;
cout << endl;
cout << "MENU" << endl;
cout << "Indtast nummer for navigation" << endl;
cout << "1. Indsaet driftsparametre " << endl;
cout << "2. Analyser harmoniske " << endl;
cout << "3. Fremvis data " << endl;
while(true)
{
cin >> USB_.menu;
if(cin.good())
break;
cin.clear();
}
/*
err = libusb_bulk_transfer(dev, 0x02, USB_.USB_ARRAY, sizeof(union USB_), &transfer_size, 1000);
if( err )
error( "Bulk OUT Transfer Failed!", err);
err = libusb_bulk_transfer(dev, 0x81, USB_.USB_ARRAY, sizeof(union USB_), &transfer_size, 1000);
if( err )
error( "Bulk IN Transfer Failed!", err);
*/
if(USB_.menu == 1)
while(true)
{
cout << "Indsaet oensket spaending" << endl;
cout << "Indtast 999 for at vende tilbage til hovedmenuen" << endl;
cin >> Reg_To;
cout << endl;
if(Reg_To == 999)
{
break;
}
USB_.Regulate_To = Reg_To;
cout << "=======================" << endl;
cout << "Saetter oensket spaending til:" << " " << USB_.Regulate_To << "V" << endl;
cout << "=======================" << endl;
cout << endl;
cout << "Vender tilbage til hovedmenu" << endl;
cout << "..." << endl;
cout << endl;
if(cin.good())
break;
cin.clear();
}
}
}
libusb_open_device_with_vid_pid combines finding and opening and doesn't return an error code. If you are sure the device is there, have you checked you have the rights to read/write to it ? You can also increase the verbosity of error messages.
– Leiaz
Thanks! that did it!. I forgot to use sudo.. rookie mistake – Çağrı Esen

Playing a sound in a MIDI Callback function

I got this little piece of code which is working fine for now. However I want to play a sound in the callback function but I read in the MSDN pages:
"Applications should not call any multimedia functions from inside the callback function, as doing so can cause a deadlock. Other system functions can safely be called from the callback".
I'm quite new to programming and my question is: How can I work around this and still be able to play sounds when a MIDI-key is hit.
#include<iostream>
#include<cstdlib>
#include<windows.h>
#include<Mmsystem.h>
#include<stdio.h>
using namespace std;
void CALLBACK midiCallback(HMIDIIN handle, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
switch (uMsg)
{
case MIM_OPEN:
cout << "-----OPENED.-----" << endl;
break;
case MIM_CLOSE:
cout << "-----EVERYTHING IS CLOSING.-----" << endl;
break;
case MIM_DATA:
cout << "-----APPARENTLY THERE I5 DATA.-----" << endl;
break;
case MIM_LONGDATA:
cout << "-----LONGDATA'D.-----" << endl;
break;
case MIM_ERROR:
cout << "-----ERROR.-----" << endl;
break;
case MIM_LONGERROR:
cout << "-----LONGERROR. EVEN WORSE.-----" << endl;
break;
}
cout << "dwInstance is " << dwInstance << endl;
cout << "Handle is " << handle << endl;
cout << "dwParam1 is " << dwParam1 << endl; //dwParam1 is the bytes of the MIDI Message packed into an unsigned long
cout << "dwParam1_hiword is " << HIWORD(dwParam1) << endl; //velocity
cout << "dwParam1_loword is " << LOWORD(dwParam1) << endl; //keyID
cout << "dwParam2 is " << dwParam2 << endl; //dwParam2 is the timestamp of key press
cout << "uMsg is " << uMsg << endl;
cout << "-----" << endl;
}
void MidiThing() {
MIDIINCAPS mic;
unsigned long result;
HMIDIIN inHandle;
unsigned long iNumDevs, i;
iNumDevs = midiInGetNumDevs(); /* Get the number of MIDI In devices in this computer */
/* Go through all of those devices, displaying their names */
for (i = 0; i < iNumDevs; i++)
{
/* Get info about the next device */
if (!midiInGetDevCaps(i, &mic, sizeof(MIDIINCAPS)))
{
/* Display its Device ID and name */
cout << "Device ID [" << i << "]: " << mic.szPname << endl;
}
}
cout << endl;
// Open the default MIDI In device. (DevID 0)
result = midiInOpen(&inHandle, 0, (DWORD)midiCallback, 0, CALLBACK_FUNCTION);
if (result != MMSYSERR_NOERROR) {
cout << "midiInOpen() failed...rv= " << result << endl;
}
else
{
midiInStart(inHandle);
}
cout << endl;
cout << "Press \"ESC\" to quit." << endl;
while (1) {
if (GetAsyncKeyState(VK_ESCAPE))
{
break;
cout << "exit=true." << endl;
}
Sleep(100);
}
midiInStop(inHandle);
midiInReset(inHandle);
midiInClose(inHandle);
cout << endl;
cout << inHandle << " was the MIDIIN handle." << endl;
cout << endl;
cout << "MIDI is closed now." << endl;
}
int main(int argc, char *argv[])
{
MidiThing();
cout << "Exit is success." << endl;
return EXIT_SUCCESS;
}
Wake up another thread from the callback.

rand number inclining. (C++) [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Problems with srand(), C++
Basically, the random number I am generating is inclining in size, everytime it is used inside my while loop. It being random, should't incline and not be random as such.
The variable hit is defined by the random number. But as I said, the random number is not random. Also, as the random number gets bigger it goes over the limit I set for it.
//Code im using for random number :
srand((unsigned)time(0));
hit = rand()%15;
//The subject for the problem :
while (1) {
if (mon1==0) {
cout << "A dragon appears." << endl;
system ("pause");
cout << "Enter 1 to attack and 2 to run away, " <<name << endl;
cin >> act;
if (act==2) {
cout << "You run away. " << endl;
}
if (act==1) {
cout << " You choose to attack! Good luck " << endl;
}
}
if (mon1==1) { // orc
srand((unsigned)time(0));
hit = rand()%15;
ehealth = (100);
cout << " A orc appears" << endl;
system ("pause");
cout << "Enter 1 to attack and 2 to run away, " <<name << endl;
cin >> act;
system ("cls");
if (act==2) {
cout << "You run away. " << endl;
system ("cls");
}
if (act==1) { // ATTACK HERE MAIN ATTACk TESING !!!!!!!!!!!!!!!!!!!!!!! ORC
cout << " You choose to attack! Good luck " << endl;
cout << " Your health is " << health << endl;
cout << " The enemys health is " << ehealth << endl;
cout << " You have 3 abilitys." << endl;
while (1) {
cout << " Press 1 to swipe, 2 to block the enemys attack and 3 to use your special attack" <<endl;
cin >> act1;
system ("cls");
if (act1==1) {
cout << " You swipe the enemy " << endl; // swipe
cout << " You hit for " << hit << endl;
if (wep==1) {
hit = (hit + 4);
cout << " As you are the axe i will add on 4 to that, making " << hit << endl; // axe
}
ehealth = (ehealth - hit);
cout << " The enemys health is " << ehealth << endl;
cout << " Your health is " << health << endl;
system ("pause");
}
if (act1==2) {
cout <<" You block, making you immune to the next attack" << endl; //block
ehit = (0);
//newrand
cout << " Your health is " << health << endl;
cout << " The enemys health is " << ehealth << endl;
}
if (act1==3) {
cout << " Special attack is being worked on BUDDY, GUY, FRIEND!! " << endl;
}
system ("pause");
if (health < 0) {
cout << "You died, sorry!" << endl;
}
if (ehealth < 0) {
cout << " Yay! You killed the enemy!" << endl;
}
if (health == 0) {
cout << "You died, sorry!" << endl;
}
if (ehealth == 0) {
cout << " Yay! You killed the enemy!" << endl;
}
cout << " Now it is the enemys turn! " << endl;
health = ( health - ehit );
cout << " The enemy hits you for a " << ehit << endl;
cout << " Your health is now " << health << endl;
srand((unsigned)time(0));
ehit = rand()%10;
system ("pause");
system ("cls");
}
// END OF ORC
}
}
hit is randomized when the program starts.
If the monster is an orc, hit is re-randomized.
Every time you attach with an axe, hit permanently increases by four.
You probably want to re-randomize hit each time the user attacks as well?
This code causes this behavior:
hit = (hit + 4);
You increase hit always by 4. So you should use a temporary variable instead.
You only need to call srand once, at the start of the program. That "seeds" the random number generator for an unlimited number of rand() calls afterwards - calling it multiple times will just make the random numbers not random, as you encountered.