mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Port the Greaseweazle driver to use the serial port rather than raw libusb.
This commit is contained in:
@@ -6,8 +6,17 @@ The FluxEngine isn't the only project which does this; another one is the
|
||||
completely open source solution. This requires more work to set up (or you can
|
||||
buy a prebuilt GreaseWeazle board), but provides completely open source
|
||||
hardware which doesn't require the use of the Cypress Windows-based tools that
|
||||
the FluxEngine does. Luckily, the FluxEngine software supports it
|
||||
out-of-the-box --- just plug it in and nearly everything should work.
|
||||
the FluxEngine does. Luckily, the FluxEngine software supports it almost
|
||||
out-of-the-box --- just plug it in and nearly everything should work. You will
|
||||
may need to tell FluxEngine which serial port the GreaseWeazle is plugged
|
||||
in with; this can only be detected on some platforms:
|
||||
|
||||
```
|
||||
fluxengine read ibm -o ibm.img --usb.serial=/dev/ttyACM3
|
||||
```
|
||||
|
||||
Try it without the `--usb.serial` parameter and see whether it works. You'll
|
||||
get an error if it doesn't.
|
||||
|
||||
I am aware that having _software_ called FluxEngine and _hardware_ called
|
||||
FluxEngine makes things complicated when you're not using the FluxEngine client
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
#include "protocol.h"
|
||||
#include "fluxmap.h"
|
||||
#include "bytes.h"
|
||||
#include <libusb.h>
|
||||
#include "fmt/format.h"
|
||||
#include "greaseweazle.h"
|
||||
|
||||
#define TIMEOUT 5000
|
||||
#include "usbserial.h"
|
||||
#include <unistd.h>
|
||||
|
||||
static const char* gw_error(int e)
|
||||
{
|
||||
@@ -52,12 +51,9 @@ private:
|
||||
if (len == 0)
|
||||
break;
|
||||
|
||||
int actual;
|
||||
int rc = libusb_bulk_transfer(_device, EP_IN,
|
||||
_readbuffer, sizeof(_readbuffer),
|
||||
&actual, TIMEOUT);
|
||||
if (rc < 0)
|
||||
Error() << "failed to receive command reply: " << usberror(rc);
|
||||
ssize_t actual = ::read(_fd, _readbuffer, sizeof(_readbuffer));
|
||||
if (actual < 0)
|
||||
Error() << "failed to receive command reply: " << strerror(actual);
|
||||
|
||||
_readbuffer_fill = actual;
|
||||
_readbuffer_ptr = 0;
|
||||
@@ -91,14 +87,13 @@ private:
|
||||
| ((read_byte() & 0xfe) << 20);
|
||||
}
|
||||
|
||||
void write_bytes(const uint8_t* buffer, int len)
|
||||
void write_bytes(const uint8_t* buffer, size_t len)
|
||||
{
|
||||
while (len > 0)
|
||||
{
|
||||
int actual;
|
||||
int rc = libusb_bulk_transfer(_device, EP_OUT, (uint8_t*)buffer, len, &actual, 0);
|
||||
if (rc < 0)
|
||||
Error() << "failed to send command: " << usberror(rc);
|
||||
ssize_t actual = ::write(_fd, buffer, len);
|
||||
if (actual < 0)
|
||||
Error() << "failed to send command: " << strerror(errno);
|
||||
|
||||
buffer += actual;
|
||||
len -= actual;
|
||||
@@ -127,30 +122,10 @@ private:
|
||||
public:
|
||||
GreaseWeazleUsb(libusb_device_handle* device)
|
||||
{
|
||||
_device = device;
|
||||
|
||||
/* Configure the device. */
|
||||
|
||||
int i;
|
||||
int cfg = -1;
|
||||
libusb_get_configuration(_device, &cfg);
|
||||
if (cfg != 1)
|
||||
{
|
||||
i = libusb_set_configuration(_device, 1);
|
||||
if (i < 0)
|
||||
Error() << "the GreaseWeazle would not accept configuration: " << usberror(i);
|
||||
}
|
||||
|
||||
/* Detach the existing kernel serial port driver, if there is one, and claim it ourselves. */
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (libusb_kernel_driver_active(_device, i))
|
||||
libusb_detach_kernel_driver(_device, i);
|
||||
int rc = libusb_claim_interface(_device, i);
|
||||
if (rc < 0)
|
||||
Error() << "unable to claim interface: " << libusb_error_name(rc);
|
||||
}
|
||||
_fd = openUsbSerialDevice(device);
|
||||
if (_fd == -1)
|
||||
Error() << "cannot autodetect GreaseWeazle serial device path on this platform;"
|
||||
<< " please use --usb.serial=<path>";
|
||||
|
||||
_version = getVersion();
|
||||
if ((_version != 22) && (_version != 24))
|
||||
@@ -419,6 +394,7 @@ public:
|
||||
{ Error() << "unsupported operation on the GreaseWeazle"; }
|
||||
|
||||
private:
|
||||
int _fd;
|
||||
int _version;
|
||||
nanoseconds_t _clock;
|
||||
nanoseconds_t _revolutions;
|
||||
|
||||
@@ -5,5 +5,7 @@ import "lib/common.proto";
|
||||
message UsbProto {
|
||||
optional string device = 1
|
||||
[(help) = "serial number of hardware device to use"];
|
||||
optional string serial = 2
|
||||
[(help) = "path to serial port to devices which need it"];
|
||||
}
|
||||
|
||||
|
||||
25
lib/usb/usbserial.cc
Normal file
25
lib/usb/usbserial.cc
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "globals.h"
|
||||
#include "flags.h"
|
||||
#include "usb.h"
|
||||
#include "bytes.h"
|
||||
#include "fmt/format.h"
|
||||
#include "usbserial.h"
|
||||
#include "proto.h"
|
||||
#include "lib/usb/usb.pb.h"
|
||||
#include <libusb.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
int openUsbSerialDevice(libusb_device_handle* handle)
|
||||
{
|
||||
if (!config.usb().has_serial())
|
||||
return -1;
|
||||
|
||||
std::string path = config.usb().serial();
|
||||
int fd = open(path.c_str(), O_RDWR);
|
||||
if (fd == -1)
|
||||
Error() << fmt::format("unable to open serial device {}: {}", path, strerror(errno));
|
||||
return fd;
|
||||
}
|
||||
|
||||
9
lib/usb/usbserial.h
Normal file
9
lib/usb/usbserial.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef USBSERIAL_H
|
||||
#define USBSERIAL_H
|
||||
|
||||
class libusb_device_handle;
|
||||
|
||||
extern int openUsbSerialDevice(libusb_device_handle* handle);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -357,6 +357,7 @@ buildlibrary libbackend.a \
|
||||
lib/usb/greaseweazle.cc \
|
||||
lib/usb/greaseweazleusb.cc \
|
||||
lib/usb/usb.cc \
|
||||
lib/usb/usbserial.cc \
|
||||
lib/utils.cc \
|
||||
lib/writer.cc \
|
||||
|
||||
|
||||
Reference in New Issue
Block a user