/* * This file is part of the flashrom project. * * Copyright (C) 2016 Marc Schink * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ /* * Driver for the J-Link hardware by SEGGER. * See https://www.segger.com/ for more info. */ #include #include #include #include #include #include #include "flash.h" #include "programmer.h" #include "spi.h" /* * Maximum number of bytes that can be transferred at once via the JTAG * interface, see jaylink_jtag_io(). */ #define JTAG_MAX_TRANSFER_SIZE (32768 / 8) /* * Default base frequency in Hz. Used when the base frequency can not be * retrieved from the device. */ #define DEFAULT_FREQ 16000000 /* * Default frequency divider. Used when the frequency divider can not be * retrieved from the device. */ #define DEFAULT_FREQ_DIV 4 /* Minimum target voltage required for operation in mV. */ #define MIN_TARGET_VOLTAGE 1200 struct jlink_spi_data { struct jaylink_context *ctx; struct jaylink_device_handle *devh; bool reset_cs; bool enable_target_power; }; static bool assert_cs(struct jlink_spi_data *jlink_data) { int ret; if (jlink_data->reset_cs) { ret = jaylink_clear_reset(jlink_data->devh); if (ret != JAYLINK_OK) { msg_perr("jaylink_clear_reset() failed: %s.\n", jaylink_strerror(ret)); return false; } } else { ret = jaylink_jtag_clear_trst(jlink_data->devh); if (ret != JAYLINK_OK) { msg_perr("jaylink_jtag_clear_trst() failed: %s.\n", jaylink_strerror(ret)); return false; } } return true; } static bool deassert_cs(struct jlink_spi_data *jlink_data) { int ret; if (jlink_data->reset_cs) { ret = jaylink_set_reset(jlink_data->devh); if (ret != JAYLINK_OK) { msg_perr("jaylink_set_reset() failed: %s.\n", jaylink_strerror(ret)); return false; } } else { ret = jaylink_jtag_set_trst(jlink_data->devh); if (ret != JAYLINK_OK) { msg_perr("jaylink_jtag_set_trst() failed: %s.\n", jaylink_strerror(ret)); return false; } } return true; } static int jlink_spi_send_command(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr) { uint32_t length; uint8_t *buffer; struct jlink_spi_data *jlink_data = flash->mst->spi.data; length = writecnt + readcnt; if (length > JTAG_MAX_TRANSFER_SIZE) return SPI_INVALID_LENGTH; buffer = malloc(length); if (!buffer) { msg_perr("Memory allocation failed.\n"); return SPI_GENERIC_ERROR; } /* Reverse all bytes because the device transfers data LSB first. */ reverse_bytes(buffer, writearr, writecnt); memset(buffer + writecnt, 0x00, readcnt); if (!assert_cs(jlink_data)) { free(buffer); return SPI_PROGRAMMER_ERROR; } int ret; ret = jaylink_jtag_io(jlink_data->devh, buffer, buffer, buffer, length * 8, JAYLINK_JTAG_VERSION_2); if (ret != JAYLINK_OK) { msg_perr("jaylink_jtag_io() failed: %s.\n", jaylink_strerror(ret)); free(buffer); return SPI_PROGRAMMER_ERROR; } if (!deassert_cs(jlink_data)) { free(buffer); return SPI_PROGRAMMER_ERROR; } /* Reverse all bytes because the device transfers data LSB first. */ reverse_bytes(readarr, buffer + writecnt, readcnt); free(buffer); return 0; } static int jlink_spi_shutdown(void *data) { struct jlink_spi_data *jlink_data = data; if (jlink_data->enable_target_power) { int ret = jaylink_set_target_power(jlink_data->devh, false); if (ret != JAYLINK_OK) { msg_perr("jaylink_set_target_power() failed: %s.\n", jaylink_strerror(ret)); } } if (jlink_data->devh) jaylink_close(jlink_data->devh); jaylink_exit(jlink_data->ctx); /* jlink_data->ctx, jlink_data->devh are freed by jaylink_close and jaylink_exit */ free(jlink_data); return 0; } static const struct spi_master spi_master_jlink_spi = { /* Maximum data read size in one go (excluding opcode+address). */ .max_data_read = JTAG_MAX_TRANSFER_SIZE - 5, /* Maximum data write size in one go (excluding opcode+address). */ .max_data_write = JTAG_MAX_TRANSFER_SIZE - 5, .command = jlink_spi_send_command, .multicommand = default_spi_send_multicommand, .read = default_spi_read, .write_256 = default_spi_write_256, .write_aai = default_spi_write_aai, .features = SPI_MASTER_4BA, .shutdown = jlink_spi_shutdown, .probe_opcode = default_spi_probe_opcode, }; static int jlink_spi_init(void) { char *arg; unsigned long speed = 0; struct jaylink_context *jaylink_ctx = NULL; struct jaylink_device_handle *jaylink_devh = NULL; bool reset_cs; struct jlink_sp
<html>
<head></head>
<body>

<h2>Hoe activeer ik OpenKeychain in K-9 Mail?</h2>
<p>Volg deze stappen om OpenKeychain te gebruiken met K-9 Mail:</p>
<ol>
<li>Open K-9 Mail en druk lang op de account waarmee je OpenKeychain wil gebruiken.</li>
    <li>Selecteer "Accountinstellingen", scroll helemaal naar beneden en klik op "Cryptografie".</li>
    <li>Klik op "OpenPGP-provider" en selecteer OpenKeychain in de lijst.</li>
</ol>
<h2>Ik heb een bug in OpenKeychain gevonden!</h2>
<p>Rapporteer de bug met de <a href="https://github.com/openpgp-keychain/openpgp-keychain/issues">problemen tracker van OpenKeychain</a>.</p>

<h2>Bijdragen</h2>
<p>Als je ons wil helpen om OpenKeychain te ontwikkelen door code bij te dragen, <a href="https://github.com/openpgp-keychain/openpgp-keychain#contribute-code">volg onze kleine gids op Github</a>.</p>

<h2>Vertalingen</h2>
<p>Help OpenKeychain te vertalen! Iedereen kan deelnemen op <a href="https://www.transifex.com/projects/p/openpgp-keychain/">OpenKeychain op Transifex</a>.</p>

</body>
</html>