2 * This file is part of the libCEC(R) library.
4 * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
5 * libCEC(R) is an original work, containing original code.
7 * libCEC(R) is a trademark of Pulse-Eight Limited.
9 * This program is dual-licensed; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 * Alternatively, you can license this library under a commercial license,
25 * please contact Pulse-Eight Licensing for more information.
27 * For more information contact:
28 * Pulse-Eight Licensing <license@pulse-eight.com>
29 * http://www.pulse-eight.com/
30 * http://www.pulse-eight.net/
33 #include "AdapterDetection.h"
34 #include "platform/os-dependent.h"
35 #include "util/StdString.h"
37 #if !defined(__WINDOWS__)
44 // the virtual COM port only shows up when requesting devices with the raw device guid!
45 static GUID USB_RAW_GUID
= { 0xA5DCBF10, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };
48 #define CEC_VID 0x2548
49 #define CEC_PID 0x1001
54 #if !defined(__WINDOWS__)
55 bool TranslateComPort(CStdString
&strString
)
57 CStdString
strTmp(strString
);
59 int iSlash
= strTmp
.Find('/');
62 strTmp
= strTmp
.Left(iSlash
);
64 strString
.Format("%s/%s:1.0/tty", strString
.c_str(), strTmp
.c_str());
71 bool FindComPort(CStdString
&strLocation
)
73 CStdString strPort
= strLocation
;
74 bool bReturn(!strPort
.IsEmpty());
75 CStdString
strConfigLocation(strLocation
);
76 if (TranslateComPort(strConfigLocation
))
79 struct dirent
*dirent
;
80 if((dir
= opendir(strConfigLocation
.c_str())) == NULL
)
83 while ((dirent
= readdir(dir
)) != NULL
)
85 if(strcmp((char*)dirent
->d_name
, "." ) != 0 && strcmp((char*)dirent
->d_name
, ".." ) != 0)
87 strPort
.Format("/dev/%s", dirent
->d_name
);
88 if (!strPort
.IsEmpty())
90 strLocation
= strPort
;
103 int CAdapterDetection::FindAdapters(vector
<cec_adapter
> &deviceList
, const char *strDevicePath
/* = NULL */)
107 #if !defined(__WINDOWS__)
109 if (!(udev
= udev_new()))
112 struct udev_enumerate
*enumerate
;
113 struct udev_list_entry
*devices
, *dev_list_entry
;
114 struct udev_device
*dev
;
115 enumerate
= udev_enumerate_new(udev
);
116 udev_enumerate_scan_devices(enumerate
);
117 devices
= udev_enumerate_get_list_entry(enumerate
);
118 udev_list_entry_foreach(dev_list_entry
, devices
)
121 strPath
= udev_list_entry_get_name(dev_list_entry
);
123 dev
= udev_device_new_from_syspath(udev
, strPath
);
127 dev
= udev_device_get_parent(udev_device_get_parent(dev
));
130 if (!udev_device_get_sysattr_value(dev
,"idVendor") || !udev_device_get_sysattr_value(dev
, "idProduct"))
132 udev_device_unref(dev
);
136 int iVendor
, iProduct
;
137 sscanf(udev_device_get_sysattr_value(dev
, "idVendor"), "%x", &iVendor
);
138 sscanf(udev_device_get_sysattr_value(dev
, "idProduct"), "%x", &iProduct
);
139 if (iVendor
== CEC_VID
&& iProduct
== CEC_PID
)
141 CStdString
strPath(udev_device_get_syspath(dev
));
142 if (strDevicePath
&& strcmp(strPath
.c_str(), strDevicePath
))
145 CStdString
strComm(strPath
);
146 if (FindComPort(strComm
))
148 cec_adapter foundDev
;
149 foundDev
.path
= strPath
;
150 foundDev
.comm
= strComm
;
151 deviceList
.push_back(foundDev
);
155 udev_device_unref(dev
);
158 udev_enumerate_unref(enumerate
);
162 DWORD required
= 0, iMemberIndex
= 0;
165 SP_DEVICE_INTERFACE_DATA deviceInterfaceData
;
166 deviceInterfaceData
.cbSize
= sizeof(SP_DEVICE_INTERFACE_DATA
);
168 SP_DEVINFO_DATA devInfoData
;
169 devInfoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
171 if ((hDevHandle
= SetupDiGetClassDevs(&USB_RAW_GUID
, 0, 0, DIGCF_PRESENT
| DIGCF_DEVICEINTERFACE
)) == INVALID_HANDLE_VALUE
)
175 TCHAR
*buffer
= NULL
;
176 PSP_DEVICE_INTERFACE_DETAIL_DATA devicedetailData
;
179 bResult
= SetupDiEnumDeviceInfo(hDevHandle
, iMemberIndex
, &devInfoData
);
182 bResult
= SetupDiEnumDeviceInterfaces(hDevHandle
, 0, &USB_RAW_GUID
, iMemberIndex
, &deviceInterfaceData
);
186 SetupDiDestroyDeviceInfoList(hDevHandle
);
193 BOOL bDetailResult
= false;
195 // As per MSDN, Get the required buffer size. Call SetupDiGetDeviceInterfaceDetail with a
196 // NULL DeviceInterfaceDetailData pointer, a DeviceInterfaceDetailDataSize of zero,
197 // and a valid RequiredSize variable. In response to such a call, this function returns
198 // the required buffer size at RequiredSize and fails with GetLastError returning
199 // ERROR_INSUFFICIENT_BUFFER.
200 // Allocate an appropriately sized buffer and call the function again to get the interface details.
202 SetupDiGetDeviceInterfaceDetail(hDevHandle
, &deviceInterfaceData
, NULL
, 0, &required
, NULL
);
204 buffer
= new TCHAR
[required
];
205 devicedetailData
= (PSP_DEVICE_INTERFACE_DETAIL_DATA
) buffer
;
206 devicedetailData
->cbSize
= sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA
);
207 nBufferSize
= required
;
210 bDetailResult
= SetupDiGetDeviceInterfaceDetail(hDevHandle
, &deviceInterfaceData
, devicedetailData
, nBufferSize
, &required
, NULL
);
214 if (strDevicePath
&& strcmp(strDevicePath
, devicedetailData
->DevicePath
) != 0)
217 CStdString strVendorId
;
218 CStdString strProductId
;
219 CStdString
strTmp(devicedetailData
->DevicePath
);
220 strVendorId
= strTmp
.substr(strTmp
.Find("vid_") + 4, 4);
221 strProductId
= strTmp
.substr(strTmp
.Find("pid_") + 4, 4);
222 if (strTmp
.Find("&mi_") >= 0 && strTmp
.Find("&mi_00") < 0)
225 int iVendor
, iProduct
;
226 sscanf(strVendorId
, "%x", &iVendor
);
227 sscanf(strProductId
, "%x", &iProduct
);
228 if (iVendor
!= CEC_VID
|| iProduct
!= CEC_PID
)
231 HKEY hDeviceKey
= SetupDiOpenDevRegKey(hDevHandle
, &devInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_QUERY_VALUE
);
235 TCHAR strPortName
[256];
236 strPortName
[0] = _T('\0');
237 DWORD dwSize
= sizeof(strPortName
);
240 /* search the registry */
241 if ((RegQueryValueEx(hDeviceKey
, _T("PortName"), NULL
, &dwType
, reinterpret_cast<LPBYTE
>(strPortName
), &dwSize
) == ERROR_SUCCESS
) && (dwType
== REG_SZ
))
243 if (_tcslen(strPortName
) > 3 && _tcsnicmp(strPortName
, _T("COM"), 3) == 0 &&
244 _ttoi(&(strPortName
[3])) > 0)
246 cec_adapter foundDev
;
247 foundDev
.path
= devicedetailData
->DevicePath
;
248 foundDev
.comm
= strPortName
;
249 deviceList
.push_back(foundDev
);
254 RegCloseKey(hDeviceKey
);