mirror of
https://github.com/Klipper3d/klipper.git
synced 2025-08-03 03:54:06 -06:00
lib: Add bossac 1.9 code to lib directory
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
79632878ac
commit
2b9124f3c0
36 changed files with 6287 additions and 0 deletions
332
lib/bossac/src/PosixSerialPort.cpp
Normal file
332
lib/bossac/src/PosixSerialPort.cpp
Normal file
|
@ -0,0 +1,332 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// BOSSA
|
||||
//
|
||||
// Copyright (c) 2011-2018, ShumaTech
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the <organization> nor the
|
||||
// names of its contributors may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#include "PosixSerialPort.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <termios.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifndef B460800
|
||||
#define B460800 460800
|
||||
#endif
|
||||
#ifndef B921600
|
||||
#define B921600 921600
|
||||
#endif
|
||||
|
||||
PosixSerialPort::PosixSerialPort(const std::string& name, bool isUsb) :
|
||||
SerialPort(name), _devfd(-1), _isUsb(isUsb), _timeout(0),
|
||||
_autoFlush(false)
|
||||
{
|
||||
}
|
||||
|
||||
PosixSerialPort::~PosixSerialPort()
|
||||
{
|
||||
if (_devfd >= 0)
|
||||
::close(_devfd);
|
||||
}
|
||||
|
||||
bool
|
||||
PosixSerialPort::open(int baud,
|
||||
int data,
|
||||
SerialPort::Parity parity,
|
||||
SerialPort::StopBit stop)
|
||||
{
|
||||
struct termios options;
|
||||
speed_t speed;
|
||||
// Try opening port assuming _name is full path. If it fails
|
||||
// try "/dev/" + _name
|
||||
_devfd = ::open(_name.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
if (_devfd == -1)
|
||||
{
|
||||
std::string dev("/dev/");
|
||||
dev += _name;
|
||||
_devfd = ::open(dev.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
if (_devfd == -1)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tcgetattr(_devfd, &options) == -1)
|
||||
{
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (baud)
|
||||
{
|
||||
case 1200:
|
||||
speed = B1200;
|
||||
break;
|
||||
case 9600:
|
||||
speed = B9600;
|
||||
break;
|
||||
case 19200:
|
||||
speed = B19200;
|
||||
break;
|
||||
case 38400:
|
||||
speed = B38400;
|
||||
break;
|
||||
case 57600:
|
||||
speed = B57600;
|
||||
break;
|
||||
case 115200:
|
||||
speed = B115200;
|
||||
break;
|
||||
case 230400:
|
||||
speed = B230400;
|
||||
break;
|
||||
case 460800:
|
||||
speed = B460800;
|
||||
break;
|
||||
case 921600:
|
||||
speed = B921600;
|
||||
break;
|
||||
default:
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cfsetispeed(&options, speed) || cfsetospeed(&options, speed))
|
||||
{
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
options.c_cflag |= (CLOCAL | CREAD);
|
||||
|
||||
switch (data)
|
||||
{
|
||||
case 8:
|
||||
options.c_cflag &= ~CSIZE;
|
||||
options.c_cflag |= CS8;
|
||||
break;
|
||||
case 7:
|
||||
options.c_cflag &= ~CSIZE;
|
||||
options.c_cflag |= CS7;
|
||||
break;
|
||||
default:
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (parity)
|
||||
{
|
||||
case SerialPort::ParityNone:
|
||||
options.c_cflag &= ~PARENB;
|
||||
options.c_cflag &= ~PARODD;
|
||||
options.c_iflag &= ~(INPCK | ISTRIP);
|
||||
break;
|
||||
case SerialPort::ParityOdd:
|
||||
options.c_cflag |= PARENB;
|
||||
options.c_cflag |= PARODD;
|
||||
options.c_iflag |= (INPCK | ISTRIP);
|
||||
break;
|
||||
case SerialPort::ParityEven:
|
||||
options.c_cflag |= PARENB;
|
||||
options.c_cflag &= ~PARODD;
|
||||
options.c_iflag |= (INPCK | ISTRIP);
|
||||
break;
|
||||
default:
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (stop)
|
||||
{
|
||||
case StopBitOne:
|
||||
options.c_cflag &= ~CSTOPB;
|
||||
break;
|
||||
case StopBitTwo:
|
||||
options.c_cflag |= CSTOPB;
|
||||
break;
|
||||
default:
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// No hardware flow control
|
||||
options.c_cflag &= ~CRTSCTS;
|
||||
|
||||
// No software flow control
|
||||
options.c_iflag &= ~(IXON | IXOFF | IXANY);
|
||||
|
||||
// Raw input
|
||||
options.c_iflag &= ~(BRKINT | ICRNL);
|
||||
options.c_lflag &= ~(ICANON | IEXTEN | ECHO | ECHOE | ISIG);
|
||||
|
||||
// Raw output
|
||||
options.c_oflag &= ~OPOST;
|
||||
|
||||
// No wait time
|
||||
options.c_cc[VMIN] = 0;
|
||||
options.c_cc[VTIME] = 0;
|
||||
|
||||
if (tcsetattr(_devfd, TCSANOW, &options))
|
||||
{
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PosixSerialPort::close()
|
||||
{
|
||||
if (_devfd >= 0)
|
||||
::close(_devfd);
|
||||
_devfd = -1;
|
||||
}
|
||||
|
||||
int
|
||||
PosixSerialPort::read(uint8_t* buffer, int len)
|
||||
{
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
int numread = 0;
|
||||
int retval;
|
||||
|
||||
if (_devfd == -1)
|
||||
return -1;
|
||||
|
||||
while (numread < len)
|
||||
{
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(_devfd, &fds);
|
||||
|
||||
tv.tv_sec = _timeout / 1000;
|
||||
tv.tv_usec = (_timeout % 1000) * 1000;
|
||||
|
||||
retval = select(_devfd + 1, &fds, NULL, NULL, &tv);
|
||||
|
||||
if (retval < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (retval == 0)
|
||||
{
|
||||
return numread;
|
||||
}
|
||||
else if (FD_ISSET(_devfd, &fds))
|
||||
{
|
||||
retval = ::read(_devfd, (uint8_t*) buffer + numread, len - numread);
|
||||
if (retval < 0)
|
||||
return -1;
|
||||
numread += retval;
|
||||
}
|
||||
}
|
||||
|
||||
return numread;
|
||||
}
|
||||
|
||||
int
|
||||
PosixSerialPort::write(const uint8_t* buffer, int len)
|
||||
{
|
||||
if (_devfd == -1)
|
||||
return -1;
|
||||
|
||||
int res = ::write(_devfd, buffer, len);
|
||||
// Used on macos to avoid upload errors
|
||||
if (_autoFlush)
|
||||
flush();
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
PosixSerialPort::get()
|
||||
{
|
||||
uint8_t byte;
|
||||
|
||||
if (_devfd == -1)
|
||||
return -1;
|
||||
|
||||
if (read(&byte, 1) != 1)
|
||||
return -1;
|
||||
|
||||
return byte;
|
||||
}
|
||||
|
||||
int
|
||||
PosixSerialPort::put(int c)
|
||||
{
|
||||
uint8_t byte;
|
||||
|
||||
byte = c;
|
||||
return write(&byte, 1);
|
||||
}
|
||||
|
||||
void
|
||||
PosixSerialPort::flush()
|
||||
{
|
||||
// There isn't a reliable way to flush on a file descriptor
|
||||
// so we just wait it out. One millisecond is the USB poll
|
||||
// interval so that should cover it.
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
bool
|
||||
PosixSerialPort::timeout(int millisecs)
|
||||
{
|
||||
_timeout = millisecs;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PosixSerialPort::setDTR(bool dtr)
|
||||
{
|
||||
if (_devfd == -1)
|
||||
return;
|
||||
|
||||
int iFlags = TIOCM_DTR;
|
||||
|
||||
ioctl(_devfd, (dtr ? TIOCMBIS : TIOCMBIC), &iFlags);
|
||||
}
|
||||
|
||||
void
|
||||
PosixSerialPort::setRTS(bool rts)
|
||||
{
|
||||
if (_devfd == -1)
|
||||
return;
|
||||
|
||||
int iFlags = TIOCM_RTS;
|
||||
|
||||
ioctl(_devfd, (rts ? TIOCMBIS : TIOCMBIC), &iFlags);
|
||||
}
|
||||
|
||||
void
|
||||
PosixSerialPort::setAutoFlush(bool autoflush)
|
||||
{
|
||||
_autoFlush = autoflush;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue