mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-13 16:18:42 +00:00
Tacx Fortius fixes for Mac OSX
Under Mac OSX the Tacx Fortius support needed a few minor tweaks; * sleep 60ms between read/write operations to avoid interrupt errors * clear_halt on read/write endpoints before attempting to read/write to the device * remove the errant usb_reset which really should not have been called in LibUsb since it deletes the device structure(!) The LibUsb class has been modified to clear_halt when opening ANT devices too -- since regression testing on Mac showed that a) you need the latest drivers to work with a USB2 stick on Lion (64bit) and it now appears to mandate a clear_halt when opening the device (but this may be related to the Garmin ANT agent leaving it in an unknown state).
This commit is contained in:
@@ -108,7 +108,7 @@ ANT::ANT(QObject *parent, DeviceConfiguration *devConf) : QThread(parent)
|
||||
// sticks, if it is not available we use stubs
|
||||
#if defined GC_HAVE_LIBUSB
|
||||
usbMode = USBNone;
|
||||
usb2 = new LibUsb();
|
||||
usb2 = new LibUsb(TYPE_ANT);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -671,7 +671,7 @@ int ANT::openPort()
|
||||
int rc;
|
||||
|
||||
// on windows we try on USB2 then on USB1 then fail...
|
||||
if ((rc=usb2->open(TYPE_ANT)) != -1) {
|
||||
if ((rc=usb2->open()) != -1) {
|
||||
usbMode = USB2;
|
||||
return rc;
|
||||
} else if ((rc= USBXpress::open(&devicePort)) != -1) {
|
||||
@@ -693,7 +693,7 @@ int ANT::openPort()
|
||||
|
||||
#ifdef GC_HAVE_LIBUSB
|
||||
int rc;
|
||||
if ((rc=usb2->open(TYPE_ANT)) != -1) {
|
||||
if ((rc=usb2->open()) != -1) {
|
||||
usbMode = USB2;
|
||||
return rc;
|
||||
} else {
|
||||
|
||||
@@ -66,7 +66,7 @@ Fortius::Fortius(QObject *parent, QString) : QThread(parent)
|
||||
memcpy(SLOPE_Command, slope_command, 12);
|
||||
|
||||
// for interacting over the USB port
|
||||
usb2 = new LibUsb();
|
||||
usb2 = new LibUsb(TYPE_FORTIUS);
|
||||
}
|
||||
|
||||
Fortius::~Fortius()
|
||||
@@ -327,6 +327,10 @@ void Fortius::run()
|
||||
|
||||
if (readMessage() > 0) {
|
||||
|
||||
msleep(60); //slow down - need to wait for previous interrupt to clear
|
||||
// before reading. Not sure why, but solves issues
|
||||
// when working on OSX, and possibly Windows
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// UPDATE BASIC TELEMETRY (HR, CAD, SPD et al)
|
||||
// The data structure is very simple, no bit twiddling needed here
|
||||
@@ -499,7 +503,7 @@ int Fortius::closePort()
|
||||
int Fortius::openPort()
|
||||
{
|
||||
// on windows we try on USB2 then on USB1 then fail...
|
||||
return usb2->open(TYPE_FORTIUS);
|
||||
return usb2->open();
|
||||
}
|
||||
|
||||
int Fortius::rawWrite(uint8_t *bytes, int size) // unix!!
|
||||
|
||||
128
src/LibUsb.cpp
128
src/LibUsb.cpp
@@ -26,7 +26,7 @@
|
||||
#include "Settings.h"
|
||||
#include "MainWindow.h"
|
||||
|
||||
LibUsb::LibUsb()
|
||||
LibUsb::LibUsb(int type) : type(type)
|
||||
{
|
||||
|
||||
// dynamic load of libusb on Windows, it is statically linked in Linux
|
||||
@@ -63,34 +63,36 @@ LibUsb::LibUsb()
|
||||
|
||||
usb_set_debug(0);
|
||||
|
||||
#ifdef WIN32 // we initialise whenever we open on Linux/Mac
|
||||
// Initialize the library.
|
||||
usb_init();
|
||||
if (OperatingSystem != WINDOWS) {
|
||||
// Initialize the library.
|
||||
usb_init();
|
||||
|
||||
// Find all busses.
|
||||
usb_find_busses();
|
||||
// Find all busses.
|
||||
usb_find_busses();
|
||||
|
||||
// Find all connected devices.
|
||||
usb_find_devices();
|
||||
#endif
|
||||
// Find all connected devices.
|
||||
usb_find_devices();
|
||||
}
|
||||
}
|
||||
|
||||
int LibUsb::open(int type)
|
||||
int LibUsb::open()
|
||||
{
|
||||
|
||||
#ifdef WIN32
|
||||
if (!isDllLoaded) return -1;
|
||||
#else
|
||||
if (OperatingSystem == WINDOWS) {
|
||||
|
||||
// Initialize the library.
|
||||
usb_init();
|
||||
if (!isDllLoaded) return -1;
|
||||
|
||||
// Find all busses.
|
||||
usb_find_busses();
|
||||
} else {
|
||||
|
||||
// Find all connected devices.
|
||||
usb_find_devices();
|
||||
#endif
|
||||
// Initialize the library.
|
||||
usb_init();
|
||||
|
||||
// Find all busses.
|
||||
usb_find_busses();
|
||||
|
||||
// Find all connected devices.
|
||||
usb_find_devices();
|
||||
}
|
||||
|
||||
readBufSize = 0;
|
||||
readBufIndex = 0;
|
||||
@@ -108,23 +110,11 @@ int LibUsb::open(int type)
|
||||
|
||||
if (device == NULL) return -1;
|
||||
|
||||
int rc;
|
||||
#ifndef WIN32
|
||||
// reset the device, god only knows what mess we left it in...
|
||||
rc = usb_reset(device);
|
||||
if (rc < 0) qDebug()<<"usb_reset Error: "<< usb_strerror();
|
||||
#endif
|
||||
// Clear halt is needed, but ignore return code
|
||||
usb_clear_halt(device, writeEndpoint);
|
||||
usb_clear_halt(device, readEndpoint);
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
// these functions fail on OS X Lion
|
||||
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();
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LibUsb::close()
|
||||
@@ -145,9 +135,7 @@ int LibUsb::read(char *buf, int bytes)
|
||||
// check it isn't closed already
|
||||
if (!device) return -1;
|
||||
|
||||
#ifdef WIN32
|
||||
if (!isDllLoaded) return -1;
|
||||
#endif
|
||||
if (OperatingSystem == WINDOWS && !isDllLoaded) return -1;
|
||||
|
||||
// The USB2 stick really doesn't like you reading 1 byte when more are available
|
||||
// so we use a local buffered read
|
||||
@@ -203,18 +191,17 @@ int LibUsb::write(char *buf, int bytes)
|
||||
// check it isn't closed
|
||||
if (!device) return -1;
|
||||
|
||||
#ifdef WIN32
|
||||
if (!isDllLoaded) return -1;
|
||||
#endif
|
||||
if (OperatingSystem == WINDOWS && !isDllLoaded) return -1;
|
||||
|
||||
#ifdef WIN32
|
||||
int rc = usb_interrupt_write(device, writeEndpoint, buf, bytes, 1000);
|
||||
#else
|
||||
// we use a non-interrupted write on Linux/Mac since the interrupt
|
||||
// write block size is incorectly implemented in the version of
|
||||
// libusb we build with. It is no less efficent.
|
||||
int rc = usb_bulk_write(device, writeEndpoint, buf, bytes, 125);
|
||||
#endif
|
||||
int rc;
|
||||
if (OperatingSystem == WINDOWS) {
|
||||
rc = usb_interrupt_write(device, writeEndpoint, buf, bytes, 1000);
|
||||
} else {
|
||||
// we use a non-interrupted write on Linux/Mac since the interrupt
|
||||
// write block size is incorectly implemented in the version of
|
||||
// libusb we build with. It is no less efficent.
|
||||
rc = usb_bulk_write(device, writeEndpoint, buf, bytes, 125);
|
||||
}
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
@@ -324,21 +311,22 @@ struct usb_dev_handle* LibUsb::OpenFortius()
|
||||
int rc = usb_set_configuration(udev, 1);
|
||||
if (rc < 0) {
|
||||
qDebug()<<"usb_set_configuration Error: "<< usb_strerror();
|
||||
#ifdef __linux__
|
||||
// looks like the udev rule has not been implemented
|
||||
qDebug()<<"check permissions on:"<<QString("/dev/bus/usb/%1/%2").arg(bus->dirname).arg(dev->filename);
|
||||
qDebug()<<"did you remember to setup a udev rule for this device?";
|
||||
#endif
|
||||
|
||||
if (OperatingSystem == LINUX) {
|
||||
// looks like the udev rule has not been implemented
|
||||
qDebug()<<"check permissions on:"<<QString("/dev/bus/usb/%1/%2").arg(bus->dirname).arg(dev->filename);
|
||||
qDebug()<<"did you remember to setup a udev rule for this device?";
|
||||
}
|
||||
}
|
||||
|
||||
rc = usb_claim_interface(udev, interface);
|
||||
if (rc < 0) qDebug()<<"usb_claim_interface Error: "<< usb_strerror();
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
// fails on Mac OS X, we don't actually need it anyway
|
||||
rc = usb_set_altinterface(udev, alternate);
|
||||
if (rc < 0) qDebug()<<"usb_set_altinterface Error: "<< usb_strerror();
|
||||
#endif
|
||||
if (OperatingSystem != OSX) {
|
||||
// fails on Mac OS X, we don't actually need it anyway
|
||||
rc = usb_set_altinterface(udev, alternate);
|
||||
if (rc < 0) qDebug()<<"usb_set_altinterface Error: "<< usb_strerror();
|
||||
}
|
||||
|
||||
return udev;
|
||||
}
|
||||
@@ -376,21 +364,21 @@ struct usb_dev_handle* LibUsb::OpenAntStick()
|
||||
int rc = usb_set_configuration(udev, 1);
|
||||
if (rc < 0) {
|
||||
qDebug()<<"usb_set_configuration Error: "<< usb_strerror();
|
||||
#ifdef __linux__
|
||||
// looks like the udev rule has not been implemented
|
||||
qDebug()<<"check permissions on:"<<QString("/dev/bus/usb/%1/%2").arg(bus->dirname).arg(dev->filename);
|
||||
qDebug()<<"did you remember to setup a udev rule for this device?";
|
||||
#endif
|
||||
if (OperatingSystem == LINUX) {
|
||||
// looks like the udev rule has not been implemented
|
||||
qDebug()<<"check permissions on:"<<QString("/dev/bus/usb/%1/%2").arg(bus->dirname).arg(dev->filename);
|
||||
qDebug()<<"did you remember to setup a udev rule for this device?";
|
||||
}
|
||||
}
|
||||
|
||||
rc = usb_claim_interface(udev, interface);
|
||||
if (rc < 0) qDebug()<<"usb_claim_interface Error: "<< usb_strerror();
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
// fails on Mac OS X, we don't actually need it anyway
|
||||
rc = usb_set_altinterface(udev, alternate);
|
||||
if (rc < 0) qDebug()<<"usb_set_altinterface Error: "<< usb_strerror();
|
||||
#endif
|
||||
if (OperatingSystem != OSX) {
|
||||
// fails on Mac OS X, we don't actually need it anyway
|
||||
rc = usb_set_altinterface(udev, alternate);
|
||||
if (rc < 0) qDebug()<<"usb_set_altinterface Error: "<< usb_strerror();
|
||||
}
|
||||
|
||||
return udev;
|
||||
}
|
||||
|
||||
@@ -52,8 +52,8 @@ class MainWindow;
|
||||
class LibUsb {
|
||||
|
||||
public:
|
||||
LibUsb();
|
||||
int open(int type);
|
||||
LibUsb(int type);
|
||||
int open();
|
||||
void close();
|
||||
int read(char *buf, int bytes);
|
||||
int write(char *buf, int bytes);
|
||||
@@ -107,6 +107,7 @@ private:
|
||||
int readBufSize;
|
||||
|
||||
bool isDllLoaded;
|
||||
int type;
|
||||
};
|
||||
#endif
|
||||
#endif // gc_LibUsb_h
|
||||
|
||||
Reference in New Issue
Block a user