i2c module stuff, firmware now correctly handles error conditions
This commit is contained in:
parent
f163c38823
commit
16963bd39b
|
@ -4,7 +4,6 @@
|
|||
|
||||
#define DBOARD_HAS_UART
|
||||
#define DBOARD_HAS_CMSISDAP
|
||||
// TODO: rename to _SPI
|
||||
#define DBOARD_HAS_SPI
|
||||
#define DBOARD_HAS_I2C
|
||||
#define DBOARD_HAS_TEMPSENSOR
|
||||
|
|
|
@ -87,17 +87,18 @@ epout.write(b'\x12') # get mode1 features
|
|||
print("stat=%d"%stat)
|
||||
print(res)
|
||||
|
||||
epout.write(b'\x20') # get mode1 name
|
||||
print("echo time!")
|
||||
epout.write(b'\x14\x00\x42') # I2C echo!
|
||||
(stat, res) = rdresp(epin)
|
||||
print("stat=%d"%stat)
|
||||
print(res)
|
||||
|
||||
epout.write(b'\x21') # get mode1 version
|
||||
epout.write(b'\x1f\x14\x00\x43')
|
||||
(stat, res) = rdresp(epin)
|
||||
print("stat=%d"%stat)
|
||||
print(res)
|
||||
|
||||
epout.write(b'\x22') # get mode1 features
|
||||
epout.write(b'\x14\x00\x44') # I2C echo!
|
||||
(stat, res) = rdresp(epin)
|
||||
print("stat=%d"%stat)
|
||||
print(res)
|
||||
|
|
|
@ -453,17 +453,19 @@ static int dmj_probe(struct usb_interface *itf, const struct usb_device_id *usb_
|
|||
goto out_free;
|
||||
}
|
||||
|
||||
if (dmj->dmj_mode & DMJ_FEATURE_MODE1_SPI) {
|
||||
if (dmj->dmj_m1feature & DMJ_FEATURE_MODE1_SPI) {
|
||||
// TODO: add SPI MFD
|
||||
}
|
||||
if (dmj->dmj_mode & DMJ_FEATURE_MODE1_I2C) {
|
||||
if (dmj->dmj_m1feature & DMJ_FEATURE_MODE1_I2C) {
|
||||
ret = mfd_add_hotplug_devices(dev, dmj_mfd_i2c, ARRAY_SIZE(dmj_mfd_i2c));
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to add MFD I2C devices\n");
|
||||
goto out_free;
|
||||
} else {
|
||||
dev_warn(dev, "added i2c mfd\n");
|
||||
}
|
||||
}
|
||||
if (dmj->dmj_mode & DMJ_FEATURE_MODE1_TEMPSENSOR) {
|
||||
if (dmj->dmj_m1feature & DMJ_FEATURE_MODE1_TEMPSENSOR) {
|
||||
// TODO: add tempsensor MFD
|
||||
}
|
||||
}
|
||||
|
|
|
@ -219,7 +219,7 @@ static int dmj_i2c_check_hw(struct platform_device *pdev)
|
|||
len = sizeof(curmode);
|
||||
ret = dmj_transfer(pdev, DMJ_CMD_CFG_GET_CUR_MODE,
|
||||
DMJ_XFER_FLAGS_PARSE_RESP, NULL, 0, &curmode, &len);
|
||||
ret = dmj_check_retval(ret, len, dev, "i2c test", true, sizeof(curmode), sizeof(curmode));
|
||||
ret = dmj_check_retval(ret, len, dev, "i2c test 1", true, sizeof(curmode), sizeof(curmode));
|
||||
if (ret < 0) return ret;
|
||||
if (curmode != 0x1) {
|
||||
dev_err(dev, "device must be in mode 1 for ICD to work, but it is in mode %d\n", curmode);
|
||||
|
@ -229,7 +229,7 @@ static int dmj_i2c_check_hw(struct platform_device *pdev)
|
|||
len = sizeof(m1ver);
|
||||
ret = dmj_transfer(pdev, (1<<4) | DMJ_CMD_MODE_GET_VERSION,
|
||||
DMJ_XFER_FLAGS_PARSE_RESP, NULL, 0, &m1ver, &len);
|
||||
ret = dmj_check_retval(ret, len, dev, "i2c test", true, sizeof(m1ver), sizeof(m1ver));
|
||||
ret = dmj_check_retval(ret, len, dev, "i2c test 2", true, sizeof(m1ver), sizeof(m1ver));
|
||||
if (ret < 0) return ret;
|
||||
if (le16_to_cpu(m1ver) > ver_max || le16_to_cpu(m1ver) < ver_min) {
|
||||
dev_err(dev, "bad mode 1 version %04x on device, must be between %04x and %04x\n",
|
||||
|
@ -240,7 +240,7 @@ static int dmj_i2c_check_hw(struct platform_device *pdev)
|
|||
len = sizeof(m1feat);
|
||||
ret = dmj_transfer(pdev, (1<<4) | DMJ_CMD_MODE_GET_FEATURES,
|
||||
DMJ_XFER_FLAGS_PARSE_RESP, NULL, 0, &m1feat, &len);
|
||||
ret = dmj_check_retval(ret, len, dev, "i2c test", true, sizeof(m1feat), sizeof(m1feat));
|
||||
ret = dmj_check_retval(ret, len, dev, "i2c test 3", true, sizeof(m1feat), sizeof(m1feat));
|
||||
if (ret < 0) return ret;
|
||||
if (!(m1feat & DMJ_FEATURE_MODE1_I2C)) {
|
||||
dev_err(dev, "device's mode 1 does not support I2C\n");
|
||||
|
@ -286,6 +286,8 @@ static int dmj_i2c_probe(struct platform_device *pdev)
|
|||
struct dmj_i2c *dmji;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
dev_warn(dev, "i2c probe hi!\n");
|
||||
|
||||
ret = dmj_i2c_check_hw(pdev);
|
||||
if (ret) return -ENODEV;
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
/*#define MODE_ENABLE_I2CTINYUSB*/
|
||||
|
||||
enum m_default_cmds {
|
||||
mdef_cmd_spi = mode_cmd__specific | 0x10,
|
||||
mdef_cmd_spi = mode_cmd__specific,
|
||||
mdef_cmd_i2c,
|
||||
mdef_cmd_tempsense
|
||||
};
|
||||
|
@ -137,25 +137,25 @@ static void handle_cmd_cb(uint8_t cmd) {
|
|||
#ifdef DBOARD_HAS_SPI
|
||||
sp_spi_bulk_cmd();
|
||||
#else
|
||||
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
|
||||
vnd_cfg_write_str(cfg_resp_illcmd, "SPI not implemented on this device");
|
||||
#endif
|
||||
break;
|
||||
case mdef_cmd_i2c:
|
||||
#ifdef DBOARD_HAS_I2C
|
||||
i2ctu_bulk_cmd();
|
||||
#else
|
||||
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
|
||||
vnd_cfg_write_str(cfg_resp_illcmd, "I2C not implemented on this device");
|
||||
#endif
|
||||
break;
|
||||
case mdef_cmd_tempsense:
|
||||
#ifdef DBOARD_HAS_TEMPSENSOR
|
||||
tempsense_bulk_cmd();
|
||||
#else
|
||||
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
|
||||
vnd_cfg_write_str(cfg_resp_illcmd, "temperature sensor not implemented on this device");
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
|
||||
vnd_cfg_write_strf(cfg_resp_illcmd, "unknown mode1 command %02x", cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -276,7 +276,7 @@ void i2ctu_bulk_cmd(void) {
|
|||
} break;
|
||||
|
||||
default:
|
||||
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
|
||||
vnd_cfg_write_str(cfg_resp_illcmd, "unknown I2C command");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// vim: set et:
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <tusb.h>
|
||||
|
||||
|
@ -14,6 +16,8 @@ static uint8_t tx_buf[CFG_TUD_VENDOR_TX_BUFSIZE];
|
|||
|
||||
static uint32_t rxavail, rxpos, txpos;
|
||||
|
||||
static const int VND_N_CFG;
|
||||
|
||||
void vnd_cfg_init(void) {
|
||||
rxavail = 0;
|
||||
rxpos = 0;
|
||||
|
@ -22,13 +26,13 @@ void vnd_cfg_init(void) {
|
|||
|
||||
uint8_t vnd_cfg_read_byte(void) {
|
||||
while (rxavail <= 0) {
|
||||
if (!tud_vendor_n_mounted(0) && !tud_vendor_n_available(0)) {
|
||||
if (!tud_vendor_n_mounted(VND_N_CFG) || !tud_vendor_n_available(VND_N_CFG)) {
|
||||
thread_yield();
|
||||
continue;
|
||||
}
|
||||
|
||||
rxpos = 0;
|
||||
rxavail = tud_vendor_n_read(0, rx_buf, sizeof rx_buf);
|
||||
rxavail = tud_vendor_n_read(VND_N_CFG, rx_buf, sizeof rx_buf);
|
||||
|
||||
if (rxavail == 0) thread_yield();
|
||||
}
|
||||
|
@ -39,13 +43,24 @@ uint8_t vnd_cfg_read_byte(void) {
|
|||
|
||||
return rv;
|
||||
}
|
||||
void vnd_cfg_drop_incoming(void) {
|
||||
rxavail = 0;
|
||||
rxpos = 0;
|
||||
|
||||
// empty tinyusb internal buffer
|
||||
if (tud_vendor_n_mounted(VND_N_CFG)) {
|
||||
while (tud_vendor_n_available(VND_N_CFG)) {
|
||||
tud_vendor_n_read(VND_N_CFG, rx_buf, sizeof rx_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
void vnd_cfg_write_flush(void) {
|
||||
// TODO: is this needed?
|
||||
while (tud_vendor_n_write_available(0) < txpos) {
|
||||
while (tud_vendor_n_write_available(VND_N_CFG) < txpos) {
|
||||
thread_yield();
|
||||
}
|
||||
|
||||
tud_vendor_n_write(0, tx_buf, txpos);
|
||||
tud_vendor_n_write(VND_N_CFG, tx_buf, txpos);
|
||||
txpos = 0;
|
||||
}
|
||||
void vnd_cfg_write_byte(uint8_t v) {
|
||||
|
@ -56,7 +71,7 @@ void vnd_cfg_write_byte(uint8_t v) {
|
|||
tx_buf[txpos] = v;
|
||||
++txpos;
|
||||
}
|
||||
void vnd_cfg_write_resp(enum cfg_resp stat, uint32_t len, const void* data) {
|
||||
void vnd_cfg_write_resp_no_drop(enum cfg_resp stat, uint32_t len, const void* data) {
|
||||
if (len > 0x3fffff) {
|
||||
printf("W: truncating response length from 0x%lx to 0x3fffff\n", len);
|
||||
len = 0x3fffff;
|
||||
|
@ -82,6 +97,23 @@ void vnd_cfg_write_resp(enum cfg_resp stat, uint32_t len, const void* data) {
|
|||
|
||||
vnd_cfg_write_flush();
|
||||
}
|
||||
void vnd_cfg_write_resp(enum cfg_resp stat, uint32_t len, const void* data) {
|
||||
if (stat != cfg_resp_ok) vnd_cfg_drop_incoming();
|
||||
vnd_cfg_write_resp_no_drop(stat, len, data);
|
||||
}
|
||||
void vnd_cfg_write_str(enum cfg_resp stat, const char* str) {
|
||||
vnd_cfg_write_resp(stat, strlen(str), str);
|
||||
}
|
||||
void vnd_cfg_write_strf(enum cfg_resp stat, const char* fmt, ...) {
|
||||
static char pbuf[64];
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(pbuf, sizeof pbuf, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
vnd_cfg_write_str(stat, pbuf);
|
||||
}
|
||||
|
||||
void vnd_cfg_task(void) {
|
||||
uint8_t cmd = vnd_cfg_read_byte();
|
||||
|
@ -157,11 +189,18 @@ void vnd_cfg_task(void) {
|
|||
#else /* CFG_TUD_VENDOR == 0 */
|
||||
void vnd_cfg_init(void) { }
|
||||
uint8_t vnd_cfg_read_byte(void) { return 0xff; }
|
||||
void vnd_cfg_drop_incoming(void) { }
|
||||
void vnd_cfg_write_flush(void) { }
|
||||
void vnd_cfg_write_byte(uint8_t v) { (void)v; }
|
||||
void vnd_cfg_write_resp(enum cfg_resp stat, uint16_t len, const void* data) {
|
||||
(void)stat; (void)len; (void)data;
|
||||
}
|
||||
void vnd_cfg_write_str(enum cfg_resp stat, const char* str) {
|
||||
(void)stat; (void)str;
|
||||
}
|
||||
void vnd_cfg_write_strf(enum cfg_resp stat, const char* fmt, ...) {
|
||||
(void)stat; (void)str;
|
||||
}
|
||||
void vnd_cfg_task(void) { }
|
||||
#endif /* CFG_TUD_VENDOR */
|
||||
|
||||
|
|
|
@ -52,9 +52,14 @@ enum cfg_resp {
|
|||
};
|
||||
|
||||
uint8_t vnd_cfg_read_byte (void);
|
||||
void vnd_cfg_drop_incoming(void);
|
||||
void vnd_cfg_write_flush(void);
|
||||
void vnd_cfg_write_byte(uint8_t v);
|
||||
void vnd_cfg_write_resp_no_drop(enum cfg_resp stat, uint32_t len, const void* data);
|
||||
void vnd_cfg_write_resp(enum cfg_resp stat, uint32_t len, const void* data);
|
||||
void vnd_cfg_write_str(enum cfg_resp stat, const char* str);
|
||||
__attribute__((__format__(printf, 2, 3)))
|
||||
void vnd_cfg_write_strf(enum cfg_resp stat, const char* fmt, ...);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue