I'm trying to open a WinUSB device that is part of a composite device. I have located the correct child device using cfgmgr32, and have its DEVINST number. In order to open it with WinUSB, I need to first call CreateFile, for which I need the Device Path.
The Device Path looks like:
\\\\?\\usb#vid_9999&pid_0102#3555303335351909000b0#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
How can I obtain the Device Path?
I recommend looking at the get_filename_from_devinst_and_guid function which is part of libusbp.
The basic outline is:
Make sure you know the device interface GUID you are looking for. That is the thing in brackets at the end of the filename you provided. This usually comes from the INF file that sets up WinUSB, though it can also come from MS OS descriptors on the device. You can find it in the registry. You have to pack it into a Win32 API GUID struct.
Call SetupDiGetClassDevs(guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); to get a list of all the present (connected) devices supporting that device interface GUID.
Use SetupDiEnumDeviceInfo to iterate through the list until you find the item that matches the DEVINST you already found.
Use SetupDiEnumDeviceInterfaces to get the list of interfaces for that item. There should only be one entry because you already specified the device interface GUID you are interested in.
Use SetupDiGetDeviceInterfaceDetail to get SP_DEVICE_INTERFACE_DETAIL_DATA_A data structure.
The filename you are looking for is in the DevicePath member of that structure.
This function returns a list of NULL-terminated Device Paths (that's what we get from CM_Get_Device_Interface_List)
You need to pass it the DEVINST, and the wanted interface GUID.
Since both the DEVINST and interface GUID are specified, it is highly likely that CM_Get_Device_Interface_List will return a single Device Path for that interface, but technically you should be prepared to get more than one result.
I used this function successfully in production code for getting the Device Interface of a USB HUB (GUID_CLASS_USBHUB): I used the resulting Device Path with CreateFile and opened it succesfully.
It is responsibility of the caller to delete[] the returned list if the function returns successfully (return code 0)
int GetDevInstInterfaces(DEVINST dev, LPGUID interfaceGUID, wchar_t**outIfaces, ULONG* outIfacesLen)
{
CONFIGRET cres;
if (!outIfaces)
return -1;
if (!outIfacesLen)
return -2;
// Get System Device ID
WCHAR sysDeviceID[256];
cres = CM_Get_Device_ID(dev, sysDeviceID, sizeof(sysDeviceID) / sizeof(sysDeviceID[0]), 0);
if (cres != CR_SUCCESS)
return -11;
// Get list size
ULONG ifaceListSize = 0;
cres = CM_Get_Device_Interface_List_Size(&ifaceListSize, interfaceGUID, sysDeviceID, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
if (cres != CR_SUCCESS)
return -12;
// Allocate memory for the list
wchar_t* ifaceList = new wchar_t[ifaceListSize];
// Populate the list
cres = CM_Get_Device_Interface_List(interfaceGUID, sysDeviceID, ifaceList, ifaceListSize, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
if (cres != CR_SUCCESS) {
delete[] ifaceList;
return -13;
}
// Return list
*outIfaces = ifaceList;
*outIfacesLen = ifaceListSize;
return 0;
}
Related
I am trying to define a complex structure (practically a POD) as a property in a REP file. The structure is defined already as Q_GADGET in a separate header file.
When I try to instantiate the replica the system crashes complaining that
it is unable to create a certain type (and in the log then comes three completely bogus (e.g. too high) type id numbers)
Is it possible to define structures as properties in the QT5 Remote Object
world? If yes how?
Thanks,
It appears my "naive" operator<< implementation was wrong. I simply <<-ed all the members one after the other into the stream, which caused some issues.
However using the
inline QDataStream& operator<<(QDataStream& stream, const my::api::User & value) {
QtRemoteObjects::copyStoredProperties(&value, stream);
return stream;
}
inline QDataStream& operator>>(QDataStream& stream, my::api::User & value) {
QtRemoteObjects::copyStoredProperties(stream, &value);
return stream;
}
"ethalon" solution (generated my the REPC compiler for PODs) works just fine.
I am trying to record the state of the application when an Exception occurs within the application, i am specifically interested with the method local variable values(Both Primitive and User Defined)? i have gone through the documentation of ASM 5.1, but i couldn't find any interfaces which lets me access the values? is there a way to do this, if not using ASM are there any other Interfaces which would let me do this ? The solution should be independent of the application, it should be a plug and play type solution, using which i should be able to plug it to any java application.
Getting Field Ids using JNI:
char *klazName;
error = (*jvmti)->GetLocalObject(jvmti, thread, i,
table_ptr[j].slot, &value_ptr);
check_jvmti_error(jvmti, error,
"Cannot Get Local Variable Object");
if(!error){
klaz = (*env)->GetObjectClass(env,value_ptr);
error = (*jvmti)->GetClassSignature(jvmti, klaz,
&klazName, NULL);
if(strstr(klazName,"String")!=NULL){
printf("...%s\n",klazName);
field = (*env)->GetFieldID(env,declaring_class_ptr,table_ptr[j].name,"S");
value = (jstring)(*env)->GetObjectField(env,value_ptr,field);
stringVal = (*env)->GetStringUTFChars(env,value,0);
printf("Value of Field %s is .\n", stringVal);
JVM TI GetLocal* functions should help.
I am trying to interface with a USB device that provides an external C++ dll file and have read a myriad of articles surrounding delegates, marshalling, pointers and I generally get the idea of what is happening. Unfortunately, my practical experience in this area is letting me down in obtaining the final solution.
I have connected to the device in order to create a session successfully but there is a function called EnumDevices which supposedly enumerates the device list for specific future calls. The function has a function within itself that lists the devices and it is this part I am struggling with.
The enumdevices call in the API looks like this:
EnumDevices(INTERFACE,FoundDevice,NULL);
bool __stdcall FoundDevice(long data, const char *DeviceName)
{
printf("device name %s\n", DeviceName)
Return True
}
and according to the documentation, FoundDevice is a call back method called for each found device.
In VB.Net, what I have done is as follows:
Created a delegate function
Delegate Function FoundDeviceDelegate(data as integer, DeviceName as PInvoker.Marshal.ByteArrayPtr) as Boolean
Then I created a local function with the same signature
Private Function FoundDevice(data as integer, DeviceName as PInvoker.Marshal.ByteArrayPtr) as Boolean
Msgbox(DeviceName.ToString)
Return True
End Function
In my main code, I make the following declarations and calls
dim devhandler as assembly.FoundDeviceHandler = AddressOf FoundDevice
dim device as new assembly.FoundDevice(devhandler)
assembly.EnumDevices(INTERFACE,device,vbNull)
('assembly' is the reference to the external dll, 'INTERFACE' is a constant and 'device' expects a function with the two parameters - user and devicename)
I thought that the EnumDevices call would then pass back to the device reference which in turns calls the DeviceHandler which references the delegated function which would then output the device name.
What I have got is a pointer value on 'device' but I am struggling referencing this back to a device name. It is never executing the FoundDevice function to show the messagebox.
I have read so much that I think I have read too much surrounding delegates and marshalling etc that I am now struggling to get to the end which feels so close given that I have the pointer reference when I debug it.
If anyone can make sense of the above and provide any useful assistance, it would be very much appreciated.
I'm trying to write a User-Space Device driver to pull some data from a custom HID device. I'm do the following to store a reference of the device in the HID manage into a variable.
CFSetRef device = IOHIDManagerCopyDevices(HIDManager);
after this I do the following to register my callback which is setting up the report read from the device (another area I'm struggling with.)
IOHIDDeviceRegisterInputReportCallback(device, report, ReadDailyDataResonposeSize, Handle_IOHIDDeviceIOHIDReportCallback, NULL);
I'm getting an error in the above function on the reference to 'device' saying "Incompatible pointer types passing CFSetRef"
If I try to change the type that device is when creating it though I get another saying that it needs to be a CFSetRef. So I'm a little confused, anyone have any advice. I'm very new to C as well as working on Macs. The documentation has come off pretty terse to me thus far.
EDIT: Here Is a link to the rest of my code for reference.
http://pastebin.com/rFsHisdh
This is the signature of the IOHIDDeviceRegisterInputReportCallback function according to the documentation:
CF_EXPORT void IOHIDDeviceRegisterInputReportCallback(
IOHIDDeviceRef device,
uint8_t *report,
CFIndex reportLength,
IOHIDReportCallback callback,
void *context) AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
As you can see the first argument should be a IOHIDDeviceRef and you are passing in a CFSetRef which provide[s] support for the mathematical concept of a set as Martin R answer indicates.
To get the elements of the set and pass the device (if any) you should do the following:
CFSetRef devices = IOHIDManagerCopyDevices(HIDManager);
CFIndex size = CFSetGetCount(devices);
if(size > 0) {
CFTypeRef array[size]; // array of IOHIDDeviceRef
CFSetGetValues(devices, array);
IOHIDDeviceRegisterInputReportCallback((IOHIDDeviceRef)array[0], report, ReadDailyDataResonposeSize, Handle_IOHIDDeviceIOHIDReportCallback, NULL);
}
Hope it helps.
IOHIDManagerCopyDevices() returns a set of IOHIDDeviceRef elements.
You have to get one element from the set and pass that to
IOHIDDeviceRegisterInputReportCallback().
I ran into this problem. You were pasting from an Apple document that is no longer correct ( https://developer.apple.com/library/archive/technotes/tn2187/_index.html ). Your report variable is allocated in the wrong format, causing an memory error during runtime. Do the following:
uint8_t *report = (uint8_t *)malloc(reportSize);
IOHIDDeviceRegisterInputReportCallback(device, report, ReadDailyDataResonposeSize, Handle_IOHIDDeviceIOHIDReportCallback, NULL);```
I'm trying to build a small program that hosts vst effects and I would like to scan a folder for plugin dlls.
I know how to find all the dlls but now I have the following questions:
What is the best way to determine if a given dll is a vst plugin?
I tried to just see if the ddl exports the proper function and this works fine for plugins made with the more recent versions of the vst sdk since it exports a method called "VstPluginMain" but older versions export a rather generic "main" function.
How do I determine if the plugin is an effect or an instrument?
How do I scan vst shell plugins?
Shell plugins are basically dlls that somehow contain multiple effects. An example of this are the plugins made by Waves Audio http://www.waves.com/
ps: If there is a library that can do all of this for me please let me know.
How to determine a VST plugin?
Once you've found main/VSTPluginMain... call it!
If what's returned is NULL, it's not a VST.
If what's returned is a pointer to the bytes "VstP" (see VstInt32 magic; ///< must be #kEffectMagic ('VstP') in aeffect.h), then you have a VST.
The VSTPluginMain returns a pointer to an AEffect structure. You will need to look at this structure.
Effect or instrument? AEffect::flags | (effFlagsIsSynth = 1 << 8)
Shell VSTs are more complex:
Category will be kPlugCategShell
Support the "shellCategory" canDo.
Use effShellGetNextPlugin to enumerate.
To instance, respond to audioMasterCurrentId in your callback with the ID you want.
#Dave Gamble nailed it, but I wanted to add a few things on VST shell plugins, since they are a bit tricky to work with.
To determine if a VST is a shell plugin, send the effGetPlugCategory opcode to the plugin dispatcher. If it returns kPlugCategShell, then it's a shell plugin. To get the list of sub-plugins in the shell, you basically call effShellGetNextPlugin until it returns 0. Example code snippit (adapted from a working VST host):
// All this stuff should probably be set up far earlier in your code...
// This assumes that you have already opened the plugin and called VSTPluginMain()
typedef VstIntPtr (*Vst2xPluginDispatcherFunc)(AEffect *effect, VstInt32 opCode, VstInt32 index, VstIntPtr value, void *ptr, float opt);
Vst2xPluginDispatcherFunc dispatcher;
AEffect* plugin;
char nameBuffer[40];
while(true) {
memset(nameBuffer, 0, 40);
VstInt32 shellPluginId = dispatcher(pluginHandle, effShellGetNextPlugin, 0, 0, nameBuffer, 0.0f);
if(shellPluginId == 0 || nameBuffer[0] == '\0') {
break;
}
else {
// Do something with the name and ID
}
}
If you actually want to load a plugin in a VST shell, it's a bit trickier. First, your host needs to handle the audioMasterCurrentId opcode in the host callback. When you call the VST's VSTPluginMain() method to instantiate the plugin, it will call the host callback with this opcode and ask for the unique ID which should be loaded.
Because this callback is made before the main function returns (and hence, before it delivers an AEffect* to your host), that means that you probably will need to store the shell plugin ID to load in a global variable, since you will not be able to save a pointer to any meaningful data in void* user field of the AEffect struct in time for it to be passed back to you in the host callback.
If you want to develop your VST Host application in .NET take a look at VST.NET