diff --git a/src/platforms/hosted/Makefile.inc b/src/platforms/hosted/Makefile.inc index c43c5d3..b73f6d7 100644 --- a/src/platforms/hosted/Makefile.inc +++ b/src/platforms/hosted/Makefile.inc @@ -17,10 +17,16 @@ CFLAGS += -fsanitize=address LDFLAGS += -lasan endif else ifneq (, $(findstring mingw, $(SYS))) +# Build for windows versions Vista, and above, where the +# 'SetupDiGetDevicePropertyW()' function is available +CFLAGS += -D_WIN32_WINNT=0x600 SRC += serial_win.c LDFLAGS += -lws2_32 LDFLAGS += -lsetupapi else ifneq (, $(findstring cygwin, $(SYS))) +# Build for windows versions Vista, and above, where the +# 'SetupDiGetDevicePropertyW()' function is available +CFLAGS += -D_WIN32_WINNT=0x600 SRC += serial_win.c LDFLAGS += -lws2_32 LDFLAGS += -lsetupapi diff --git a/src/platforms/hosted/bmp_serial.c b/src/platforms/hosted/bmp_serial.c index 89fff2a..098c147 100644 --- a/src/platforms/hosted/bmp_serial.c +++ b/src/platforms/hosted/bmp_serial.c @@ -44,12 +44,115 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info) return -1; } #elif defined(__WIN32__) || defined(__CYGWIN__) + + +/* This source has been used as an example: + * https://stackoverflow.com/questions/3438366/setupdigetdeviceproperty-usage-example */ + +#include +#include +#include // for MAX_DEVICE_ID_LEN, CM_Get_Parent and CM_Get_Device_ID +#include +#include + +/* include DEVPKEY_Device_BusReportedDeviceDesc from WinDDK\7600.16385.1\inc\api\devpropdef.h */ +#ifdef DEFINE_DEVPROPKEY +#undef DEFINE_DEVPROPKEY +#endif +#define DEFINE_DEVPROPKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid) const DEVPROPKEY DECLSPEC_SELECTANY name = { { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }, pid } + +/* include DEVPKEY_Device_BusReportedDeviceDesc from WinDDK\7600.16385.1\inc\api\devpkey.h */ +DEFINE_DEVPROPKEY(DEVPKEY_Device_BusReportedDeviceDesc, 0x540b947e, 0x8b40, 0x45bc, 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 4); // DEVPROP_TYPE_STRING + +/* List all USB devices with some additional information. + * Unfortunately, this code is quite ugly. */ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info) { - (void)cl_opts; - (void)info; - return -1; + unsigned i; + DWORD dwSize; + DEVPROPTYPE ulPropertyType; + CONFIGRET status; + HDEVINFO hDevInfo; + SP_DEVINFO_DATA DeviceInfoData; + TCHAR szDeviceInstanceID [MAX_DEVICE_ID_LEN]; + WCHAR busReportedDeviceSesc[4096]; + int probes_found = 0; + bool is_printing_probes_info = cl_opts->opt_list_only != 0; + + info->bmp_type = BMP_TYPE_BMP; + + hDevInfo = SetupDiGetClassDevs (0, "USB", NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT); + if (hDevInfo == INVALID_HANDLE_VALUE) + return -1; +print_probes_info: + for (i = 0; ; i++) { + char serial_number[sizeof info->serial]; + DeviceInfoData.cbSize = sizeof (DeviceInfoData); + if (!SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData)) + break; + + status = CM_Get_Device_ID(DeviceInfoData.DevInst, szDeviceInstanceID , MAX_PATH, 0); + if (status != CR_SUCCESS) + continue; + + if (!sscanf(szDeviceInstanceID, "USB\\VID_1D50&PID_6018\\%s", serial_number)) + continue; + + if (SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_Device_BusReportedDeviceDesc, + &ulPropertyType, (BYTE*)busReportedDeviceSesc, sizeof busReportedDeviceSesc, &dwSize, 0)) + { + probes_found ++; + if (is_printing_probes_info) + { + DEBUG_WARN("%2d: %s, %ls\n", probes_found, + serial_number, busReportedDeviceSesc); + } + else + { + bool probe_identified = true; + if ((cl_opts->opt_serial && strstr(serial_number, cl_opts->opt_serial)) || + (cl_opts->opt_position && cl_opts->opt_position == probes_found) || + /* Special case for the very first probe found. */ + (probe_identified = false, probes_found == 1)) { + + strncpy(info->serial, serial_number, sizeof info->serial); + strncpy(info->manufacturer, "BMP", sizeof info->manufacturer); + snprintf(info->product, sizeof info->product, "%ls", busReportedDeviceSesc); + /* Don't bother to parse the version string. It is a part of the + * product description string. It seems that at the moment it + * is only being used to print a version string in response + * to the 'monitor version' command, so it doesn't really matter + * if the version string is printed as a part of the product string, + * or as a separate string, the result is pretty much the same. */ + info->version[0] = 0; + if (probe_identified) + return 0; + } + } + } + } + if (is_printing_probes_info) + return 1; + if (probes_found == 1) + /* Exactly one probe found. Its information has already been filled + * in the detection loop, so use this probe. */ + return 0; + if (probes_found < 1) { + DEBUG_WARN("No BMP probe found\n"); + return -1; + } + /* Otherwise, if this line is reached, then more than one probe has been found, + * and no probe was identified as selected by the user. + * Restart the identification loop, this time printing the probe information, + * and then return. */ + DEBUG_WARN("%d debuggers found!\nSelect with -P , or " + "-s <(partial)serial no.>\n", + probes_found); + probes_found = 0; + is_printing_probes_info = true; + goto print_probes_info; } + #else #define BMP_IDSTRING "usb-Black_Sphere_Technologies_Black_Magic_Probe" #define DEVICE_BY_ID "/dev/serial/by-id/" diff --git a/src/platforms/pc/cl_utils.c b/src/platforms/pc/cl_utils.c index d19b921..e27fe59 100644 --- a/src/platforms/pc/cl_utils.c +++ b/src/platforms/pc/cl_utils.c @@ -123,10 +123,10 @@ static void cl_help(char **argv) DEBUG_WARN("\t\t\t 1 = INFO, 2 = GDB, 4 = TARGET, 8 = PROBE, 16 = WIRE\n"); DEBUG_WARN("Probe selection arguments:\n"); DEBUG_WARN("\t-d \"path\"\t: Use serial BMP device at "); -#if HOSTED_BMP_ONLY == 1 +#if HOSTED_BMP_ONLY == 1 && defined(__APPLE__) DEBUG_WARN("\n"); #else - DEBUG_WARN(" Deprecated!\n"); + DEBUG_WARN(". Deprecated!\n"); #endif DEBUG_WARN("\t-P \t: Use debugger found at position \n"); DEBUG_WARN("\t-n \t: Use target device found at position \n");