Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .github/workflows/c-cpp.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: C/C++ CI

on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: configure
run: ./configure
- name: make
run: make
- name: make check
run: make check
- name: make distcheck
run: make distcheck
1 change: 1 addition & 0 deletions checksums-sha256.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c715024872c5df87e27c7655703150b47c07f2526e1ca4c2d32a81da6cdbd57d termux-api-app_v0.51.0+github.debug.apk
366 changes: 366 additions & 0 deletions mcp2210.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,366 @@
/*
* Copyright 2014 Con Kolivas
*
* 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 3 of the License, or (at your option)
* any later version. See COPYING for more details.
*/
#include "miner.h"
#include "usbutils.h"
#include "mcp2210.h"

static bool mcp2210_send(struct cgpu_info *cgpu, char *buf, enum usb_cmds cmd)
{
int amount, err;

if (unlikely(cgpu->usbinfo.nodev))
return false;

err = usb_write(cgpu, buf, MCP2210_BUFFER_LENGTH, &amount, cmd);
if (err || amount != MCP2210_BUFFER_LENGTH) {
applog(LOG_WARNING, "%s %d: Error %d sending %s sent %d of %d",
cgpu->drv->name, cgpu->device_id, err, usb_cmdname(cmd),
amount, MCP2210_BUFFER_LENGTH);
return false;
}
return true;
}

static bool mcp2210_recv(struct cgpu_info *cgpu, char *buf, enum usb_cmds cmd)
{
int amount, err;

if (unlikely(cgpu->usbinfo.nodev))
return false;

err = usb_read(cgpu, buf, MCP2210_BUFFER_LENGTH, &amount, cmd);
if (err || amount != MCP2210_BUFFER_LENGTH) {
applog(LOG_WARNING, "%s %d: Error %d receiving %s received %d of %d",
cgpu->drv->name, cgpu->device_id, err, usb_cmdname(cmd),
amount, MCP2210_BUFFER_LENGTH);
return false;
}
return true;
}

bool mcp2210_send_recv(struct cgpu_info *cgpu, char *buf, enum usb_cmds cmd)
{
uint8_t mcp_cmd = buf[0];

if (!mcp2210_send(cgpu, buf, cmd))
return false;

if (!mcp2210_recv(cgpu, buf, cmd))
return false;

/* Return code should always echo original command */
if (buf[0] != mcp_cmd) {
applog(LOG_WARNING, "%s %d: Response code mismatch, asked for %u got %u",
cgpu->drv->name, cgpu->device_id, mcp_cmd, buf[0]);
return false;
}
return true;
}

bool mcp2210_get_gpio_settings(struct cgpu_info *cgpu, struct mcp_settings *mcp)
{
char buf[MCP2210_BUFFER_LENGTH];
int i;

memset(buf, 0, MCP2210_BUFFER_LENGTH);
buf[0] = MCP2210_GET_GPIO_SETTING;
if (!mcp2210_send_recv(cgpu, buf, C_MCP_GETGPIOSETTING))
return false;

for (i = 0; i < 8; i++) {
mcp->designation.pin[i] = buf[4 + i];
mcp->value.pin[i] = !!(buf[13] & (0x01u << i));
mcp->direction.pin[i] = !!(buf[15] & (0x01u << i));
}
mcp->designation.pin[8] = buf[12];
mcp->value.pin[8] = buf[14] & 0x01u;
mcp->direction.pin[8] = buf[16] & 0x01u;

return true;
}

bool mcp2210_set_gpio_settings(struct cgpu_info *cgpu, struct mcp_settings *mcp)
{
char buf[MCP2210_BUFFER_LENGTH];
uint8_t buf17;
int i;

memset(buf, 0, MCP2210_BUFFER_LENGTH);
buf[0] = MCP2210_GET_GPIO_SETTING;
if (!mcp2210_send_recv(cgpu, buf, C_MCP_GETGPIOSETTING))
return false;
buf17 = buf[17];

memset(buf, 0, MCP2210_BUFFER_LENGTH);
buf[0] = MCP2210_SET_GPIO_SETTING;
buf[17] = buf17;
for (i = 0; i < 8; i++) {
buf[4 + i] = mcp->designation.pin[i];
buf[13] |= mcp->value.pin[i] << i;
buf[15] |= mcp->direction.pin[i] << i;
}
buf[12] = mcp->designation.pin[8];
buf[14] = mcp->value.pin[8];
buf[16] = mcp->direction.pin[8];
return mcp2210_send_recv(cgpu, buf, C_MCP_SETGPIOSETTING);
}

/* Get all the pin designations and store them in a gpio_pin struct */
bool mcp2210_get_gpio_pindes(struct cgpu_info *cgpu, struct gpio_pin *gp)
{
char buf[MCP2210_BUFFER_LENGTH];
int i;

memset(buf, 0, MCP2210_BUFFER_LENGTH);
buf[0] = MCP2210_GET_GPIO_SETTING;
if (!mcp2210_send_recv(cgpu, buf, C_MCP_GETGPIOSETTING))
return false;

for (i = 0; i < 9; i++)
gp->pin[i] = buf[4 + i];
return true;
}


/* Get all the pin vals and store them in a gpio_pin struct */
bool mcp2210_get_gpio_pinvals(struct cgpu_info *cgpu, struct gpio_pin *gp)
{
char buf[MCP2210_BUFFER_LENGTH];
int i;

memset(buf, 0, MCP2210_BUFFER_LENGTH);
buf[0] = MCP2210_GET_GPIO_PIN_VAL;
if (!mcp2210_send_recv(cgpu, buf, C_MCP_GETGPIOPINVAL))
return false;

for (i = 0; i < 8; i++)
gp->pin[i] = !!(buf[4] & (0x01u << i));
gp->pin[8] = buf[5] & 0x01u;

return true;
}

/* Get all the pindirs */
bool mcp2210_get_gpio_pindirs(struct cgpu_info *cgpu, struct gpio_pin *gp)
{
char buf[MCP2210_BUFFER_LENGTH];
int i;

memset(buf, 0, MCP2210_BUFFER_LENGTH);
buf[0] = MCP2210_GET_GPIO_PIN_DIR;
if (!mcp2210_send_recv(cgpu, buf, C_MCP_GETGPIOPINDIR))
return false;

for (i = 0; i < 8; i++)
gp->pin[i] = !!(buf[4] & (0x01u << i));
gp->pin[8] = buf[5] & 0x01u;

return true;
}

/* Get the designation of one pin */
bool mcp2210_get_gpio_pin(struct cgpu_info *cgpu, int pin, int *des)
{
struct gpio_pin gp;

if (!mcp2210_get_gpio_pindes(cgpu, &gp))
return false;

*des = gp.pin[pin];
return true;
}

/* Get one pinval */
bool mcp2210_get_gpio_pinval(struct cgpu_info *cgpu, int pin, int *val)
{
char buf[MCP2210_BUFFER_LENGTH];

memset(buf, 0, MCP2210_BUFFER_LENGTH);
buf[0] = MCP2210_GET_GPIO_PIN_VAL;
if (!mcp2210_send_recv(cgpu, buf, C_MCP_GETGPIOPINVAL))
return false;

buf[0] = MCP2210_GET_GPIO_PIN_VAL;

if (pin < 8)
*val = !!(buf[4] & (0x01u << pin));
else
*val = !!(buf[5] & 0x01u);

return true;
}

/* Get one pindir */
bool mcp2210_get_gpio_pindir(struct cgpu_info *cgpu, int pin, int *dir)
{
char buf[MCP2210_BUFFER_LENGTH];

memset(buf, 0, MCP2210_BUFFER_LENGTH);
buf[0] = MCP2210_GET_GPIO_PIN_DIR;
if (!mcp2210_send_recv(cgpu, buf, C_MCP_GETGPIOPINDIR))
return false;

buf[0] = MCP2210_GET_GPIO_PIN_DIR;

if (pin < 8)
*dir = !!(buf[4] & (0x01u << pin));
else
*dir = !!(buf[5] & 0x01u);

return true;
}

bool mcp2210_spi_cancel(struct cgpu_info *cgpu)
{
char buf[MCP2210_BUFFER_LENGTH];

memset(buf, 0, MCP2210_BUFFER_LENGTH);
buf[0] = MCP2210_SPI_CANCEL;
return mcp2210_send_recv(cgpu, buf, C_MCP_SPICANCEL);
}

/* Abbreviations correspond to:
* IdleChipSelectValue, ActiveChipSelectValue, CSToDataDelay, LastDataByteToCSDelay,
* SubsequentDataByteDelay, BytesPerSPITransfer
*/
bool
mcp2210_get_spi_transfer_settings(struct cgpu_info *cgpu, unsigned int *bitrate, unsigned int *icsv,
unsigned int *acsv, unsigned int *cstdd, unsigned int *ldbtcsd,
unsigned int *sdbd, unsigned int *bpst, unsigned int *spimode)
{
char buf[MCP2210_BUFFER_LENGTH];

memset(buf, 0, MCP2210_BUFFER_LENGTH);
buf[0] = MCP2210_GET_SPI_SETTING;

if (!mcp2210_send_recv(cgpu, buf, C_MCP_GETSPISETTING))
return false;
*bitrate = buf[7] << 24 | buf[6] << 16 | buf[5] << 8 | buf[4];
*icsv = (buf[9] & 0x1) << 8 | buf[8];
*acsv = (buf[11] & 0x1) << 8 | buf[10];
*cstdd = buf[13] << 8 | buf[12];
*ldbtcsd = buf[15] << 8 | buf[14];
*sdbd = buf[17] << 8 | buf[16];
*bpst = buf[19] << 8 | buf[18];
*spimode = buf[20];
return true;
}

bool
mcp2210_set_spi_transfer_settings(struct cgpu_info *cgpu, unsigned int bitrate, unsigned int icsv,
unsigned int acsv, unsigned int cstdd, unsigned int ldbtcsd,
unsigned int sdbd, unsigned int bpst, unsigned int spimode)
{
char buf[MCP2210_BUFFER_LENGTH];
bool ret;

memset(buf, 0, MCP2210_BUFFER_LENGTH);
buf[0] = MCP2210_SET_SPI_SETTING;

buf[4] = bitrate & 0xfful;
buf[5] = (bitrate & 0xff00ul) >> 8;
buf[6] = (bitrate & 0xff0000ul) >> 16;
buf[7] = (bitrate & 0xff000000ul) >> 24;

buf[8] = icsv & 0xff;
buf[9] = (icsv & 0x100) >> 8;

buf[10] = acsv & 0xff;
buf[11] = (acsv & 0x100) >> 8;

buf[12] = cstdd & 0xff;
buf[13] = (cstdd & 0xff00) >> 8;

buf[14] = ldbtcsd & 0xff;
buf[15] = (ldbtcsd & 0xff00) >> 8;

buf[16] = sdbd & 0xff;
buf[17] = (sdbd & 0xff00) >> 8;

buf[18] = bpst & 0xff;
buf[19] = (bpst & 0xff00) >> 8;

buf[20] = spimode;
ret = mcp2210_send_recv(cgpu, buf, C_MCP_SETSPISETTING);
if (!ret)
return ret;
if (buf[1] != 0) {
applog(LOG_DEBUG, "Failed to set spi settings");
return false;
}
return true;
}

/* Perform an spi transfer of *length bytes and return the amount of data
* returned in the same buffer in *length */
bool mcp2210_spi_transfer(struct cgpu_info *cgpu, struct mcp_settings *mcp,
char *data, unsigned int *length)
{
uint8_t res, status, orig_len, offset = 0;
char buf[MCP2210_BUFFER_LENGTH];

if (unlikely(*length > MCP2210_TRANSFER_MAX || !*length)) {
applog(LOG_ERR, "%s %d: Unable to spi transfer %u bytes", cgpu->drv->name,
cgpu->device_id, *length);
return false;
}
if (mcp->bpst != *length) {
/* Set the transfer setting only when it changes. */
mcp->bpst = *length;
if (!mcp2210_set_spi_transfer_settings(cgpu, mcp->bitrate, mcp->icsv,
mcp->acsv, mcp->cstdd, mcp->ldbtcsd, mcp->sdbd, mcp->bpst, mcp->spimode))
return false;
}
orig_len = *length;
retry:
applog(LOG_DEBUG, "%s %d: SPI sending %u bytes", cgpu->drv->name, cgpu->device_id,
*length);
memset(buf, 0, MCP2210_BUFFER_LENGTH);
buf[0] = MCP2210_SPI_TRANSFER;
buf[1] = *length;

if (*length)
memcpy(buf + 4, data + offset, *length);
if (!mcp2210_send_recv(cgpu, buf, C_MCP_SPITRANSFER))
return false;

res = (uint8_t)buf[1];
switch(res) {
case MCP2210_SPI_TRANSFER_SUCCESS:
*length = buf[2];
status = buf[3];
applog(LOG_DEBUG, "%s %d: SPI transfer success, received %u bytes status 0x%x",
cgpu->drv->name, cgpu->device_id, *length, status);
if (*length) {
memcpy(data + offset, buf + 4, *length);
offset += *length;
}
if (status == 0x30) {
/* This shouldn't happen */
applog(LOG_DEBUG, "%s %d: SPI expecting more data inappropriately",
cgpu->drv->name, cgpu->device_id);
return false;
}
if (offset < orig_len) {
*length = 0;
goto retry;
}
*length = orig_len;
return true;
case MCP2210_SPI_TRANSFER_ERROR_IP:
applog(LOG_DEBUG, "%s %d: SPI transfer error in progress",
cgpu->drv->name, cgpu->device_id);
goto retry;
case MCP2210_SPI_TRANSFER_ERROR_NA:
applog(LOG_WARNING, "%s %d: External owner error on mcp2210 spi transfer",
cgpu->drv->name, cgpu->device_id);
default:
return false;
}
}
Loading