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:
Mark Liversedge
2011-12-17 12:31:25 +00:00
parent 88dbbb2b11
commit ca45ef310e
4 changed files with 70 additions and 77 deletions

View File

@@ -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 {

View File

@@ -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!!

View File

@@ -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;
}

View File

@@ -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