Example #1
0
bool
MacroPacket::read(CommPortPtr dev, int len, QString &err)
{
    if (command == 0) {
        if (MACRO_DEBUG) printf("reading command from device\n");
        int n = dev->read(&command, 1, err);
        if (n <= 0) {
            err = (n < 0) ? (tr("read command error: ") + err) : tr("read timeout");
            return false;
        }
        checksum += command;
        len--;
        if (MACRO_DEBUG) printf("command %s\n" ,cEscape(&command,n).toLatin1().constData());
    }

    if (MACRO_DEBUG) printf("reading %d from device\n", len);
    char buf[len];
    int n = dev->read(&buf, len, err);

    if (n <= 0) {
        err = (n < 0) ? (tr("read error: ") + err) : tr("read timeout");
        return false;
    } else if (n < len) {
        err += QString(tr(", read only %1 bytes instead of: %2"))
            .arg(n).arg(len);
        return false;
    }

    if (MACRO_DEBUG) printf("payload %s\n" ,cEscape(buf,n).toLatin1().constData());
    addToPayload(buf,n);

    return true;
}
int
PowerTapDevice::readUntilNewline(CommPortPtr dev, char *buf, int len, QString &err)
{
    int sofar = 0;
    while (!hasNewline(buf, sofar)) {
        assert(sofar < len);
        // Read one byte at a time to avoid waiting for timeout.
        int n = dev->read(buf + sofar, 1, err);
        if (n <= 0) {
            err = (n < 0) ? (tr("read error: ") + err) : tr("read timeout");
            err += QString(tr(", read %1 bytes so far: \"%2\""))
                .arg(sofar).arg(cEscape(buf, sofar));
            return -1;
        }
        sofar += n;
    }
    return sofar;
}
Example #3
0
bool
MacroPacket::write(CommPortPtr dev, QString &err)
{
    const char *msg = cEscape(data(), payload.count()+2).toLatin1().constData();

    if (MACRO_DEBUG) printf("writing '%s' to device\n", msg);

    int n = dev->write(data(), payload.count()+2, err);
    if (n != payload.count()+2) {
        if (n < 0) {
            if (MACRO_DEBUG) printf("failed to write %s to device: %s\n", msg, err.toLatin1().constData());
            err = QString(tr("failed to write to device: %1")).arg(err);
        }
        else {
            if (MACRO_DEBUG) printf("timeout writing %s to device\n", msg);
            err = QString(tr("timeout writing to device"));
        }
        return false;
    }

    if (MACRO_DEBUG) printf("writing to device ok\n");
    return true;
}
bool
PowerTapDevice::download( const QDir &tmpdir,
                         QList<DeviceDownloadFile> &files,
                         QString &err)
{
    if (!dev->open(err)) {
        err = tr("ERROR: open failed: ") + err;
        return false;
    }
    // make several attempts at reading the version
    int attempts = 3;
    int veridx = -1;
    int version_len;
    char vbuf[256];
    QByteArray version;

    do {
	if (!doWrite(dev, 0x56, false, err)) // 'V'
	    return false;

    emit updateStatus( tr("Reading version...") );
    if(m_Cancelled) {
        err = tr("download cancelled");
	    return false;
	}

	version_len = readUntilNewline(dev, vbuf, sizeof(vbuf), err);
	if (version_len < 0) {
	    err = tr("Error reading version: ") + err;
	    return false;
	}
	if (PT_DEBUG) {
	    printf("read version \"%s\"\n",
		   cEscape(vbuf, version_len).toLatin1().constData());
	}
	version = QByteArray(vbuf, version_len);

	// We expect the version string to be something like
	// "VER 02.21 PRO...", so if we see two V's, it's probably
	// because there's a hardware echo going on.
	veridx = version.indexOf("VER");

    } while ((--attempts > 0) && (veridx < 0));

    if (veridx < 0) {
	err = QString(tr("Unrecognized version \"%1\""))
	    .arg(cEscape(vbuf, version_len));
	return false;
    }
    bool hwecho = version.indexOf('V') < veridx;
    if (PT_DEBUG) printf("hwecho=%s\n", hwecho ? "true" : "false");

    emit updateStatus( tr("Reading header...") );
    if(m_Cancelled) {
        err = tr("download cancelled");
        return false;
    }

    if (!doWrite(dev, 0x44, hwecho, err)) // 'D'
        return false;
    unsigned char header[6];
    int header_len = dev->read(header, sizeof(header), err);
    if (header_len != 6) {
        if (header_len < 0)
            err = tr("ERROR: reading header: ") + err;
        else
            err = tr("ERROR: timeout reading header");
        return false;
    }
    if (PT_DEBUG) {
        printf("read header \"%s\"\n",
               cEscape((char*) header,
                       sizeof(header)).toLatin1().constData());
    }
    QVector<unsigned char> records;
    for (size_t i = 0; i < sizeof(header); ++i)
        records.append(header[i]);

    emit updateStatus( tr("Reading data...") );
    if(m_Cancelled) {
        err = tr("download cancelled");
        return false;
    }
    double recIntSecs = 0.0;

    fflush(stdout);
    while (true) {
        if (PT_DEBUG) printf("reading block\n");
        unsigned char buf[256 * 6 + 1];
        int n = dev->read(buf, 2, err);
        if (n < 2) {
            if (n < 0)
                err = tr("ERROR: reading first two: ") + err;
            else
                err = tr("ERROR: timeout reading first two");
            return false;
        }
        if (PT_DEBUG) {
            printf("read 2 bytes: \"%s\"\n",
                   cEscape((char*) buf, 2).toLatin1().constData());
        }
        if (hasNewline((char*) buf, 2))
            break;
        unsigned count = 2;
        while (count < sizeof(buf)) {
            n = dev->read(buf + count, sizeof(buf) - count, err);
            if (n < 0) {
                err = tr("ERROR: reading block: ") + err;
                return false;
            }
            if (n == 0) {
                err = tr("ERROR: timeout reading block");
                return false;
            }
            if (PT_DEBUG) {
                printf("read %d bytes: \"%s\"\n", n,
                       cEscape((char*) buf + count, n).toLatin1().constData());
            }
            count += n;
        }
        unsigned csum = 0;
        for (int i = 0; i < ((int) sizeof(buf)) - 1; ++i)
            csum += buf[i];
        if ((csum % 256) != buf[sizeof(buf) - 1]) {
            err = tr("ERROR: bad checksum");
            return false;
        }
        if (PT_DEBUG) printf("good checksum\n");
        for (size_t i = 0; i < sizeof(buf) - 1; ++i)
            records.append(buf[i]);
        if (recIntSecs == 0.0) {
            unsigned char *data = records.data();
            bool bIsVer81 = PowerTapUtil::is_Ver81(data);
            for (int i = 0; i < records.size(); i += 6) {
                if (PowerTapUtil::is_config(data + i, bIsVer81)) {
                    unsigned unused1, unused2, unused3;
                    PowerTapUtil::unpack_config(
                        data + i, &unused1, &unused2,
                        &recIntSecs, &unused3, bIsVer81);
                }
            }
        }
        if (recIntSecs != 0.0) {
            int min = (int) round(records.size() / 6 * recIntSecs);
            emit updateProgress( QString(tr("progress: %1:%2"))
                .arg(min / 60)
                .arg(min % 60, 2, 10, QLatin1Char('0')));
        }
        if(m_Cancelled){
            err = tr("download cancelled");
            return false;
        }
        if (!doWrite(dev, 0x71, hwecho, err)) // 'q'
            return false;
    }

    QString tmpl = tmpdir.absoluteFilePath(".ptdl.XXXXXX");
    QTemporaryFile tmp(tmpl);
    tmp.setAutoRemove(false);
    if (!tmp.open()) {
        err = tr("Failed to create temporary file ")
            + tmpl + ": " + tmp.error();
        return false;
    }
    // QTemporaryFile initially has permissions set to 0600.
    // Make it readable by everyone.
    tmp.setPermissions(tmp.permissions()
                       | QFile::ReadOwner | QFile::ReadUser
                       | QFile::ReadGroup | QFile::ReadOther);

    DeviceDownloadFile file;
    file.extension = "raw";
    file.name = tmp.fileName();

    QTextStream os(&tmp);
    os << hex;
    os.setPadChar('0');

    bool time_set = false;
    unsigned char *data = records.data();
    bool bIsVer81 = PowerTapUtil::is_Ver81(data);

    for (int i = 0; i < records.size(); i += 6) {
        if (data[i] == 0 && !bIsVer81)
            continue;
        for (int j = 0; j < 6; ++j) {
            os.setFieldWidth(2);
            os << data[i+j];
            os.setFieldWidth(1);
            os << ((j == 5) ? "\n" : " ");
        }
        if (!time_set && PowerTapUtil::is_time(data + i, bIsVer81)) {
            struct tm time;
            time_t timet = PowerTapUtil::unpack_time(data + i, &time, bIsVer81);
            file.startTime.setTime_t( timet );
            time_set = true;
        }
    }
    if (!time_set) {
        err = tr("Failed to find start time.");
        tmp.setAutoRemove(true);
        return false;
    }

    // hack for CERVO bug dates >= 2016 set the year to 2000 (!)
    if (file.startTime.date().year() == 2000) {

        // it's in the past... so set year to this
        QDate date(QDate::currentDate().year(), file.startTime.date().month(), file.startTime.date().day());

        // is that a future date?
        if (date > QDate::currentDate()) date = date.addYears(-1);

        // now update for file, if it's valid otherwise keep as it is
        if(date.isValid()) file.startTime.setDate(date);
    }

    files << file;
    return true;
}