问题
For any good sockets programmers out there:
Is it possible to enumerate multiple active IrDA devices connected to the PC through USB ports using sockets?
If so, how? This is really my main question. The remainder of the post rounds out the details and describes what I have tried.
I am developing an application on Windows 7, using Microsoft SDK and an ANSI C compiler. The application design requires it to detect any IrDA devices in range, connect using sockets, and communicate to multiple devices through multiple IrDA dongles (one dongle per device), each dongle is connected to the PC via USB. Note: Using virtual COM ports is to be avoided.
I have successfully used sockets calls to enumerate, create a socket, connect and communicate to a single IrDA device. This works well.
However, I am not sure how to setup the code to successfully enumerate multiple IrDA devices.
So far, I am only able to connect to one device at a time. Even though It is clear that Windows is "Discovering" three IrDA dongles, as seen in the following images - overall scenario (1st image), device manager (2nd image), device properties (3rd image):
Illustration 1: Overall scenario:
Illustration 2: From Device Manager:
Illustration 3: Properties of each 'found' IrDA device
(second two arrows are included to show Port-Hub address of all three devices)
The simple scenario I am using:
(some of the variable names are different from scenario description above, but are consistent within the code)
1st - I place two active IrDA devices sitting in front of two dongles (separated by several feet, so there is no signal ambiguity between the two devices) Using only 2 for now to keep it simple.
2nd - I create 2 IrDA sockets, get two handles using: socket(AF_IRDA, SOCK_STREAM, 0);
3rd - I call:
if ((errorCode = getsockopt(gSocketHandle[0],
SOL_IRLMP,
IRLMP_ENUMDEVICES,
(char*)pDeviceList,
&deviceListLength)) == SOCKET_ERROR)
4th - I then populate the destinIrdaDeviceAddr with the new information in pDeviceList and
memcpy(&destinIrdaDeviceAddr.irdaDeviceID[0], &pDevList->Device[0].irdaDeviceID[0], 4);
5th - call:
connect(gSocketHandle[0],(const struct sockaddr*)&destinIrdaDeviceAddr,(int) sizeof(SOCKADDR_IRDA))
After this call completes, I repeat (step 3 ) using the next socket handle (gSocketHandle1). But instead of getting another enumerated device, I just get the same device. This second call results in the same information in pDeviceList as was in the first device. Stated another way, I am only enumerating a single device.
Here is the code attempting to enumerate two IrDA devices:
// adapted from http://msdn.microsoft.com/en-us/library/windows/desktop/ms691754(v=vs.85).aspx
#include <windows.h>
#include <winsock2.h>
#include <ansi_c.h>
#include <af_irda.h>
#pragma comment(lib, "ws2_32.lib")
#define DEVICE_LIST_LEN 5
#define MAX_RETRIES 10
SOCKET conn1, conn2;
char* iGetLastErrorText(DWORD nErrorCode);
void main()
{
WSADATA wsaData;
// discovery buffer
BYTE DevListBuff[sizeof(DEVICELIST) - sizeof(IRDA_DEVICE_INFO) +
(sizeof(IRDA_DEVICE_INFO) * DEVICE_LIST_LEN)];
int DevListLen = sizeof(DevListBuff);
PDEVICELIST pDevList = (PDEVICELIST) &DevListBuff;
int DevNum, i;
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
{
printf("IR-Client: Unable to load the Winsock library!\n");
getchar();
}
else printf("IR-Client: Winsock library 2.2 loaded!\n");
SOCKADDR_IRDA DstAddrIR = { AF_IRDA, 0, 0, 0, 0, "IrDA:IrCOMM" };
//Create socket handles
if ((conn1 = socket(AF_IRDA, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
// WSAGetLastError
}
if ((conn2 = socket(AF_IRDA, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
// WSAGetLastError
}
/////////////////////////
//enumerate devices - socket conn1
/////////////////////////
// search for the peer device
pDevList->numDevice = 0;
if (getsockopt(conn1, SOL_IRLMP, IRLMP_ENUMDEVICES, (CHAR *) pDevList, &DevListLen)
== SOCKET_ERROR)
{
// WSAGetLastError
}
if (pDevList->numDevice == 0)
{
printf("no devices found\n");
}
// assume first device, we should have a common dialog here
memcpy(&DstAddrIR.irdaDeviceID[0], &pDevList->Device[0].irdaDeviceID[0], 4);
printf("%x\n", &DstAddrIR.irdaDeviceID[0]);
// nothing special for IrCOMM from now on...
if (connect(conn1, (const struct sockaddr *) &DstAddrIR, sizeof(SOCKADDR_IRDA))
== SOCKET_ERROR)
{
// WSAGetLastError
}
/////////////////////////
//enumerate devices - socket conn2
/////////////////////////
// search for the peer device
pDevList->numDevice = 0;
if (getsockopt(conn2, SOL_IRLMP, IRLMP_ENUMDEVICES, (CHAR *) pDevList, &DevListLen) == SOCKET_ERROR)
{
// WSAGetLastError
}
if (pDevList->numDevice == 0)
{
printf("no devices found\n");
}
// assume first device, we should have a common dialog here
memcpy(&DstAddrIR.irdaDeviceID[0], &pDevList->Device[0].irdaDeviceID[0], 4);
printf("%x\n", &DstAddrIR.irdaDeviceID[0]);
// nothing special for IrCOMM from now on...
if (connect(conn2, (const struct sockaddr *) &DstAddrIR, sizeof(SOCKADDR_IRDA))
== SOCKET_ERROR)
{
// WSAGetLastError
}
getchar(); //to view irdaDeviceID
}
char* iGetLastErrorText(DWORD nErrorCode)
{
char* msg;
// Ask Windows to prepare a standard message for a GetLastError() code:
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, nErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL);
// Return the message
if (!msg)
return("Unknown error");
else
return(msg);
}
The following image shows values for ->irdaDeviceID[0]. Both values are the same indicating only one device was enumerated.
来源:https://stackoverflow.com/questions/17710790/discover-multiple-usb-irda-devices-open-and-connect-a-socket-for-each