summaryrefslogtreecommitdiff
path: root/src/sdbwinapi/sdb_helper_routines.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sdbwinapi/sdb_helper_routines.cpp')
-rw-r--r--src/sdbwinapi/sdb_helper_routines.cpp276
1 files changed, 276 insertions, 0 deletions
diff --git a/src/sdbwinapi/sdb_helper_routines.cpp b/src/sdbwinapi/sdb_helper_routines.cpp
new file mode 100644
index 0000000..4dbff40
--- /dev/null
+++ b/src/sdbwinapi/sdb_helper_routines.cpp
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+ This file consists of implementation of helper routines used
+ in the API.
+*/
+
+#include "stdafx.h"
+#include "sdb_api.h"
+#include "sdb_api_legacy.h"
+#include "sdb_helper_routines.h"
+#include "sdb_interface_enum.h"
+
+bool GetSDKComplientParam(SdbOpenAccessType access_type,
+ SdbOpenSharingMode sharing_mode,
+ ULONG* desired_access,
+ ULONG* desired_sharing) {
+ if (NULL != desired_access) {
+ switch (access_type) {
+ case SdbOpenAccessTypeReadWrite:
+ *desired_access = GENERIC_READ | GENERIC_WRITE;
+ break;
+
+ case SdbOpenAccessTypeRead:
+ *desired_access = GENERIC_READ;
+ break;
+
+ case SdbOpenAccessTypeWrite:
+ *desired_access = GENERIC_WRITE;
+ break;
+
+ case SdbOpenAccessTypeQueryInfo:
+ *desired_access = FILE_READ_ATTRIBUTES | FILE_READ_EA;
+ break;
+
+ default:
+ SetLastError(ERROR_INVALID_ACCESS);
+ return false;
+ }
+ }
+
+ if (NULL != desired_sharing) {
+ switch (sharing_mode) {
+ case SdbOpenSharingModeReadWrite:
+ *desired_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ break;
+
+ case SdbOpenSharingModeRead:
+ *desired_sharing = FILE_SHARE_READ;
+ break;
+
+ case SdbOpenSharingModeWrite:
+ *desired_sharing = FILE_SHARE_WRITE;
+ break;
+
+ case SdbOpenSharingModeExclusive:
+ *desired_sharing = 0;
+ break;
+
+ default:
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool EnumerateDeviceInterfaces(HDEVINFO hardware_dev_info,
+ GUID class_id,
+ bool exclude_removed,
+ bool active_only,
+ SdbEnumInterfaceArray* interfaces) {
+ SdbEnumInterfaceArray tmp;
+ bool ret = false;
+
+ // Enumerate interfaces on this device
+ for (ULONG index = 0; ; index++) {
+ SP_DEVICE_INTERFACE_DATA interface_data;
+ interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+
+ // SetupDiEnumDeviceInterfaces() returns information about device
+ // interfaces exposed by one or more devices defined by our interface
+ // class. Each call returns information about one interface. The routine
+ // can be called repeatedly to get information about several interfaces
+ // exposed by one or more devices.
+ if (SetupDiEnumDeviceInterfaces(hardware_dev_info,
+ 0,
+ &class_id,
+ index,
+ &interface_data)) {
+ // Satisfy "exclude removed" and "active only" filters.
+ if ((!exclude_removed || (0 == (interface_data.Flags & SPINT_REMOVED))) &&
+ (!active_only || (interface_data.Flags & SPINT_ACTIVE))) {
+ std::wstring dev_name;
+
+ if (GetUsbDeviceName(hardware_dev_info, &interface_data, &dev_name)) {
+ try {
+ // Add new entry to the array
+ tmp.push_back(SdbInstanceEnumEntry(dev_name.c_str(),
+ interface_data.InterfaceClassGuid,
+ interface_data.Flags));
+ } catch (... ) {
+ SetLastError(ERROR_OUTOFMEMORY);
+ break;
+ }
+ } else {
+ // Something went wrong in getting device name
+ break;
+ }
+ }
+ } else {
+ if (ERROR_NO_MORE_ITEMS == GetLastError()) {
+ // There are no more items in the list. Enum is completed.
+ ret = true;
+ break;
+ } else {
+ // Something went wrong in SDK enum
+ break;
+ }
+ }
+ }
+
+ // On success, swap temp array with the returning one
+ if (ret)
+ interfaces->swap(tmp);
+
+ return ret;
+}
+
+bool EnumerateDeviceInterfaces(GUID class_id,
+ ULONG flags,
+ bool exclude_removed,
+ bool active_only,
+ SdbEnumInterfaceArray* interfaces) {
+ // Open a handle to the plug and play dev node.
+ // SetupDiGetClassDevs() returns a device information set that
+ // contains info on all installed devices of a specified class.
+ HDEVINFO hardware_dev_info =
+ SetupDiGetClassDevs(&class_id, NULL, NULL, flags);
+
+ bool ret = false;
+
+ if (INVALID_HANDLE_VALUE != hardware_dev_info) {
+ // Do the enum
+ ret = EnumerateDeviceInterfaces(hardware_dev_info,
+ class_id,
+ exclude_removed,
+ active_only,
+ interfaces);
+
+ // Preserve last error accross hardware_dev_info destruction
+ ULONG error_to_report = ret ? NO_ERROR : GetLastError();
+
+ SetupDiDestroyDeviceInfoList(hardware_dev_info);
+
+ if (NO_ERROR != error_to_report)
+ SetLastError(error_to_report);
+ }
+
+ return ret;
+}
+
+bool GetUsbDeviceDetails(
+ HDEVINFO hardware_dev_info,
+ PSP_DEVICE_INTERFACE_DATA dev_info_data,
+ PSP_DEVICE_INTERFACE_DETAIL_DATA* dev_info_detail_data) {
+ ULONG required_len = 0;
+
+ // First query for the structure size. At this point we expect this call
+ // to fail with ERROR_INSUFFICIENT_BUFFER error code.
+ if (SetupDiGetDeviceInterfaceDetail(hardware_dev_info,
+ dev_info_data,
+ NULL,
+ 0,
+ &required_len,
+ NULL)) {
+ return false;
+ }
+
+ if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
+ return false;
+
+ // Allocate buffer for the structure
+ PSP_DEVICE_INTERFACE_DETAIL_DATA buffer =
+ reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(malloc(required_len));
+
+ if (NULL == buffer) {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return false;
+ }
+
+ buffer->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
+
+ // Retrieve the information from Plug and Play.
+ if (SetupDiGetDeviceInterfaceDetail(hardware_dev_info,
+ dev_info_data,
+ buffer,
+ required_len,
+ &required_len,
+ NULL)) {
+ *dev_info_detail_data = buffer;
+ return true;
+ } else {
+ // Free the buffer if this call failed
+ free(buffer);
+
+ return false;
+ }
+}
+
+bool GetUsbDeviceName(HDEVINFO hardware_dev_info,
+ PSP_DEVICE_INTERFACE_DATA dev_info_data,
+ std::wstring* name) {
+ PSP_DEVICE_INTERFACE_DETAIL_DATA func_class_dev_data = NULL;
+ if (!GetUsbDeviceDetails(hardware_dev_info,
+ dev_info_data,
+ &func_class_dev_data)) {
+ return false;
+ }
+
+ try {
+ *name = func_class_dev_data->DevicePath;
+ } catch (...) {
+ SetLastError(ERROR_OUTOFMEMORY);
+ }
+
+ free(func_class_dev_data);
+
+ return !name->empty();
+}
+
+bool IsLegacyInterface(const wchar_t* interface_name) {
+ // Open USB device for this intefface
+ HANDLE usb_device_handle = CreateFile(interface_name,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+ if (INVALID_HANDLE_VALUE == usb_device_handle) {
+ printf("INVALID_HANDLE_VALUE == usb_device_handle\n");
+ return NULL;
+ }
+ printf("INVALID_HANDLE_VALUE != usb_device_handle\n");
+ // Try to issue SDB_IOCTL_GET_USB_DEVICE_DESCRIPTOR IOCTL that is supported
+ // by the legacy driver, but is not implemented in the WinUsb driver.
+ DWORD ret_bytes = 0;
+ USB_DEVICE_DESCRIPTOR descriptor;
+ BOOL ret = DeviceIoControl(usb_device_handle,
+ SDB_IOCTL_GET_USB_DEVICE_DESCRIPTOR,
+ NULL, 0,
+ &descriptor,
+ sizeof(descriptor),
+ &ret_bytes,
+ NULL);
+ ::CloseHandle(usb_device_handle);
+
+ // If IOCTL succeeded we've got legacy driver underneath.
+ return ret ? true : false;
+}