Пример #1
0
bool
MacroDevice::download( const QDir &tmpdir,
                         QList<DeviceDownloadFile> &files,
                         CancelCallback cancelCallback,
                         ProgressCallback progressCallback,
                         QString &err)
{
    if (MACRO_DEBUG) printf("download O-Synce Macro");

    if (!dev->open(err)) {
        err = "ERROR: open failed: " + err;
        return false;
    }

    statusCallback("Request number of training...");
    if (MACRO_DEBUG) printf("Request number of training\n");

    MacroPacket cmd(NUMBER_OF_TRAINING_REQUESTS);
    cmd.addToPayload(UNKNOWN);

    if (!cmd.write(dev, err)) return false;

    if (cancelCallback())
    {
        err = "download cancelled";
        return false;
    }

    MacroPacket response = MacroPacket();
    response.read(dev, 2, err);

    if (response.payload.size() == 0)
    {
        err = "no data";
        return false;
    }

    char count = response.payload.at(0);

    if (count == 0)
    {
        err = "no data";
        return false;
    }

    response.read(dev, 7*count, err);

    if (!response.verifyCheckSum(dev, err))
    {
        err = "data error";
        return false;
    }

    if (cancelCallback())
    {
        err = "download cancelled";
        return false;
    }

    // create temporary file
    QString tmpl = tmpdir.absoluteFilePath(".macrodl.XXXXXX");
    QTemporaryFile tmp(tmpl);
    tmp.setAutoRemove(false);

    if (!tmp.open()) {
        err = "Failed to create temporary file "
            + tmpl + ": " + tmp.error();
        return false;
    }

    if (MACRO_DEBUG) printf("Acknowledge");
    cmd= MacroPacket(ACKNOWLEDGE);
    cmd.addToPayload(response.command);
    if (!cmd.write(dev, err)) return false;

    // timestamp from the first training
    struct tm start;
    start.tm_sec = bcd2Int(response.payload.at(2));
    start.tm_min = bcd2Int(response.payload.at(3));
    start.tm_hour = bcd2Int(response.payload.at(4));
    start.tm_mday = bcd2Int(response.payload.at(5));
    start.tm_mon = hex2Int(response.payload.at(6)) -1;
    start.tm_year = bcd2Int(response.payload.at(7)) -100;
    start.tm_isdst = -1;

    DeviceDownloadFile file;
    file.extension = "osyn";
    file.name = tmp.fileName();
    file.startTime.setTime_t( mktime( &start ));
    files.append(file);

    QTextStream os(&tmp);
    os << hex;

    for (int i = 0; i < count; i++)
    {
        if (MACRO_DEBUG) printf("Request training %d\n",i);
        statusCallback( QString("Request datas of training %1 / %2...")
            .arg(i+1).arg((int)count) );

        if (cancelCallback())
        {
            err = "download cancelled";
            return false;
        }

        cmd = MacroPacket(TRAINING_DETAIL_REQUEST);
        cmd.addToPayload(i);
        if (!cmd.write(dev, err)) return false;

        if (cancelCallback())
        {
            err = "download cancelled";
            return false;
        }
        bool lastpage = false;
        while (!lastpage)
        {
            MacroPacket response2 = MacroPacket();
            response2.read(dev, 259, err);

            if (!response2.verifyCheckSum(dev, err))
            {
                err = "data error";
                return false;
            }

            if (hexHex2Int(response2.payload.at(0), response2.payload.at(1)) == LAST_PAGE)
                lastpage = true;

            //int training_flag = hex2Int(response2.payload.at(43));
            tmp.write(response2.dataArray());
            progressCallback( QString("training %1/%2... (%3 Bytes)")
                .arg(i+1)
                .arg((int)count)
                .arg(tmp.size()) );
            if (cancelCallback())
            {
                err = "download cancelled";
                return false;
            }

            if (MACRO_DEBUG) printf("Acknowledge\n");

            cmd= MacroPacket(ACKNOWLEDGE);
            cmd.addToPayload(response2.command);
            if (!cmd.write(dev, err)) return false;
        }

     }


    tmp.close();

    dev->close();

    // QTemporaryFile initially has permissions set to 0600.
    // Make it readable by everyone.
    tmp.setPermissions(tmp.permissions()
                       | QFile::ReadOwner | QFile::ReadUser
                       | QFile::ReadGroup | QFile::ReadOther);


    return true;
}
Пример #2
0
bool
PowerTapDevice::download( const QDir &tmpdir,
                         QList<DeviceDownloadFile> &files,
                         CancelCallback cancelCallback,
                         ProgressCallback progressCallback,
                         QString &err)
{
    if (!dev->open(err)) {
        err = "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;

	statusCallback( "Reading version..." );
	if (cancelCallback()) {
	    err = "download cancelled";
	    return false;
	}

	version_len = readUntilNewline(dev, vbuf, sizeof(vbuf), err);
	if (version_len < 0) {
	    err = "Error reading version: " + err;
	    return false;
	}
	if (PT_DEBUG) {
	    printf("read version \"%s\"\n",
		   cEscape(vbuf, version_len).toAscii().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("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");

    statusCallback( "Reading header..." );
    if (cancelCallback()) {
        err = "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 = "ERROR: reading header: " + err;
        else
            err = "ERROR: timeout reading header";
        return false;
    }
    if (PT_DEBUG) {
        printf("read header \"%s\"\n",
               cEscape((char*) header,
                       sizeof(header)).toAscii().constData());
    }
    QVector<unsigned char> records;
    for (size_t i = 0; i < sizeof(header); ++i)
        records.append(header[i]);

    statusCallback( "Reading ride data..." );
    if (cancelCallback()) {
        err = "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 = "ERROR: reading first two: " + err;
            else
                err = "ERROR: timeout reading first two";
            return false;
        }
        if (PT_DEBUG) {
            printf("read 2 bytes: \"%s\"\n",
                   cEscape((char*) buf, 2).toAscii().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 = "ERROR: reading block: " + err;
                return false;
            }
            if (n == 0) {
                err = "ERROR: timeout reading block";
                return false;
            }
            if (PT_DEBUG) {
                printf("read %d bytes: \"%s\"\n", n,
                       cEscape((char*) buf + count, n).toAscii().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 = "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);
            progressCallback( QString("progress: %1:%2")
                .arg(min / 60)
                .arg(min % 60, 2, 10, QLatin1Char('0')));
        }
        if (cancelCallback()) {
            err = "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 = "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 = "Failed to find ride time.";
        tmp.setAutoRemove(true);
        return false;
    }

    files << file;
    return true;
}