mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-13 16:18:42 +00:00
Native ANT+ part 2 - USB2 Support and minor improvements
This patch adds support for the Garmin USB2 stick using libusb-win library. Instructions are included in gcconfig.pri.in for configuring and installing the neccessary libs. To enable support for USB1 and USB2 support in the same binary stubs are created when UsbXpress/Libusb are not available and the device i/o attempts to use USB2 before falling back to USB1. Since I was also in the middle of some coding changes I merged my developments (Mark) with Darren's patch whilst fixing it up for commit, namely: 1. the configuration screen no longer demands a COMx port when using Native ANT+ on Windows. 2. new signals in ANTChannel notify the ANT class when info is stale or lost (but they are not used at present). 3. The previous debug messages have been removed, although new debug messages are added for stale/drop/timeout signals.
This commit is contained in:
committed by
Mark Liversedge
parent
22d04f8524
commit
f8d60bfbe2
189
src/ANT.cpp
189
src/ANT.cpp
@@ -90,11 +90,32 @@ ANT::ANT(QObject *parent, DeviceConfiguration *devConf) : QThread(parent)
|
||||
antIDs.clear();
|
||||
|
||||
// setup the channels
|
||||
for (int i=0; i<ANT_MAX_CHANNELS; i++) antChannel[i] = new ANTChannel(i, this);
|
||||
for (int i=0; i<ANT_MAX_CHANNELS; i++) {
|
||||
|
||||
// create the channel
|
||||
antChannel[i] = new ANTChannel(i, this);
|
||||
|
||||
// connect up its signals
|
||||
connect(antChannel[i], SIGNAL(dropInfo(int)), this, SLOT(dropInfo(int)));
|
||||
connect(antChannel[i], SIGNAL(lostInfo(int)), this, SLOT(lostInfo(int)));
|
||||
connect(antChannel[i], SIGNAL(staleInfo(int)), this, SLOT(staleInfo(int)));
|
||||
connect(antChannel[i], SIGNAL(searchTimeout(int)), this, SLOT(searchTimeout(int)));
|
||||
connect(antChannel[i], SIGNAL(searchComplete(int)), this, SLOT(searchComplete(int)));
|
||||
}
|
||||
|
||||
// on windows we use libusb to read from USB2
|
||||
// sticks, if it is not available we use stubs
|
||||
#ifdef WIN32
|
||||
usbMode = USBNone;
|
||||
usb2 = new LibUsb();
|
||||
#endif
|
||||
}
|
||||
|
||||
ANT::~ANT()
|
||||
{
|
||||
#ifdef WIN32
|
||||
delete usb2;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ANT::setDevice(QString x)
|
||||
@@ -114,7 +135,6 @@ void ANT::setBaud(int x)
|
||||
|
||||
void ANT::run()
|
||||
{
|
||||
//qDebug() << "Starting ANT thread...";
|
||||
int status; // control commands from controller
|
||||
bool isPortOpen = false;
|
||||
|
||||
@@ -254,7 +274,6 @@ ANT::stop()
|
||||
int
|
||||
ANT::quit(int code)
|
||||
{
|
||||
//qDebug()<<"Stopping ANT thread...";
|
||||
// event code goes here!
|
||||
closePort();
|
||||
exit(code);
|
||||
@@ -287,7 +306,7 @@ ANT::addDevice(int device_number, int device_type, int channel_number)
|
||||
if (((antChannel[i]->channel_type & 0xf ) == device_type) &&
|
||||
(antChannel[i]->device_number == device_number)) {
|
||||
// send the channel found...
|
||||
antChannel[i]->channelInfo();
|
||||
//XXX antChannel[i]->channelInfo();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -375,7 +394,8 @@ void
|
||||
ANT::report()
|
||||
{
|
||||
for (int i=0; i<ANT_MAX_CHANNELS; i++)
|
||||
antChannel[i]->channelInfo();
|
||||
//XXX antChannel[i]->channelInfo();
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -440,6 +460,36 @@ ANT::discover(DeviceConfiguration *, QProgressDialog *)
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ANT::dropInfo(int number) // we dropped a connection
|
||||
{
|
||||
qDebug()<<"drop info for channel"<<number;
|
||||
}
|
||||
|
||||
void
|
||||
ANT::lostInfo(int number) // we lost informa
|
||||
{
|
||||
qDebug()<<"lost info for channel"<<number;
|
||||
}
|
||||
|
||||
void
|
||||
ANT::staleInfo(int number) // info is now stale
|
||||
{
|
||||
qDebug()<<"stale info for channel"<<number;
|
||||
}
|
||||
|
||||
void
|
||||
ANT::searchTimeout(int number) // search timed out
|
||||
{
|
||||
qDebug()<<"search timeout on channel"<<number;
|
||||
}
|
||||
|
||||
void
|
||||
ANT::searchComplete(int number) // search completed successfully
|
||||
{
|
||||
qDebug()<<"search completed on channel"<<number;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* Message I/O
|
||||
*--------------------------------------------------------------------*/
|
||||
@@ -509,9 +559,7 @@ ANT::handleChannelEvent(void) {
|
||||
int channel = rxMessage[ANT_OFFSET_DATA] & 0x7;
|
||||
if(channel >= 0 && channel < 4) {
|
||||
|
||||
// handle a channel event here!
|
||||
//qDebug()<<"channel event on channel:"<<channel;
|
||||
|
||||
// handle a channel event here!
|
||||
antChannel[channel]->receiveMessage(rxMessage);
|
||||
}
|
||||
}
|
||||
@@ -519,7 +567,6 @@ ANT::handleChannelEvent(void) {
|
||||
void
|
||||
ANT::processMessage(void) {
|
||||
|
||||
//qDebug()<<"processing ant message"<<rxMessage[ANT_OFFSET_ID];
|
||||
ANTMessage(this, rxMessage); // for debug!
|
||||
|
||||
QDataStream out(&antlog);
|
||||
@@ -569,7 +616,18 @@ ANT::processMessage(void) {
|
||||
int ANT::closePort()
|
||||
{
|
||||
#ifdef WIN32
|
||||
return (int)!CloseHandle(devicePort);
|
||||
switch (usbMode) {
|
||||
case USB2 :
|
||||
usb2->close();
|
||||
return 0;
|
||||
break;
|
||||
case USB1 :
|
||||
return (int)!CloseHandle(devicePort);
|
||||
break;
|
||||
default :
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
tcflush(devicePort, TCIOFLUSH); // clear out the garbage
|
||||
return close(devicePort);
|
||||
@@ -578,8 +636,22 @@ int ANT::closePort()
|
||||
|
||||
int ANT::openPort()
|
||||
{
|
||||
#ifndef WIN32
|
||||
#ifdef WIN32
|
||||
int rc;
|
||||
|
||||
// on windows we try on USB2 then on USB1 then fail...
|
||||
if ((rc=usb2->open()) != -1) {
|
||||
usbMode = USB2;
|
||||
return rc;
|
||||
} else if ((rc= USBXpress::open(&devicePort)) != -1) {
|
||||
usbMode = USB1;
|
||||
return rc;
|
||||
} else {
|
||||
usbMode = USBNone;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else
|
||||
// LINUX AND MAC USES TERMIO / IOCTL / STDIO
|
||||
|
||||
#if defined(Q_OS_MACX)
|
||||
@@ -620,59 +692,6 @@ int ANT::openPort()
|
||||
if(tcsetattr(devicePort, TCSANOW, &deviceSettings) == -1) return errno;
|
||||
tcgetattr(devicePort, &deviceSettings);
|
||||
|
||||
#else
|
||||
#ifdef GC_HAVE_USBXPRESS
|
||||
return USBXpress::open(&devicePort);
|
||||
#else
|
||||
// WINDOWS USES SET/GETCOMMSTATE AND READ/WRITEFILE
|
||||
|
||||
COMMTIMEOUTS timeouts; // timeout settings on serial ports
|
||||
|
||||
// if deviceFilename references a port above COM9
|
||||
// then we need to open "\\.\COMX" not "COMX"
|
||||
QString portSpec;
|
||||
int portnum = deviceFilename.midRef(3).toString().toInt();
|
||||
if (portnum < 10)
|
||||
portSpec = deviceFilename;
|
||||
else
|
||||
portSpec = "\\\\.\\" + deviceFilename;
|
||||
wchar_t deviceFilenameW[32]; // \\.\COM32 needs 9 characters, 32 should be enough?
|
||||
MultiByteToWideChar(CP_ACP, 0, portSpec.toAscii(), -1, (LPWSTR)deviceFilenameW,
|
||||
sizeof(deviceFilenameW));
|
||||
|
||||
// win32 commport API
|
||||
devicePort = CreateFile (deviceFilenameW, GENERIC_READ|GENERIC_WRITE,
|
||||
FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
||||
if (devicePort == INVALID_HANDLE_VALUE) return -1;
|
||||
|
||||
if (GetCommState (devicePort, &deviceSettings) == false) return -1;
|
||||
|
||||
// so we've opened the comm port lets set it up for
|
||||
deviceSettings.BaudRate = CBR_2400;
|
||||
deviceSettings.fParity = NOPARITY;
|
||||
deviceSettings.ByteSize = 8;
|
||||
deviceSettings.StopBits = ONESTOPBIT;
|
||||
deviceSettings.EofChar = 0x0;
|
||||
deviceSettings.ErrorChar = 0x0;
|
||||
deviceSettings.EvtChar = 0x0;
|
||||
deviceSettings.fBinary = true;
|
||||
deviceSettings.fRtsControl = RTS_CONTROL_HANDSHAKE;
|
||||
deviceSettings.fOutxCtsFlow = TRUE;
|
||||
|
||||
|
||||
if (SetCommState(devicePort, &deviceSettings) == false) {
|
||||
CloseHandle(devicePort);
|
||||
return -1;
|
||||
}
|
||||
|
||||
timeouts.ReadIntervalTimeout = 0;
|
||||
timeouts.ReadTotalTimeoutConstant = 1000;
|
||||
timeouts.ReadTotalTimeoutMultiplier = 50;
|
||||
timeouts.WriteTotalTimeoutConstant = 2000;
|
||||
timeouts.WriteTotalTimeoutMultiplier = 0;
|
||||
SetCommTimeouts(devicePort, &timeouts);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// success
|
||||
@@ -684,13 +703,19 @@ int ANT::rawWrite(uint8_t *bytes, int size) // unix!!
|
||||
int rc=0;
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef GC_HAVE_USBXPRESS
|
||||
rc = USBXpress::write(&devicePort, bytes, size);
|
||||
#else
|
||||
DWORD cBytes;
|
||||
rc = WriteFile(devicePort, bytes, size, &cBytes, NULL);
|
||||
#endif
|
||||
if (!rc) return -1;
|
||||
switch (usbMode) {
|
||||
case USB1:
|
||||
rc = USBXpress::write(&devicePort, bytes, size);
|
||||
break;
|
||||
case USB2:
|
||||
rc = usb2->write((char *)bytes, size);
|
||||
break;
|
||||
default:
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!rc) rc = -1; // return -1 if nothing written
|
||||
return rc;
|
||||
|
||||
#else
|
||||
@@ -704,9 +729,9 @@ int ANT::rawWrite(uint8_t *bytes, int size) // unix!!
|
||||
if (rc != -1) tcdrain(devicePort); // wait till its gone.
|
||||
|
||||
ioctl(devicePort, FIONREAD, &ibytes);
|
||||
return rc;
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
@@ -715,16 +740,18 @@ int ANT::rawRead(uint8_t bytes[], int size)
|
||||
int rc=0;
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef GC_HAVE_USBXPRESS
|
||||
return USBXpress::read(&devicePort, bytes, size);
|
||||
#else
|
||||
switch (usbMode) {
|
||||
case USB1:
|
||||
return USBXpress::read(&devicePort, bytes, size);
|
||||
break;
|
||||
case USB2:
|
||||
return usb2->read((char *)bytes, size);
|
||||
break;
|
||||
default:
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// Readfile deals with timeouts and readyread issues
|
||||
DWORD cBytes;
|
||||
rc = ReadFile(devicePort, bytes, size, &cBytes, NULL);
|
||||
if (rc) return (int)cBytes;
|
||||
else return (-1);
|
||||
#endif
|
||||
#else
|
||||
|
||||
int timeout=0, i=0;
|
||||
|
||||
13
src/ANT.h
13
src/ANT.h
@@ -58,6 +58,7 @@
|
||||
#include <windows.h>
|
||||
#include <winbase.h>
|
||||
#include "USBXpress.h" // for Garmin USB1 sticks
|
||||
#include "LibUsb.h" // for Garmin USB2 sticks
|
||||
#else
|
||||
#include <termios.h> // unix!!
|
||||
#include <unistd.h> // unix!!
|
||||
@@ -240,6 +241,11 @@ public slots:
|
||||
|
||||
// channel management
|
||||
bool discover(DeviceConfiguration *, QProgressDialog *); // confirm Server available at portSpec
|
||||
void dropInfo(int number); // we dropped a connection
|
||||
void lostInfo(int number); // we lost informa
|
||||
void staleInfo(int number); // info is now stale
|
||||
void searchTimeout(int number); // search timed out
|
||||
void searchComplete(int number); // search completed successfully
|
||||
|
||||
// get telemetry
|
||||
RealtimeData getRealtimeData(); // return current realtime data
|
||||
@@ -310,6 +316,9 @@ private:
|
||||
#ifdef WIN32
|
||||
HANDLE devicePort; // file descriptor for reading from com3
|
||||
DCB deviceSettings; // serial port settings baud rate et al
|
||||
LibUsb *usb2; // used for USB2 support
|
||||
enum UsbMode { USBNone, USB1, USB2 };
|
||||
enum UsbMode usbMode;
|
||||
#else
|
||||
int devicePort; // unix!!
|
||||
struct termios deviceSettings; // unix!!
|
||||
@@ -324,8 +333,8 @@ private:
|
||||
unsigned char rxMessage[ANT_MAX_MESSAGE_SIZE];
|
||||
|
||||
// state machine whilst receiving bytes
|
||||
enum States {ST_WAIT_FOR_SYNC, ST_GET_LENGTH, ST_GET_MESSAGE_ID, ST_GET_DATA, ST_VALIDATE_PACKET};
|
||||
enum States state;
|
||||
enum States {ST_WAIT_FOR_SYNC, ST_GET_LENGTH, ST_GET_MESSAGE_ID, ST_GET_DATA, ST_VALIDATE_PACKET} state;
|
||||
//enum States state;
|
||||
int length;
|
||||
int bytes;
|
||||
int checksum;
|
||||
|
||||
@@ -25,7 +25,7 @@ static float timeout_drop=2.0; // time before reporting dropped message
|
||||
static float timeout_scan=10.0; // time to do initial scan
|
||||
static float timeout_lost=30.0; // time to do more thorough scan
|
||||
|
||||
ANTChannel::ANTChannel(int number, ANT *parent) : number(number), parent(parent)
|
||||
ANTChannel::ANTChannel(int number, ANT *parent) : parent(parent), number(number)
|
||||
{
|
||||
channel_type=CHANNEL_TYPE_UNUSED;
|
||||
channel_type_flags=0;
|
||||
@@ -97,7 +97,7 @@ void ANTChannel::open(int device, int chan_type)
|
||||
// close an ant channel assignment
|
||||
void ANTChannel::close()
|
||||
{
|
||||
lostInfo();
|
||||
emit lostInfo(number);
|
||||
lastMessage = ANTMessage();
|
||||
parent->sendMessage(ANTMessage::close(number));
|
||||
}
|
||||
@@ -133,7 +133,7 @@ void ANTChannel::receiveMessage(unsigned char *ant_message)
|
||||
if (get_timestamp() > blanking_timestamp + timeout_blanking) {
|
||||
if (!blanked) {
|
||||
blanked=1;
|
||||
staleInfo(); //XXX does nothing for now....
|
||||
emit staleInfo(number);
|
||||
}
|
||||
} else blanked=0;
|
||||
}
|
||||
@@ -159,12 +159,14 @@ void ANTChannel::channelEvent(unsigned char *ant_message) {
|
||||
// timeouts are normal for search channel
|
||||
if (channel_type_flags & CHANNEL_TYPE_QUICK_SEARCH) {
|
||||
|
||||
channel_type_flags &= ~CHANNEL_TYPE_QUICK_SEARCH;
|
||||
channel_type_flags |= CHANNEL_TYPE_WAITING;
|
||||
channel_type_flags &= ~CHANNEL_TYPE_QUICK_SEARCH;
|
||||
channel_type_flags |= CHANNEL_TYPE_WAITING;
|
||||
|
||||
emit searchTimeout(number);
|
||||
|
||||
} else {
|
||||
|
||||
lostInfo(); //XXX does nothing for now
|
||||
emit lostInfo(number);
|
||||
|
||||
channel_type=CHANNEL_TYPE_UNUSED;
|
||||
channel_type_flags=0;
|
||||
@@ -182,7 +184,7 @@ void ANTChannel::channelEvent(unsigned char *ant_message) {
|
||||
double t=get_timestamp();
|
||||
|
||||
if (t > (last_message_timestamp + timeout_drop)) {
|
||||
if (channel_type != CHANNEL_TYPE_UNUSED) dropInfo();
|
||||
if (channel_type != CHANNEL_TYPE_UNUSED) emit dropInfo(number);
|
||||
// this is a hacky way to prevent the drop message from sending multiple times
|
||||
last_message_timestamp+=2*timeout_drop;
|
||||
}
|
||||
@@ -248,7 +250,6 @@ void ANTChannel::broadcastEvent(unsigned char *ant_message)
|
||||
last_message_timestamp=timestamp;
|
||||
|
||||
if (state != MESSAGE_RECEIVED) {
|
||||
qDebug()<<"who are you? sent";
|
||||
// first message! who are we talking to?
|
||||
parent->sendMessage(ANTMessage::requestMessage(number, ANT_CHANNEL_ID));
|
||||
blanking_timestamp=get_timestamp();
|
||||
@@ -278,7 +279,6 @@ qDebug()<<"who are you? sent";
|
||||
//
|
||||
// We got some telemetry on this channel
|
||||
//
|
||||
qDebug()<<"broadcast datapage="<<antMessage.data_page;
|
||||
if (lastMessage.type != 0) {
|
||||
|
||||
switch (channel_type) {
|
||||
@@ -315,7 +315,6 @@ qDebug()<<"broadcast datapage="<<antMessage.data_page;
|
||||
srm_offset = antMessage.srmOffset;
|
||||
parent->setWatts(0);
|
||||
parent->setCadence(0);
|
||||
qDebug()<<"got new offset!"<<srm_offset;
|
||||
break;
|
||||
|
||||
case 0x02: // slope
|
||||
@@ -563,9 +562,9 @@ void ANTChannel::channelId(unsigned char *ant_message) {
|
||||
state=MESSAGE_RECEIVED;
|
||||
|
||||
setId();
|
||||
channelInfo();
|
||||
emit channelInfo();
|
||||
|
||||
// if we were searching,
|
||||
// if we were searching,
|
||||
if (channel_type_flags & CHANNEL_TYPE_QUICK_SEARCH) {
|
||||
parent->sendMessage(ANTMessage::setSearchTimeout(number, (int)(timeout_lost/2.5)));
|
||||
}
|
||||
@@ -634,7 +633,6 @@ void ANTChannel::attemptTransition(int message_id)
|
||||
switch (state) {
|
||||
|
||||
case ANT_CLOSE_CHANNEL:
|
||||
//qDebug()<<"transition ... close channel...";
|
||||
// next step is unassign and start over
|
||||
// but we must wait until event_channel_closed
|
||||
// which is its own channel event
|
||||
@@ -642,7 +640,6 @@ void ANTChannel::attemptTransition(int message_id)
|
||||
break;
|
||||
|
||||
case ANT_UNASSIGN_CHANNEL:
|
||||
//qDebug()<<"transition ... unassign channel...";
|
||||
channel_assigned=0;
|
||||
if (st->type==CHANNEL_TYPE_UNUSED) {
|
||||
// we're shutting the channel down
|
||||
@@ -652,23 +649,21 @@ void ANTChannel::attemptTransition(int message_id)
|
||||
device_id |= 0x80;
|
||||
}
|
||||
setId();
|
||||
//qDebug()<<"st network is"<<st->network;
|
||||
parent->sendMessage(ANTMessage::assignChannel(number, 0, st->network)); // recieve channel on network 1
|
||||
// XXX commented out since newer host controllers do not exhibit this issue
|
||||
// XXX but may be relevant for Arduino/Sparkfun guys, but we don't really support
|
||||
// XXX those devices anyway as they are too slow
|
||||
// XXX parent->sendMessage(ANTMessage::boostSignal(number)); // "boost" signal on REV C AP2 devices
|
||||
|
||||
// commented out since newer host controllers do not exhibit this issue
|
||||
// but may be relevant for Arduino/Sparkfun guys, but we don't really support
|
||||
// those devices anyway as they are too slow
|
||||
// parent->sendMessage(ANTMessage::boostSignal(number)); // "boost" signal on REV C AP2 devices
|
||||
}
|
||||
break;
|
||||
|
||||
case ANT_ASSIGN_CHANNEL:
|
||||
//qDebug()<<"transition ... assign channel...";
|
||||
channel_assigned=1;
|
||||
parent->sendMessage(ANTMessage::setChannelID(number, device_number, device_id, 0));
|
||||
break;
|
||||
|
||||
case ANT_CHANNEL_ID:
|
||||
//qDebug()<<"transition ... channel id...";
|
||||
if (channel_type & CHANNEL_TYPE_QUICK_SEARCH) {
|
||||
parent->sendMessage(ANTMessage::setSearchTimeout(number, (int)(timeout_scan/2.5)));
|
||||
} else {
|
||||
@@ -677,7 +672,6 @@ void ANTChannel::attemptTransition(int message_id)
|
||||
break;
|
||||
|
||||
case ANT_SEARCH_TIMEOUT:
|
||||
//qDebug()<<"transition ... search timeout...";
|
||||
if (previous_state==ANT_CHANNEL_ID) {
|
||||
// continue down the intialization chain
|
||||
parent->sendMessage(ANTMessage::setChannelPeriod(number, st->period));
|
||||
@@ -689,18 +683,15 @@ void ANTChannel::attemptTransition(int message_id)
|
||||
break;
|
||||
|
||||
case ANT_CHANNEL_PERIOD:
|
||||
//qDebug()<<"transition ... channel period...";
|
||||
parent->sendMessage(ANTMessage::setChannelFreq(number, st->frequency));
|
||||
break;
|
||||
|
||||
case ANT_CHANNEL_FREQUENCY:
|
||||
//qDebug()<<"transition ... channel frequency...";
|
||||
parent->sendMessage(ANTMessage::open(number));
|
||||
mi.initialise();
|
||||
break;
|
||||
|
||||
case ANT_OPEN_CHANNEL:
|
||||
//qDebug()<<"transition ... open channel...";
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -711,14 +702,16 @@ void ANTChannel::attemptTransition(int message_id)
|
||||
// refactored out XXX fix this
|
||||
int ANTChannel::setTimeout(char * /*type*/, float /*value*/, int /*connection*/) { return 0; }
|
||||
|
||||
#if 0 // ARE NOW SIGNALS
|
||||
// These should emit signals to notify the channel manager
|
||||
// but for now we just ignore XXX fix this
|
||||
void ANTChannel::searchComplete() {}
|
||||
void ANTChannel::reportTimeouts() {}
|
||||
void ANTChannel::searchTimeout() {}
|
||||
void ANTChannel::staleInfo() {}
|
||||
void ANTChannel::lostInfo() {}
|
||||
void ANTChannel::dropInfo() {}
|
||||
void ANTChannel::channelInfo() {}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Calibrate... XXX not used at present
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "ANT.h"
|
||||
#include "ANTMessage.h"
|
||||
#include <QObject>
|
||||
|
||||
#define CHANNEL_TYPE_QUICK_SEARCH 0x10 // or'ed with current channel type
|
||||
/* after fast search, wait for slow search. Otherwise, starting slow
|
||||
@@ -71,9 +72,39 @@ class ANTChannelInitialisation {
|
||||
};
|
||||
|
||||
|
||||
class ANTChannel {
|
||||
class ANTChannel : public QObject {
|
||||
|
||||
private:
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
ANT *parent;
|
||||
|
||||
ANTMessage lastMessage, lastStdPwrMessage;
|
||||
int dualNullCount, nullCount;
|
||||
double last_message_timestamp;
|
||||
double blanking_timestamp;
|
||||
int blanked;
|
||||
char id[10]; // short identifier
|
||||
bool channel_assigned;
|
||||
ANTChannelInitialisation mi;
|
||||
|
||||
int messages_received; // for signal strength metric
|
||||
int messages_dropped;
|
||||
|
||||
unsigned char rx_burst_data[RX_BURST_DATA_LEN];
|
||||
int rx_burst_data_index;
|
||||
unsigned char rx_burst_next_sequence;
|
||||
void (*rx_burst_disposition)(struct ant_channel *);
|
||||
void (*tx_ack_disposition)(struct ant_channel *);
|
||||
|
||||
// what we got
|
||||
int manufacturer_id;
|
||||
int product_id;
|
||||
int product_version;
|
||||
|
||||
public:
|
||||
|
||||
enum channeltype {
|
||||
CHANNEL_TYPE_UNUSED,
|
||||
CHANNEL_TYPE_HR,
|
||||
@@ -124,14 +155,6 @@ class ANTChannel {
|
||||
void attemptTransition(int message_code);
|
||||
int setTimeout(char *type, float value, int connection);
|
||||
|
||||
// Should be signals ? XXX
|
||||
void channelInfo();
|
||||
void dropInfo();
|
||||
void lostInfo();
|
||||
void staleInfo();
|
||||
void reportTimeouts();
|
||||
void searchComplete();
|
||||
|
||||
// search
|
||||
int isSearching();
|
||||
|
||||
@@ -140,33 +163,13 @@ class ANTChannel {
|
||||
void sendCinqoSuccess();
|
||||
void checkCinqo();
|
||||
|
||||
private:
|
||||
|
||||
ANT *parent;
|
||||
|
||||
ANTMessage lastMessage, lastStdPwrMessage;
|
||||
int dualNullCount, nullCount;
|
||||
double last_message_timestamp;
|
||||
double blanking_timestamp;
|
||||
int blanked;
|
||||
char id[10]; // short identifier
|
||||
bool channel_assigned;
|
||||
ANTChannelInitialisation mi;
|
||||
|
||||
int messages_received; // for signal strength metric
|
||||
int messages_dropped;
|
||||
|
||||
unsigned char rx_burst_data[RX_BURST_DATA_LEN];
|
||||
int rx_burst_data_index;
|
||||
unsigned char rx_burst_next_sequence;
|
||||
void (*rx_burst_disposition)(struct ant_channel *);
|
||||
void (*tx_ack_disposition)(struct ant_channel *);
|
||||
|
||||
|
||||
// what we got
|
||||
int manufacturer_id;
|
||||
int product_id;
|
||||
int product_version;
|
||||
signals:
|
||||
|
||||
void channelInfo(); // we got a channel info message
|
||||
void dropInfo(int number); // we dropped a connection
|
||||
void lostInfo(int number); // we lost informa
|
||||
void staleInfo(int number); // info is now stale
|
||||
void searchTimeout(int number); // search timed out
|
||||
void searchComplete(int number); // search completed successfully
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -185,9 +185,9 @@ ANTMessage::ANTMessage(void) {
|
||||
init();
|
||||
}
|
||||
|
||||
// static helper to conver message codes to an english string
|
||||
// when outputing diagnostics for received messages
|
||||
static const char *channelEventMessage(unsigned char c)
|
||||
// convert message codes to an english string
|
||||
const char *
|
||||
ANTMessage::channelEventMessage(unsigned char c)
|
||||
{
|
||||
switch (c) {
|
||||
case 0 : return "No error";
|
||||
@@ -237,35 +237,29 @@ ANTMessage::ANTMessage(ANT *parent, const unsigned char *message) {
|
||||
switch(type) {
|
||||
case ANT_UNASSIGN_CHANNEL:
|
||||
channel = message[3];
|
||||
qDebug()<<"unassign channel"<<channel;
|
||||
break;
|
||||
case ANT_ASSIGN_CHANNEL:
|
||||
channel = message[3];
|
||||
channelType = message[4];
|
||||
networkNumber = message[5];
|
||||
qDebug()<<"assign channel"<<channel;
|
||||
break;
|
||||
case ANT_CHANNEL_ID:
|
||||
channel = message[3];
|
||||
deviceNumber = message[4] + (message[5]<<8);
|
||||
deviceType = message[6];
|
||||
transmissionType = message[7];
|
||||
qDebug()<<"assign channel id"<<deviceNumber;
|
||||
break;
|
||||
case ANT_CHANNEL_PERIOD:
|
||||
channel = message[3];
|
||||
channelPeriod = message[4] + (message[5]<<8);
|
||||
qDebug()<<"channel period"<<channel<<channelPeriod;
|
||||
break;
|
||||
case ANT_SEARCH_TIMEOUT:
|
||||
channel = message[3];
|
||||
searchTimeout = message[4];
|
||||
qDebug()<<"search timeout"<<channel<<searchTimeout;
|
||||
break;
|
||||
case ANT_CHANNEL_FREQUENCY:
|
||||
channel = message[3];
|
||||
frequency = message[4];
|
||||
qDebug()<<"channel frequency"<<channel<<frequency;
|
||||
break;
|
||||
case ANT_SET_NETWORK:
|
||||
channel = message[3];
|
||||
@@ -280,44 +274,31 @@ qDebug()<<"channel frequency"<<channel<<frequency;
|
||||
break;
|
||||
case ANT_TX_POWER:
|
||||
transmitPower = message[4];
|
||||
qDebug()<<"transmit power"<<transmitPower;
|
||||
break;
|
||||
case ANT_ID_LIST_ADD:
|
||||
qDebug()<<"ant id list add ";
|
||||
break;
|
||||
case ANT_ID_LIST_CONFIG:
|
||||
qDebug()<<"ant list config ";
|
||||
break;
|
||||
case ANT_CHANNEL_TX_POWER:
|
||||
qDebug()<<"ant channel txpower ";
|
||||
break;
|
||||
case ANT_LP_SEARCH_TIMEOUT:
|
||||
qDebug()<<"ant lp search timeout ";
|
||||
break;
|
||||
case ANT_SET_SERIAL_NUMBER:
|
||||
qDebug()<<"serial number";
|
||||
break;
|
||||
case ANT_ENABLE_EXT_MSGS:
|
||||
qDebug()<<"enable extended messages";
|
||||
break;
|
||||
case ANT_ENABLE_LED:
|
||||
qDebug()<<"enable led";
|
||||
break;
|
||||
case ANT_SYSTEM_RESET:
|
||||
qDebug()<<"system reset";
|
||||
break; // nothing to do, this is ok
|
||||
case ANT_OPEN_CHANNEL:
|
||||
channel = message[3];
|
||||
qDebug()<<"open channel"<<channel;
|
||||
break;
|
||||
case ANT_CLOSE_CHANNEL:
|
||||
qDebug()<<"close channel";
|
||||
break;
|
||||
case ANT_OPEN_RX_SCAN_CH:
|
||||
qDebug()<<"open rx scan channel";
|
||||
break;
|
||||
case ANT_REQ_MESSAGE:
|
||||
qDebug()<<"request message";
|
||||
break;
|
||||
|
||||
//
|
||||
@@ -372,8 +353,6 @@ qDebug()<<"request message";
|
||||
// 0x50 - Manufacturer UD
|
||||
// 0x52 - Battery Voltage
|
||||
|
||||
qDebug()<<"broadcast data, channel="<<message[3]<<"type="<<message[4]<<"calid?"<<message[5];
|
||||
|
||||
data_page = message[4];
|
||||
|
||||
// we need to handle ant sport messages here
|
||||
@@ -518,35 +497,24 @@ qDebug()<<"broadcast data, channel="<<message[3]<<"type="<<message[4]<<"calid?"<
|
||||
}
|
||||
break;
|
||||
case ANT_ACK_DATA:
|
||||
qDebug()<<"ack data";
|
||||
break;
|
||||
case ANT_BURST_DATA:
|
||||
qDebug()<<"burst data";
|
||||
break;
|
||||
case ANT_CHANNEL_EVENT:
|
||||
qDebug()<<"channel event" << "ID"<<message[4] << channelEventMessage(message[5]);
|
||||
|
||||
break;
|
||||
case ANT_CHANNEL_STATUS:
|
||||
qDebug()<<"channel status";
|
||||
break;
|
||||
case ANT_VERSION:
|
||||
qDebug()<<"ant version";
|
||||
break;
|
||||
case ANT_CAPABILITIES:
|
||||
qDebug()<<"ant capabilities";
|
||||
break;
|
||||
case ANT_SERIAL_NUMBER:
|
||||
qDebug()<<"ant serial number";
|
||||
break;
|
||||
case ANT_CW_INIT:
|
||||
qDebug()<<"cw init";
|
||||
break;
|
||||
case ANT_CW_TEST:
|
||||
qDebug()<<"cw test";
|
||||
break;
|
||||
default:
|
||||
qDebug()<<"message id>>"<< type;
|
||||
break; // shouldn't get here!
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,9 @@ class ANTMessage {
|
||||
static ANTMessage open(const unsigned char channel);
|
||||
static ANTMessage close(const unsigned char channel);
|
||||
|
||||
// convert a channel event message id to human readable string
|
||||
const char * channelEventMessage(unsigned char c);
|
||||
|
||||
// to avoid a myriad of tedious set/getters the data fields
|
||||
// are plain public members. This is unlikely to change in the
|
||||
// future since the whole purpose of this class is to encode
|
||||
|
||||
@@ -28,11 +28,15 @@
|
||||
|
||||
static DeviceType SupportedDevices[] =
|
||||
{
|
||||
{ DEV_CT, DEV_SERIAL, (char *) "Computrainer", true, false },
|
||||
{ DEV_ANTPLUS, DEV_QUARQ, (char *) "ANT+ via Quarqd", true, false },
|
||||
#ifdef Q_OS_WIN32
|
||||
{ DEV_ANTLOCAL, DEV_USB, (char *) "Native ANT+", true, false },
|
||||
#else
|
||||
{ DEV_ANTLOCAL, DEV_SERIAL, (char *) "Native ANT+", true, false },
|
||||
#endif
|
||||
{ DEV_CT, DEV_SERIAL, (char *) "Computrainer", true, false },
|
||||
{ DEV_GSERVER, DEV_TCP, (char *) "Golden Cheetah Server", false, false },
|
||||
{ DEV_NULL, DEV_TCP, (char *) "Null device (testing)", false, false },
|
||||
{ DEV_ANTPLUS, DEV_QUARQ, (char *) "ANT+ via Quarqd", true, false },
|
||||
// { DEV_PT, DEV_SERIAL, (char *) "Powertap Head Unit", false, true },
|
||||
// { DEV_SRM, DEV_SERIAL, (char *) "SRM PowerControl V/VI", false, true },
|
||||
// { DEV_GCLIENT, DEV_TCP, (char *) "Golden Cheetah Client", false, false },
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#define DEV_QUARQ 0x01 // ants use id:hostname:port
|
||||
#define DEV_SERIAL 0x02 // use filename COMx or /dev/cuxxxx
|
||||
#define DEV_TCP 0x03 // tcp port is hostname:port NOT IMPLEMENTED IN THIS RELEASE
|
||||
#define DEV_USB 0x04 // use filename COMx or /dev/cuxxxx
|
||||
|
||||
class DeviceType
|
||||
{
|
||||
|
||||
236
src/LibUsb.cpp
Normal file
236
src/LibUsb.cpp
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Darren Hague & Eric Brandt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
|
||||
#include "LibUsb.h"
|
||||
|
||||
#ifdef GC_HAVE_LIBUSB // only include if windows and have libusb installed
|
||||
|
||||
|
||||
LibUsb::LibUsb()
|
||||
{
|
||||
intf = NULL;
|
||||
readBufIndex = 0;
|
||||
readBufSize = 0;
|
||||
|
||||
usb_set_debug(255);
|
||||
|
||||
// Initialize the library.
|
||||
usb_init();
|
||||
|
||||
// Find all busses.
|
||||
usb_find_busses();
|
||||
|
||||
// Find all connected devices.
|
||||
usb_find_devices();
|
||||
}
|
||||
|
||||
int LibUsb::open()
|
||||
{
|
||||
// Search busses & devices for USB2 ANT+ stick
|
||||
device = OpenAntStick();
|
||||
|
||||
if (device == NULL)
|
||||
return -1;
|
||||
|
||||
int rc = usb_clear_halt(device, writeEndpoint);
|
||||
if (rc < 0)
|
||||
qDebug()<<"usb_clear_halt writeEndpoint Error: "<< usb_strerror();
|
||||
|
||||
rc = usb_clear_halt(device, readEndpoint);
|
||||
if (rc < 0)
|
||||
qDebug()<<"usb_clear_halt readEndpoint Error: "<< usb_strerror();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void LibUsb::close()
|
||||
{
|
||||
if (device) {
|
||||
usb_release_interface(device, 0);
|
||||
usb_close(device);
|
||||
}
|
||||
|
||||
device = NULL;
|
||||
}
|
||||
|
||||
int LibUsb::read(char *buf, int bytes)
|
||||
{
|
||||
// The USB2 stick really doesn't like you reading 1 byte when more are available
|
||||
// so we need a buffered reader
|
||||
|
||||
int bufRemain = readBufSize - readBufIndex;
|
||||
|
||||
// Can we entirely satisfy the request from the buffer?
|
||||
if (bufRemain > bytes)
|
||||
{
|
||||
// Yes, so do it
|
||||
memcpy(buf, readBuf+readBufIndex, bytes);
|
||||
readBufIndex += bytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
// No, so partially satisfy by emptying the buffer, then refill the buffer for the rest
|
||||
memcpy(buf, readBuf+readBufIndex, bufRemain);
|
||||
readBufSize = 0;
|
||||
readBufIndex = 0;
|
||||
|
||||
int rc = usb_bulk_read(device, readEndpoint, readBuf, 64, 1000);
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
qDebug()<<"usb_bulk_read Error reading: "<< usb_strerror();
|
||||
return rc;
|
||||
}
|
||||
|
||||
readBufSize = rc;
|
||||
|
||||
int bytesToGo = bytes - bufRemain;
|
||||
if (bytesToGo < readBufSize)
|
||||
{
|
||||
// If we have enough bytes in the buffer, return them
|
||||
memcpy(buf+bufRemain, readBuf, bytesToGo);
|
||||
readBufIndex += bytesToGo;
|
||||
rc = bytes;
|
||||
} else {
|
||||
// Otherwise, just return what we can
|
||||
memcpy(buf+bufRemain, readBuf, readBufSize);
|
||||
rc = bufRemain + readBufSize;
|
||||
readBufSize = 0;
|
||||
readBufIndex = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int LibUsb::write(char *buf, int bytes)
|
||||
{
|
||||
int rc = usb_interrupt_write(device, writeEndpoint, buf, bytes, 1000);
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
qDebug()<<"usb_interrupt_write Error writing: "<< usb_strerror();
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct usb_dev_handle* LibUsb::OpenAntStick()
|
||||
{
|
||||
struct usb_bus* bus;
|
||||
struct usb_device* dev;
|
||||
struct usb_dev_handle* udev;
|
||||
|
||||
for (bus = usb_get_busses(); bus; bus = bus->next)
|
||||
{
|
||||
for (dev = bus->devices; dev; dev = dev->next)
|
||||
{
|
||||
if (dev->descriptor.idVendor == GARMIN_USB2_VID && dev->descriptor.idProduct == GARMIN_USB2_PID)
|
||||
{
|
||||
qDebug() << "Found a Garmin USB2 ANT+ stick";
|
||||
|
||||
if ((udev = usb_open(dev)))
|
||||
{
|
||||
if (dev->descriptor.bNumConfigurations)
|
||||
{
|
||||
if ((intf = usb_find_interface(&dev->config[0])) != NULL)
|
||||
{
|
||||
int rc = usb_set_configuration(udev, 1);
|
||||
if (rc < 0)
|
||||
qDebug()<<"usb_set_configuration Error: "<< usb_strerror();
|
||||
rc = usb_claim_interface(udev, 0);
|
||||
if (rc < 0)
|
||||
qDebug()<<"usb_claim_interface Error: "<< usb_strerror();
|
||||
rc = usb_set_altinterface(udev, 0);
|
||||
if (rc < 0)
|
||||
qDebug()<<"usb_set_altinterface Error: "<< usb_strerror();
|
||||
return udev;
|
||||
}
|
||||
}
|
||||
|
||||
usb_close(udev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct usb_interface_descriptor* LibUsb::usb_find_interface(struct usb_config_descriptor* config_descriptor)
|
||||
{
|
||||
struct usb_interface_descriptor* intf;
|
||||
|
||||
readEndpoint = -1;
|
||||
writeEndpoint = -1;
|
||||
|
||||
if (!config_descriptor)
|
||||
return NULL;
|
||||
|
||||
if (!config_descriptor->bNumInterfaces)
|
||||
return NULL;
|
||||
|
||||
if (!config_descriptor->interface[0].num_altsetting)
|
||||
return NULL;
|
||||
|
||||
intf = &config_descriptor->interface[0].altsetting[0];
|
||||
|
||||
if (intf->bNumEndpoints != 2)
|
||||
return NULL;
|
||||
|
||||
for (int i = 0 ; i < 2; i++)
|
||||
{
|
||||
if (intf->endpoint[i].bEndpointAddress & USB_ENDPOINT_DIR_MASK)
|
||||
readEndpoint = intf->endpoint[i].bEndpointAddress;
|
||||
else
|
||||
writeEndpoint = intf->endpoint[i].bEndpointAddress;
|
||||
}
|
||||
|
||||
if (readEndpoint < 0 || writeEndpoint < 0)
|
||||
return NULL;
|
||||
|
||||
return intf;
|
||||
}
|
||||
#else
|
||||
|
||||
// if we don't have libusb use stubs
|
||||
LibUsb::LibUsb() {}
|
||||
|
||||
int LibUsb::open()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void LibUsb::close()
|
||||
{
|
||||
}
|
||||
|
||||
int LibUsb::read(char *, int)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int LibUsb::write(char *, int)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif // Have LIBUSB
|
||||
#endif // WIN32
|
||||
53
src/LibUsb.h
Normal file
53
src/LibUsb.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Darren Hague & Eric Brandt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef gc_LibUsb_h
|
||||
#define gc_LibUsb_h
|
||||
|
||||
#if defined WIN32
|
||||
|
||||
#ifdef GC_HAVE_LIBUSB
|
||||
#include <usb.h> // for the constants etc
|
||||
#endif
|
||||
|
||||
#define GARMIN_USB2_VID 0x0fcf
|
||||
#define GARMIN_USB2_PID 0x1008
|
||||
|
||||
class LibUsb {
|
||||
|
||||
public:
|
||||
LibUsb();
|
||||
int open();
|
||||
void close();
|
||||
int read(char *buf, int bytes);
|
||||
int write(char *buf, int bytes);
|
||||
private:
|
||||
#ifdef GC_HAVE_LIBUSB
|
||||
struct usb_dev_handle* OpenAntStick();
|
||||
struct usb_interface_descriptor* usb_find_interface(struct usb_config_descriptor* config_descriptor);
|
||||
struct usb_dev_handle* device;
|
||||
struct usb_interface_descriptor* intf;
|
||||
int readEndpoint, writeEndpoint;
|
||||
|
||||
char readBuf[64];
|
||||
int readBufIndex;
|
||||
int readBufSize;
|
||||
#endif
|
||||
};
|
||||
#endif // WIN32
|
||||
#endif // gc_LibUsb_h
|
||||
@@ -866,44 +866,55 @@ DevicePage::setConfigPane()
|
||||
switch (Supported.getType(typeSelector->itemData(typeSelector->currentIndex()).toInt()).connector) {
|
||||
|
||||
case DEV_QUARQ:
|
||||
specHint->show();
|
||||
specLabel->show();
|
||||
deviceSpecifier->show();
|
||||
specHint->setText("hostname:port");
|
||||
profHint->setText("antid 1, antid 2 ...");
|
||||
profHint->show();
|
||||
pairButton->show();
|
||||
profLabel->show();
|
||||
deviceProfile->show();
|
||||
break;
|
||||
|
||||
case DEV_SERIAL:
|
||||
#ifdef WIN32
|
||||
specHint->setText("COMx");
|
||||
#else
|
||||
specHint->setText("/dev/xxxx");
|
||||
#endif
|
||||
// we have ANT+ sticks on serial and we have Computrainers
|
||||
// on serial, which one is it?
|
||||
if (Supported.getType(typeSelector->itemData(typeSelector->currentIndex())
|
||||
.toInt()).type == DEV_ANTLOCAL) {
|
||||
pairButton->show();
|
||||
profHint->setText("antid 1, antid 2 ...");
|
||||
profHint->show();
|
||||
profLabel->show();
|
||||
deviceProfile->show();
|
||||
} else {
|
||||
pairButton->hide();
|
||||
profHint->hide();
|
||||
profLabel->hide();
|
||||
deviceProfile->hide();
|
||||
}
|
||||
break;
|
||||
case DEV_TCP:
|
||||
specHint->setText("hostname:port");
|
||||
pairButton->hide();
|
||||
specHint->show();
|
||||
specLabel->show();
|
||||
deviceSpecifier->show();
|
||||
profHint->hide();
|
||||
profLabel->hide();
|
||||
deviceProfile->hide();
|
||||
break;
|
||||
|
||||
case DEV_TCP:
|
||||
specHint->show();
|
||||
specLabel->show();
|
||||
deviceSpecifier->show();
|
||||
specHint->setText("hostname:port");
|
||||
profHint->hide();
|
||||
profLabel->hide();
|
||||
deviceProfile->hide();
|
||||
break;
|
||||
|
||||
case DEV_USB:
|
||||
specHint->hide();
|
||||
specLabel->hide();
|
||||
deviceSpecifier->hide();
|
||||
profHint->setText("antid 1, antid 2 ...");
|
||||
profHint->show();
|
||||
profLabel->show();
|
||||
deviceProfile->show();
|
||||
break;
|
||||
}
|
||||
//specHint->setTextFormat(Qt::Italic); // mmm need to read the docos
|
||||
|
||||
// pair button only valid for ANT+ (Quarqd or Native)
|
||||
int type = Supported.getType(typeSelector->itemData(typeSelector->currentIndex()).toInt()).type;
|
||||
if (type == DEV_ANTLOCAL || type == DEV_ANTPLUS) pairButton->show();
|
||||
else pairButton->hide();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -16,12 +16,15 @@
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if defined (WIN32) && defined (GC_HAVE_USBXPRESS) // only include if windows and have USBXpress installed
|
||||
|
||||
#include "USBXpress.h"
|
||||
#ifdef WIN32
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
|
||||
#ifdef GC_HAVE_USBXPRESS
|
||||
|
||||
// if we have usbxpress installed then use it...
|
||||
#include "USBXpress.h"
|
||||
|
||||
USBXpress::USBXpress() {} // nothing to do - all members are static
|
||||
|
||||
int USBXpress::open(HANDLE *handle)
|
||||
@@ -97,4 +100,31 @@ int USBXpress::write(HANDLE *handle, unsigned char *buf, int bytes)
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
#else
|
||||
|
||||
// if we don't have USBXpress installed then stubs return fail
|
||||
USBXpress::USBXpress() {} // nothing to do - all members are static
|
||||
|
||||
int USBXpress::open(HANDLE *)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int USBXpress::close(HANDLE *)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int USBXpress::read(HANDLE *, unsigned char *, int)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int USBXpress::write(HANDLE *, unsigned char *, int)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif // USBXpress
|
||||
#endif // Win32
|
||||
|
||||
@@ -79,6 +79,12 @@ D2XX_INCLUDE = /usr/local/include/D2XX
|
||||
# pathname (SiLabs in your root directory)
|
||||
#USBXPRESS_INSTALL=/c/SiLabs/MCU/USBXpress/USBXpress_API/Host/
|
||||
|
||||
# ** note this is also only required on windowsto work with
|
||||
# ** Garmin USB2 sticks whose driver uses libusb-win32.
|
||||
# You must make sure you install v0.1.12.2 of libusb-win from:
|
||||
# http://sourceforge.net/projects/libusb-win32/files/libusb-win32-releases/0.1.12.2/
|
||||
#LIBUSB_INSTALL=/c/libusb-win32-device-bin-0.1.12.2
|
||||
|
||||
# We recommend a debug build for development, and a static build for releases.
|
||||
CONFIG += debug
|
||||
#CONFIG += static
|
||||
|
||||
14
src/src.pro
14
src/src.pro
@@ -76,14 +76,20 @@ qwt3d {
|
||||
LIBS += $${ICAL_LIBS}
|
||||
}
|
||||
|
||||
# are we supporting USB1 devices on Windows?
|
||||
!isEmpty( USBXPRESS_INSTALL ) {
|
||||
LIBS += $${USBXPRESS_INSTALL}/x86/SiUSBXp.lib
|
||||
INCLUDEPATH += $${USBXPRESS_INSTALL}
|
||||
SOURCES += USBXpress.cpp
|
||||
HEADERS += USBXpress.h
|
||||
DEFINES += GC_HAVE_USBXPRESS
|
||||
}
|
||||
|
||||
# are we supporting USB2 devices on Windows?
|
||||
!isEmpty( LIBUSB_INSTALL ) {
|
||||
LIBS += $${LIBUSB_INSTALL}/lib/msvc/libusb.lib
|
||||
INCLUDEPATH += $${LIBUSB_INSTALL}/include
|
||||
DEFINES += GC_HAVE_LIBUSB
|
||||
}
|
||||
|
||||
macx {
|
||||
LIBS += -lobjc -framework Carbon -framework AppKit
|
||||
HEADERS += QtMacSegmentedButton.h
|
||||
@@ -101,6 +107,10 @@ win32 {
|
||||
-Wl,--script,win32/i386pe.x-no-rdata,--enable-auto-import
|
||||
//QMAKE_CXXFLAGS += -fdata-sections
|
||||
RC_FILE = windowsico.rc
|
||||
|
||||
# Windows only USB support
|
||||
SOURCES += USBXpress.cpp LibUsb.cpp
|
||||
HEADERS += USBXpress.h LibUsb.h
|
||||
}
|
||||
|
||||
# local qxt widgets - rather than add another dependency on libqxt
|
||||
|
||||
Reference in New Issue
Block a user