Skip to content

Commit

Permalink
support the new grid on windows
Browse files Browse the repository at this point in the history
  • Loading branch information
artfwo committed Jun 10, 2021
1 parent 51dbdc4 commit 6d16ba1
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 114 deletions.
159 changes: 45 additions & 114 deletions src/serialosc-detector/windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,21 @@
#include <assert.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdbool.h>

#include <winsock2.h>
#include <windows.h>
#include <process.h>
#include <winreg.h>
#include <dbt.h>
#include <io.h>
#include <setupapi.h>

#include <serialosc/serialosc.h>
#include <serialosc/ipc.h>

#define FTDI_REG_PATH "SYSTEM\\CurrentControlSet\\Enum\\FTDIBUS"
static GUID vcp_guid = {0x86e0d1e0L, 0x8089, 0x11d0,
{0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73}};

struct detector_state {
HANDLE to_supervisor;
Expand Down Expand Up @@ -66,136 +69,67 @@ send_connect(const struct detector_state *state, char *port)
WriteFile(state->to_supervisor, buf, bufsiz, &written, NULL);
}

static int
scan_connected_devices(const struct detector_state *state)
{
HKEY key, subkey;
char subkey_name[MAX_PATH], *subkey_path;
unsigned char port_name[64];
DWORD klen, plen, ptype;
int i = 0;

switch (RegOpenKeyEx(HKEY_LOCAL_MACHINE, FTDI_REG_PATH,
0, KEY_READ, &key)) {
case ERROR_SUCCESS:
/* ERROR: request was (unexpectedly) successful */
break;

case ERROR_FILE_NOT_FOUND:
/* print message about needing the FTDI driver maybe? */
/* fall through also */
default:
return 1;
}

for (;;) {
klen = sizeof(subkey_name) / sizeof(char);

switch (RegEnumKeyEx(key, i++, subkey_name, &klen,
NULL, NULL, NULL, NULL)) {
case ERROR_MORE_DATA:
case ERROR_SUCCESS:
break;

default:
goto done;
}

subkey_path = s_asprintf("%s\\%s\\0000\\Device Parameters",
FTDI_REG_PATH, subkey_name);

switch (RegOpenKeyEx(HKEY_LOCAL_MACHINE, subkey_path,
0, KEY_READ, &subkey)) {
case ERROR_SUCCESS:
break;

default:
free(subkey_path);
continue;
}

free(subkey_path);
static bool
get_device_port_name(char *dst, size_t dst_size, HDEVINFO hdevinfo, SP_DEVINFO_DATA *devinfo) {
DWORD plen, ptype;
HKEY hkey;
LSTATUS status;

plen = sizeof(port_name) / sizeof(char);
ptype = REG_SZ;
switch (RegQueryValueEx(subkey, "PortName", 0, &ptype,
port_name, &plen)) {
case ERROR_SUCCESS:
port_name[plen] = '\0';
break;
plen = dst_size;
ptype = REG_SZ;

default:
goto next;
}
hkey = SetupDiOpenDevRegKey(hdevinfo, devinfo, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
status = RegQueryValueEx(hkey, "PortName", NULL, &ptype, (unsigned char *) dst, &plen);

send_connect(state, (char *) port_name);
if (status == ERROR_SUCCESS) {
dst[plen] = '\0';

next:
RegCloseKey(subkey);
RegCloseKey(hkey);
return true;
}

done:
RegCloseKey(key);
return 0;
RegCloseKey(hkey);
return false;
}


static int
ftdishit_to_port(char *dst, size_t dst_size, const char *bullshit)
scan_connected_devices(const struct detector_state *state)
{
char *subkey_path, *port;
DWORD plen, ptype;
HKEY subkey;
HDEVINFO hdevinfo;
SP_DEVINFO_DATA devinfo;
int di;

if (!(bullshit = strchr(bullshit, '#')))
return -1;
hdevinfo = SetupDiGetClassDevs(&vcp_guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

if (!(port = strchr(++bullshit, '#')))
return -1;

*port = '\0';

subkey_path = s_asprintf(FTDI_REG_PATH "\\%s\\0000\\Device Parameters",
bullshit);

switch (RegOpenKeyEx(
HKEY_LOCAL_MACHINE, subkey_path,
0, KEY_READ, &subkey)) {
case ERROR_SUCCESS:
break;

default:
free(subkey_path);
return -1;
if (hdevinfo == INVALID_HANDLE_VALUE) {
fprintf(stderr, "serialosc: SetupDiGetClassDevs() failed.\n");
return 1;
}

free(subkey_path);
devinfo.cbSize = sizeof(SP_DEVINFO_DATA);
di = 0;

plen = dst_size;
ptype = REG_SZ;
switch (RegQueryValueEx(subkey, "PortName", 0, &ptype,
(unsigned char *) dst, &plen)) {
case ERROR_SUCCESS:
dst[plen] = '\0';
break;
while (SetupDiEnumDeviceInfo(hdevinfo, di, &devinfo)) {
char port_name[64];

default:
RegCloseKey(subkey);
return -1;
if (get_device_port_name(port_name, sizeof(port_name), hdevinfo, &devinfo)) {
send_connect(state, (char *) port_name);
}

di++;
}

RegCloseKey(subkey);
return 0;
}

static int
init_device_notification(struct detector_state *state)
{
DEV_BROADCAST_DEVICEINTERFACE filter;
GUID vcp_guid = {0x86e0d1e0L, 0x8089, 0x11d0,
{0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73}};

filter.dbcc_size = sizeof(filter);
filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
filter.dbcc_devicetype = DBT_DEVTYP_PORT;
filter.dbcc_reserved = 0;
filter.dbcc_classguid = vcp_guid;
filter.dbcc_name[0] = '\0';
Expand All @@ -218,20 +152,17 @@ static void
handle_device_arrival(struct detector_state *state,
DEV_BROADCAST_DEVICEINTERFACE *dev)
{
char devname[256], port[64];
char port_name[64];
DEV_BROADCAST_PORT *dev_port;

/* XXX: we could theoretically rip out all this FTDI-specific nonsense
* and just get port notifications, but win32 libmonome only knows
* how to get serial numbers from FTDI devices anyway so there's
* no real win for that change. */
if (dev->dbcc_devicetype != DBT_DEVTYP_DEVICEINTERFACE)
if (dev->dbcc_devicetype != DBT_DEVTYP_PORT)
return;

wcstombs(devname, (void *) dev->dbcc_name, sizeof(devname));
if (ftdishit_to_port(port, sizeof(port), devname))
return;
dev_port = (DEV_BROADCAST_PORT *) dev;

wcstombs(port_name, (void *) dev_port->dbcp_name, sizeof(port_name));

send_connect(state, port);
send_connect(state, port_name);
}

static LRESULT CALLBACK
Expand Down
1 change: 1 addition & 0 deletions wscript
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ def configure(conf):

conf.env.append_unique("LIBPATH", conf.env.LIBDIR)
conf.env.append_unique("CFLAGS", conf.env.CPPPATH_ST % conf.env.INCLUDEDIR)
conf.env.append_unique("LIB", ['setupapi'])

if conf.options.host:
conf.env.append_unique("LIBPATH", conf.env.PREFIX + '/lib')
Expand Down

0 comments on commit 6d16ba1

Please sign in to comment.