Files
giesCANne/SavvyCAN.pro
T
RefuhrandClaude Opus 5 3ae429ae48 feat: add gs_usb support on Windows
candleLight, CANable, CANnectivity and cantact adapters speak gs_usb. On
Linux and macOS the kernel driver exposes them as SocketCAN interfaces, so
SavvyCAN already reached them through Qt SerialBus. Windows has no such
driver, which left those adapters unusable there.

Add a GSUSBConnection that talks to the hardware directly over WinUSB:

- one connection per physical device, one SavvyCAN bus per CAN channel
- CAN FD including BRS, plus RTR, extended IDs and error frames
- known good bit timings for 16/48/80/160/170 MHz device clocks, with a
  generic solver for clocks the tables do not cover
- hardware timestamps, unwrapped across the 32 bit rollover and anchored
  to the host clock so they line up with the rest of SavvyCAN

gs_usb multiplexes every channel over a single USB bulk IN endpoint, so a
single reader thread drains it and hands frames to the connection thread in
batches, coalescing the wakeups. That keeps one producer on the lock free
queue, which the tx echo path already writes to.

Device scans skip adapters that a live connection holds. candle_dev_open()
shares the file handle and queues read URBs immediately, so probing a device
in use would consume frames the open connection is waiting for.

connections/candle_api is an unmodified copy of the candle Windows API, LGPL
3.0 rather than MIT and only compiled into Windows builds. See its README for
provenance.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XZnuZJ7zc3e8hk6C8bGDZN
2026-07-29 09:25:32 +02:00

314 lines
8.5 KiB
Prolog

#-------------------------------------------------
#
# Project created by QtCreator 2015-04-25T22:57:44
#
#-------------------------------------------------
!versionAtLeast(QT_VERSION, 5.14.0) {
error("Current version of Qt ($${QT_VERSION}) is too old, this project requires Qt 5.14 or newer")
}
QT = core gui printsupport qml serialbus serialport widgets help network opengl
CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG_OUTPUT
CONFIG += c++17
CONFIG += NO_UNIT_TESTS
DEFINES += QCUSTOMPLOT_USE_OPENGL
TARGET = SavvyCAN
TEMPLATE = app
QMAKE_INFO_PLIST = Info.plist.template
ICON = icons/SavvyIcon.icns
SOURCES += main.cpp\
canbridgewindow.cpp \
connections/canlogserver.cpp \
connections/canserver.cpp \
connections/lawicel_serial.cpp \
connections/mqtt_bus.cpp \
dbc/dbcnodeduplicateeditor.cpp \
framesenderobject.cpp \
mqtt/qmqtt_client.cpp \
mqtt/qmqtt_client_p.cpp \
mqtt/qmqtt_frame.cpp \
mqtt/qmqtt_message.cpp \
mqtt/qmqtt_network.cpp \
mqtt/qmqtt_router.cpp \
mqtt/qmqtt_routesubscription.cpp \
mqtt/qmqtt_socket.cpp \
mqtt/qmqtt_ssl_socket.cpp \
mqtt/qmqtt_timer.cpp \
mqtt/qmqtt_websocket.cpp \
mqtt/qmqtt_websocketiodevice.cpp \
qcpaxistickerhex.cpp \
re/dbccomparatorwindow.cpp \
mainwindow.cpp \
canframemodel.cpp \
simplecrypt.cpp \
triggerdialog.cpp \
utility.cpp \
qcustomplot.cpp \
frameplaybackwindow.cpp \
candatagrid.cpp \
framesenderwindow.cpp \
framefileio.cpp \
mainsettingsdialog.cpp \
scriptingwindow.cpp \
scriptcontainer.cpp \
canfilter.cpp \
can_structs.cpp \
motorcontrollerconfigwindow.cpp \
connections/canconnection.cpp \
connections/serialbusconnection.cpp \
connections/canconfactory.cpp \
connections/gvretserial.cpp \
connections/socketcand.cpp \
connections/canconmanager.cpp \
re/sniffer/snifferitem.cpp \
re/sniffer/sniffermodel.cpp \
re/sniffer/snifferwindow.cpp \
dbc/dbcmessageeditor.cpp \
dbc/dbc_classes.cpp \
dbc/dbchandler.cpp \
dbc/dbcloadsavewindow.cpp \
dbc/dbcmaineditor.cpp \
dbc/dbcnodeeditor.cpp \
dbc/dbcsignaleditor.cpp \
dbc/dbcnoderebaseeditor.cpp \
re/discretestatewindow.cpp \
re/filecomparatorwindow.cpp \
re/flowviewwindow.cpp \
re/frameinfowindow.cpp \
re/fuzzingwindow.cpp \
re/isotp_interpreterwindow.cpp \
re/rangestatewindow.cpp \
re/udsscanwindow.cpp \
connections/canbus.cpp \
connections/canconnectionmodel.cpp \
connections/connectionwindow.cpp \
re/graphingwindow.cpp \
re/newgraphdialog.cpp \
bisectwindow.cpp \
signalviewerwindow.cpp \
bus_protocols/isotp_handler.cpp \
bus_protocols/j1939_handler.cpp \
bus_protocols/uds_handler.cpp \
jsedit.cpp \
frameplaybackobject.cpp \
helpwindow.cpp \
blfhandler.cpp \
re/sniffer/SnifferDelegate.cpp \
connections/newconnectiondialog.cpp \
re/temporalgraphwindow.cpp \
re/udsfirmwareuploaderwindow.cpp \
filterutility.cpp \
pcaplite.cpp
HEADERS += mainwindow.h \
can_structs.h \
canbridgewindow.h \
canframemodel.h \
connections/canlogserver.h \
connections/canserver.h \
connections/lawicel_serial.h \
connections/socketcand.h \
connections/mqtt_bus.h \
dbc/dbcnodeduplicateeditor.h \
dbc/dbcnoderebaseeditor.h \
framesenderobject.h \
mqtt/qmqtt.h \
mqtt/qmqtt_client.h \
mqtt/qmqtt_client_p.h \
mqtt/qmqtt_frame.h \
mqtt/qmqtt_global.h \
mqtt/qmqtt_message.h \
mqtt/qmqtt_message_p.h \
mqtt/qmqtt_network_p.h \
mqtt/qmqtt_networkinterface.h \
mqtt/qmqtt_routedmessage.h \
mqtt/qmqtt_router.h \
mqtt/qmqtt_routesubscription.h \
mqtt/qmqtt_socket_p.h \
mqtt/qmqtt_socketinterface.h \
mqtt/qmqtt_ssl_socket_p.h \
mqtt/qmqtt_timer_p.h \
mqtt/qmqtt_timerinterface.h \
mqtt/qmqtt_websocket_p.h \
mqtt/qmqtt_websocketiodevice_p.h \
qcpaxistickerhex.h \
re/dbccomparatorwindow.h \
simplecrypt.h \
triggerdialog.h \
utility.h \
qcustomplot.h \
frameplaybackwindow.h \
candatagrid.h \
framesenderwindow.h \
can_trigger_structs.h \
framefileio.h \
config.h \
mainsettingsdialog.h \
scriptingwindow.h \
scriptcontainer.h \
canfilter.h \
utils/lfqueue.h \
motorcontrollerconfigwindow.h \
connections/canconnection.h \
connections/serialbusconnection.h \
connections/canconconst.h \
connections/canconfactory.h \
connections/gvretserial.h \
connections/canconmanager.h \
re/sniffer/snifferitem.h \
re/sniffer/sniffermodel.h \
re/sniffer/snifferwindow.h \
dbc/dbc_classes.h \
dbc/dbchandler.h \
dbc/dbcloadsavewindow.h \
dbc/dbcmaineditor.h \
dbc/dbcsignaleditor.h \
dbc/dbcmessageeditor.h \
dbc/dbcnodeeditor.h \
re/discretestatewindow.h \
re/filecomparatorwindow.h \
re/flowviewwindow.h \
re/frameinfowindow.h \
re/fuzzingwindow.h \
re/isotp_interpreterwindow.h \
re/rangestatewindow.h \
re/udsscanwindow.h \
connections/canbus.h \
connections/canconnectionmodel.h \
connections/connectionwindow.h \
re/graphingwindow.h \
re/newgraphdialog.h \
bisectwindow.h \
signalviewerwindow.h \
bus_protocols/isotp_handler.h \
bus_protocols/j1939_handler.h \
bus_protocols/uds_handler.h \
bus_protocols/isotp_message.h \
jsedit.h \
frameplaybackobject.h \
helpwindow.h \
blfhandler.h \
re/sniffer/SnifferDelegate.h \
connections/newconnectiondialog.h \
re/temporalgraphwindow.h \
re/udsfirmwareuploaderwindow.h \
filterutility.h \
pcaplite.h
FORMS += ui/candatagrid.ui \
triggerdialog.ui \
ui/canbridgewindow.ui \
ui/dbcnodeduplicateeditor.ui \
ui/dbccomparatorwindow.ui \
ui/dbcmessageeditor.ui \
ui/connectionwindow.ui \
ui/dbcloadsavewindow.ui \
ui/dbcmaineditor.ui \
ui/dbcnoderebaseeditor.ui \
ui/dbcsignaleditor.ui \
ui/dbcnodeeditor.ui \
ui/discretestatewindow.ui \
ui/filecomparatorwindow.ui \
ui/flowviewwindow.ui \
ui/frameinfowindow.ui \
ui/frameplaybackwindow.ui \
ui/framesenderwindow.ui \
ui/fuzzingwindow.ui \
ui/graphingwindow.ui \
ui/isotp_interpreterwindow.ui \
ui/mainsettingsdialog.ui \
ui/mainwindow.ui \
ui/motorcontrollerconfigwindow.ui \
ui/newgraphdialog.ui \
ui/rangestatewindow.ui \
ui/scriptingwindow.ui \
ui/snifferwindow.ui \
ui/udsscanwindow.ui \
ui/bisectwindow.ui \
ui/signalviewerwindow.ui \
ui/helpwindow.ui \
ui/newconnectiondialog.ui \
ui/temporalgraphwindow.ui \
ui/udsfirmwareuploaderwindow.ui
RESOURCES += \
icons.qrc \
images.qrc
win32-msvc* {
LIBS += opengl32.lib
}
win32-g++ {
LIBS += libopengl32
}
# gs_usb (candleLight / CANable / CANnectivity) support.
# Windows only - everywhere else these devices are driven by the kernel gs_usb module and
# show up as regular SocketCAN interfaces.
# connections/candle_api is LGPL-3.0, see connections/candle_api/README.md.
win32 {
SOURCES += connections/gs_usb.cpp \
connections/candle_api/candle.c \
connections/candle_api/candle_ctrl_req.c
HEADERS += connections/gs_usb.h \
connections/candle_api/candle.h \
connections/candle_api/candle_ctrl_req.h \
connections/candle_api/candle_defs.h \
connections/candle_api/ch_9.h
#lower case names so this also links with a case sensitive MinGW cross toolchain
LIBS += -lsetupapi -lole32 -lwinusb
# the candle API calls the TCHAR flavour of the setupapi/strsafe functions with wide strings
DEFINES += UNICODE _UNICODE
}
# the candle API is C99/C11, the rest of the project is C++ only so this affects nothing else
win32-g++:QMAKE_CFLAGS += -std=gnu11
win32-msvc*:QMAKE_CFLAGS += /std:c11
unix {
isEmpty(PREFIX) {
PREFIX=/usr/local
}
target.path = $$PREFIX/bin
shortcutfiles.files=SavvyCAN.desktop
shortcutfiles.path = $$PREFIX/share/applications
INSTALLS += shortcutfiles
DISTFILES += SavvyCAN.desktop
}
windows {
RC_ICONS=icons/SavvyIcon.ico
}
examplefiles.files=examples
examplefiles.path = $$PREFIX/share/savvycan/examples
INSTALLS += examplefiles
iconfiles.files=icons
iconfiles.path = $$PREFIX/share
INSTALLS += iconfiles
helpfiles.files=help/*
helpfiles.path = $$PREFIX/bin/help
INSTALLS += helpfiles
INSTALLS += target
TRANSLATIONS += \
translations/SavvyCAN_en.ts \
translations/SavvyCAN_pt_BR.ts
DISTFILES += \
translations/pt_BR.qph