Port the Greaseweazle driver to use the serial port rather than raw libusb.

This commit is contained in:
David Given
2021-05-23 12:39:41 +02:00
parent d18e54c5a3
commit 1c1ad2725e
6 changed files with 62 additions and 40 deletions

View File

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

View File

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

View File

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

@@ -0,0 +1,9 @@
#ifndef USBSERIAL_H
#define USBSERIAL_H
class libusb_device_handle;
extern int openUsbSerialDevice(libusb_device_handle* handle);
#endif

View File

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