add vendor itf-based settings & commands for I2C and temp sensor stuff
TODOs are: * add one for SPI too (TODO: look at linux kernel for required features) * document all these commands somewhere * implement linux kernel driver(s) * maaaybeeee fix the I2C-Tiny-USB driver? idk * also grep for minor TODOs in src
This commit is contained in:
parent
779c5e98f4
commit
5c17820a52
|
@ -4,11 +4,10 @@
|
||||||
|
|
||||||
#define DBOARD_HAS_UART
|
#define DBOARD_HAS_UART
|
||||||
#define DBOARD_HAS_CMSISDAP
|
#define DBOARD_HAS_CMSISDAP
|
||||||
|
// TODO: rename to _SPI
|
||||||
#define DBOARD_HAS_SERPROG
|
#define DBOARD_HAS_SERPROG
|
||||||
// FIXME: this one doesn't work yet!!!!! (kernel usb device cfg fails)
|
#define DBOARD_HAS_I2C
|
||||||
// "usb 1-1: can't set config #1, error -32"
|
#define DBOARD_HAS_TEMPSENSOR
|
||||||
/*#define DBOARD_HAS_I2C*/
|
|
||||||
/*#define DBOARD_HAS_TEMPSENSOR*/
|
|
||||||
|
|
||||||
#include "bsp-info.h"
|
#include "bsp-info.h"
|
||||||
|
|
||||||
|
|
|
@ -381,7 +381,7 @@ static inline int i2cex_read_timeout_us(i2c_inst_t* i2c, uint16_t addr, bool a10
|
||||||
return i2cex_read_blocking_until(i2c, addr, a10bit, dst, len, nostop, t);
|
return i2cex_read_blocking_until(i2c, addr, a10bit, dst, len, nostop, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((__const__)) enum ki2c_funcs i2ctu_get_func(void) {
|
__attribute__((__const__)) enum ki2c_funcs i2ctu_dev_get_func(void) {
|
||||||
// TODO: SMBUS_EMUL_ALL => I2C_M_RECV_LEN
|
// TODO: SMBUS_EMUL_ALL => I2C_M_RECV_LEN
|
||||||
// TODO: maybe also PROTOCOL_MANGLING, NOSTART
|
// TODO: maybe also PROTOCOL_MANGLING, NOSTART
|
||||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
|
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
|
||||||
|
|
|
@ -21,6 +21,26 @@
|
||||||
/* CDC-Serprog */
|
/* CDC-Serprog */
|
||||||
#include "m_default/serprog.h"
|
#include "m_default/serprog.h"
|
||||||
|
|
||||||
|
/* temperature sensor */
|
||||||
|
#include "m_default/tempsensor.h"
|
||||||
|
|
||||||
|
// FIXME: this one doesn't work yet!!!!! (kernel usb device cfg fails)
|
||||||
|
// "usb 1-1: can't set config #1, error -32"
|
||||||
|
/*#define MODE_ENABLE_I2CTINYUSB*/
|
||||||
|
|
||||||
|
enum m_default_cmds {
|
||||||
|
mdef_cmd_spi = mode_cmd__specific,
|
||||||
|
mdef_cmd_i2c,
|
||||||
|
mdef_cmd_tempsense
|
||||||
|
};
|
||||||
|
enum m_default_feature {
|
||||||
|
mdef_feat_uart = 1<<0,
|
||||||
|
mdef_feat_cmsisdap = 1<<1,
|
||||||
|
mdef_feat_spi = 1<<2,
|
||||||
|
mdef_feat_i2c = 1<<3,
|
||||||
|
mdef_feat_tempsense = 1<<4,
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef DBOARD_HAS_UART
|
#ifdef DBOARD_HAS_UART
|
||||||
static cothread_t uartthread;
|
static cothread_t uartthread;
|
||||||
static uint8_t uartstack[THREAD_STACK_SIZE];
|
static uint8_t uartstack[THREAD_STACK_SIZE];
|
||||||
|
@ -94,11 +114,46 @@ static void task_cb(void) {
|
||||||
static void handle_cmd_cb(uint8_t cmd) {
|
static void handle_cmd_cb(uint8_t cmd) {
|
||||||
uint8_t resp = 0;
|
uint8_t resp = 0;
|
||||||
|
|
||||||
// TODO: tempsensor control commands!
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case mode_cmd_get_features:
|
case mode_cmd_get_features:
|
||||||
|
#ifdef DBOARD_HAS_UART
|
||||||
|
resp |= mdef_feat_uart;
|
||||||
|
#endif
|
||||||
|
#ifdef DBOARD_HAS_CMSISDAP
|
||||||
|
resp |= mdef_feat_cmsisdap;
|
||||||
|
#endif
|
||||||
|
#ifdef DBOARD_HAS_SERPROG
|
||||||
|
resp |= mdef_feat_spi;
|
||||||
|
#endif
|
||||||
|
#ifdef DBOARD_HAS_I2C
|
||||||
|
resp |= mdef_feat_i2c;
|
||||||
|
#endif
|
||||||
|
#ifdef DBOARD_HAS_TEMPSENSOR
|
||||||
|
resp |= mdef_feat_tempsense;
|
||||||
|
#endif
|
||||||
vnd_cfg_write_resp(cfg_resp_ok, 1, &resp);
|
vnd_cfg_write_resp(cfg_resp_ok, 1, &resp);
|
||||||
break;
|
break;
|
||||||
|
case mdef_cmd_spi:
|
||||||
|
#ifdef DBOARD_HAS_SERPROG
|
||||||
|
sp_spi_bulk_cmd();
|
||||||
|
#else
|
||||||
|
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case mdef_cmd_i2c:
|
||||||
|
#ifdef DBOARD_HAS_I2C
|
||||||
|
i2ctu_bulk_cmd();
|
||||||
|
#else
|
||||||
|
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case mdef_cmd_tempsense:
|
||||||
|
#ifdef DBOARD_HAS_TEMPSENSOR
|
||||||
|
tempsense_bulk_cmd();
|
||||||
|
#else
|
||||||
|
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
|
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
|
||||||
break;
|
break;
|
||||||
|
@ -129,7 +184,7 @@ enum {
|
||||||
#if CFG_TUD_VENDOR > 0
|
#if CFG_TUD_VENDOR > 0
|
||||||
ITF_NUM_VND_CFG,
|
ITF_NUM_VND_CFG,
|
||||||
#endif
|
#endif
|
||||||
#ifdef DBOARD_HAS_I2C
|
#if defined(DBOARD_HAS_I2C) && defined(MODE_ENABLE_I2CTINYUSB)
|
||||||
ITF_NUM_VND_I2CTINYUSB,
|
ITF_NUM_VND_I2CTINYUSB,
|
||||||
#endif
|
#endif
|
||||||
#ifdef DBOARD_HAS_CMSISDAP
|
#ifdef DBOARD_HAS_CMSISDAP
|
||||||
|
@ -156,7 +211,7 @@ enum {
|
||||||
#if CFG_TUD_VENDOR > 0
|
#if CFG_TUD_VENDOR > 0
|
||||||
+ TUD_VENDOR_DESC_LEN
|
+ TUD_VENDOR_DESC_LEN
|
||||||
#endif
|
#endif
|
||||||
#ifdef DBOARD_HAS_I2C
|
#if defined(DBOARD_HAS_I2C) && defined(MODE_ENABLE_I2CTINYUSB)
|
||||||
+ TUD_I2CTINYUSB_LEN
|
+ TUD_I2CTINYUSB_LEN
|
||||||
#endif
|
#endif
|
||||||
#ifdef DBOARD_HAS_CMSISDAP
|
#ifdef DBOARD_HAS_CMSISDAP
|
||||||
|
@ -213,7 +268,7 @@ static const uint8_t desc_configuration[] = {
|
||||||
EPNUM_VND_CFG_IN, 64),
|
EPNUM_VND_CFG_IN, 64),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DBOARD_HAS_I2C
|
#if defined(DBOARD_HAS_I2C) && defined(MODE_ENABLE_I2CTINYUSB)
|
||||||
TUD_I2CTINYUSB_DESCRIPTOR(ITF_NUM_VND_I2CTINYUSB, STRID_IF_VND_I2CTINYUSB),
|
TUD_I2CTINYUSB_DESCRIPTOR(ITF_NUM_VND_I2CTINYUSB, STRID_IF_VND_I2CTINYUSB),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -288,7 +343,7 @@ static void my_hid_set_report_cb(uint8_t instance, uint8_t report_id,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DBOARD_HAS_I2CTINYUSB
|
#if defined(DBOARD_HAS_I2C) && defined(MODE_ENABLE_I2CTINYUSB)
|
||||||
static bool my_vendor_control_xfer_cb(uint8_t rhport, uint8_t ep_addr,
|
static bool my_vendor_control_xfer_cb(uint8_t rhport, uint8_t ep_addr,
|
||||||
tusb_control_request_t const* req) {
|
tusb_control_request_t const* req) {
|
||||||
return i2ctu_ctl_req(rhport, ep_addr, req);
|
return i2ctu_ctl_req(rhport, ep_addr, req);
|
||||||
|
@ -318,7 +373,7 @@ struct mode m_01_default = {
|
||||||
.tud_hid_descriptor_report_cb = my_hid_descriptor_report_cb,
|
.tud_hid_descriptor_report_cb = my_hid_descriptor_report_cb,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(DBOARD_HAS_I2CTINYUSB)
|
#if defined(DBOARD_HAS_I2C) && defined(MODE_ENABLE_I2CTINYUSB)
|
||||||
.tud_vendor_control_xfer_cb = i2ctu_ctl_req,
|
.tud_vendor_control_xfer_cb = i2ctu_ctl_req,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "info.h"
|
#include "info.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
|
#include "vnd_cfg.h"
|
||||||
|
|
||||||
#include "serprog.h"
|
#include "serprog.h"
|
||||||
|
|
||||||
|
@ -219,5 +220,10 @@ static void handle_cmd(void) {
|
||||||
|
|
||||||
void cdc_serprog_task(void) { handle_cmd(); }
|
void cdc_serprog_task(void) { handle_cmd(); }
|
||||||
|
|
||||||
|
void sp_spi_bulk_cmd(void) {
|
||||||
|
// TODO
|
||||||
|
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* DBOARD_HAS_SERPROG */
|
#endif /* DBOARD_HAS_SERPROG */
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,7 @@ enum itu_status i2ctu_dev_read(enum ki2c_flags flags, enum itu_command startstop
|
||||||
void i2ctu_init(void);
|
void i2ctu_init(void);
|
||||||
void i2ctu_deinit(void);
|
void i2ctu_deinit(void);
|
||||||
bool i2ctu_ctl_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const* req);
|
bool i2ctu_ctl_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const* req);
|
||||||
|
void i2ctu_bulk_cmd(void); /* uses data in/out from vnd_cfg.h */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -59,6 +59,7 @@ static inline void sp_spi_op_do(
|
||||||
void cdc_serprog_init(void);
|
void cdc_serprog_init(void);
|
||||||
void cdc_serprog_deinit(void);
|
void cdc_serprog_deinit(void);
|
||||||
void cdc_serprog_task(void);
|
void cdc_serprog_task(void);
|
||||||
|
void sp_spi_bulk_cmd(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
// clang-format on
|
// clang-format on
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "vnd_cfg.h"
|
||||||
|
|
||||||
#ifdef DBOARD_HAS_TEMPSENSOR
|
#ifdef DBOARD_HAS_TEMPSENSOR
|
||||||
|
|
||||||
#include "tempsensor.h"
|
#include "tempsensor.h"
|
||||||
|
@ -251,5 +253,46 @@ int tempsense_do_write(int length, const uint8_t* buf) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tempsense_bulk_cmd(void) {
|
||||||
|
uint16_t temp;
|
||||||
|
uint8_t resp[2];
|
||||||
|
|
||||||
|
switch (vnd_cfg_read_byte()) {
|
||||||
|
case tcmd_get_addr:
|
||||||
|
resp[0] = tempsense_get_addr();
|
||||||
|
vnd_cfg_write_resp(cfg_resp_ok, 1, resp);
|
||||||
|
break;
|
||||||
|
case tcmd_set_addr:
|
||||||
|
resp[0] = tempsense_get_addr();
|
||||||
|
tempsense_set_addr(vnd_cfg_read_byte());
|
||||||
|
resp[1] = tempsense_get_addr();
|
||||||
|
vnd_cfg_write_resp(cfg_resp_ok, 2, resp);
|
||||||
|
break;
|
||||||
|
case tcmd_get_temp:
|
||||||
|
temp = tempsense_dev_get_temp();
|
||||||
|
resp[0] = temp & 0xff;
|
||||||
|
resp[1] = (temp >> 8) & 0xff;
|
||||||
|
vnd_cfg_write_resp(cfg_resp_ok, 2, resp);
|
||||||
|
case tcmd_get_lower:
|
||||||
|
temp = tempsense_dev_get_lower();
|
||||||
|
resp[0] = temp & 0xff;
|
||||||
|
resp[1] = (temp >> 8) & 0xff;
|
||||||
|
vnd_cfg_write_resp(cfg_resp_ok, 2, resp);
|
||||||
|
case tcmd_get_upper:
|
||||||
|
temp = tempsense_dev_get_upper();
|
||||||
|
resp[0] = temp & 0xff;
|
||||||
|
resp[1] = (temp >> 8) & 0xff;
|
||||||
|
vnd_cfg_write_resp(cfg_resp_ok, 2, resp);
|
||||||
|
case tcmd_get_crit:
|
||||||
|
temp = tempsense_dev_get_crit();
|
||||||
|
resp[0] = temp & 0xff;
|
||||||
|
resp[1] = (temp >> 8) & 0xff;
|
||||||
|
vnd_cfg_write_resp(cfg_resp_ok, 2, resp);
|
||||||
|
default:
|
||||||
|
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,15 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum tempsense_cmd {
|
||||||
|
tcmd_get_addr,
|
||||||
|
tcmd_set_addr,
|
||||||
|
tcmd_get_temp,
|
||||||
|
tcmd_get_lower,
|
||||||
|
tcmd_get_upper,
|
||||||
|
tcmd_get_crit
|
||||||
|
};
|
||||||
|
|
||||||
void tempsense_init(void);
|
void tempsense_init(void);
|
||||||
void tempsense_deinit(void);
|
void tempsense_deinit(void);
|
||||||
|
|
||||||
|
@ -19,6 +28,8 @@ int tempsense_do_read(int length, uint8_t* buf);
|
||||||
int tempsense_do_write(int length, const uint8_t* buf);
|
int tempsense_do_write(int length, const uint8_t* buf);
|
||||||
void tempsense_do_stop(void); // stop cond
|
void tempsense_do_stop(void); // stop cond
|
||||||
|
|
||||||
|
void tempsense_bulk_cmd(void);
|
||||||
|
|
||||||
#ifdef DBOARD_HAS_TEMPSENSOR
|
#ifdef DBOARD_HAS_TEMPSENSOR
|
||||||
void tempsense_dev_init(void);
|
void tempsense_dev_init(void);
|
||||||
void tempsense_dev_deinit(void);
|
void tempsense_dev_deinit(void);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// vim: set et:
|
||||||
|
|
||||||
#include "m_default/bsp-feature.h"
|
#include "m_default/bsp-feature.h"
|
||||||
|
|
||||||
|
@ -13,7 +14,7 @@
|
||||||
#include <tusb.h>
|
#include <tusb.h>
|
||||||
#include <device/usbd_pvt.h>
|
#include <device/usbd_pvt.h>
|
||||||
|
|
||||||
#include "m_default/bsp-feature.h"
|
#include "vnd_cfg.h"
|
||||||
|
|
||||||
#include "i2ctinyusb.h"
|
#include "i2ctinyusb.h"
|
||||||
|
|
||||||
|
@ -46,6 +47,61 @@ void i2ctu_deinit(void) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle_probe(struct itu_cmd* cmd) {
|
||||||
|
uint8_t bleh = 0;
|
||||||
|
#ifdef DBOARD_HAS_TEMPSENSOR
|
||||||
|
if (tempsense_get_active() && tempsense_get_addr() == cmd->addr) {
|
||||||
|
if (cmd->cmd & ITU_CMD_I2C_IO_BEGIN_F) tempsense_do_start();
|
||||||
|
int rv = tempsense_do_write(0, &bleh);
|
||||||
|
if (rv < 0 || rv != cmd->len)
|
||||||
|
status = ITU_STATUS_ADDR_NAK;
|
||||||
|
else
|
||||||
|
status = ITU_STATUS_ADDR_ACK;
|
||||||
|
if (cmd->cmd & ITU_CMD_I2C_IO_END_F) tempsense_do_stop();
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
status = i2ctu_dev_write(cmd->flags, cmd->cmd & ITU_CMD_I2C_IO_DIR_MASK,
|
||||||
|
cmd->addr, &bleh, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void handle_read(struct itu_cmd* cmd) {
|
||||||
|
#ifdef DBOARD_HAS_TEMPSENSOR
|
||||||
|
if (tempsense_get_active() && tempsense_get_addr() == cmd->addr) {
|
||||||
|
if (cmd->cmd & ITU_CMD_I2C_IO_BEGIN_F) tempsense_do_start();
|
||||||
|
int rv = tempsense_do_read(
|
||||||
|
cmd->len > sizeof txbuf ? sizeof txbuf : cmd->len, txbuf);
|
||||||
|
if (rv < 0 || rv != cmd->len)
|
||||||
|
status = ITU_STATUS_ADDR_NAK;
|
||||||
|
else
|
||||||
|
status = ITU_STATUS_ADDR_ACK;
|
||||||
|
if (cmd->cmd & ITU_CMD_I2C_IO_END_F) tempsense_do_stop();
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
status = i2ctu_dev_read(cmd->flags, cmd->cmd & ITU_CMD_I2C_IO_DIR_MASK, cmd->addr,
|
||||||
|
txbuf, cmd->len > sizeof txbuf ? sizeof txbuf : cmd->len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void handle_write(struct itu_cmd* cmd) {
|
||||||
|
#ifdef DBOARD_HAS_TEMPSENSOR
|
||||||
|
if (tempsense_get_active() && tempsense_get_addr() == cmd->addr) {
|
||||||
|
if (cmd->cmd & ITU_CMD_I2C_IO_BEGIN_F) tempsense_do_start();
|
||||||
|
// FIXME: fix status handling
|
||||||
|
int rv = tempsense_do_write(cmd->len > sizeof rxbuf ? sizeof rxbuf : cmd->len, rxbuf);
|
||||||
|
if (rv < 0 || rv != cmd->len)
|
||||||
|
status = ITU_STATUS_ADDR_NAK;
|
||||||
|
else
|
||||||
|
status = ITU_STATUS_ADDR_ACK;
|
||||||
|
if (cmd->cmd & ITU_CMD_I2C_IO_END_F) tempsense_do_stop();
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
status = i2ctu_dev_write(cmd->flags, cmd->cmd & ITU_CMD_I2C_IO_DIR_MASK, cmd->addr, rxbuf,
|
||||||
|
cmd->len > sizeof rxbuf ? sizeof rxbuf : cmd->len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool i2ctu_ctl_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const* req) {
|
bool i2ctu_ctl_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const* req) {
|
||||||
(void)rhport;
|
(void)rhport;
|
||||||
|
|
||||||
|
@ -67,22 +123,7 @@ bool i2ctu_ctl_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const*
|
||||||
// printf("WDATA a=%04hx l=%04hx ", cmd.addr, cmd.len);
|
// printf("WDATA a=%04hx l=%04hx ", cmd.addr, cmd.len);
|
||||||
|
|
||||||
// printf("data=%02x %02x...\n", rxbuf[0], rxbuf[1]);
|
// printf("data=%02x %02x...\n", rxbuf[0], rxbuf[1]);
|
||||||
#ifdef DBOARD_HAS_TEMPSENSOR
|
handle_write(&cmd);
|
||||||
if (tempsense_get_active() && tempsense_get_addr() == cmd.addr) {
|
|
||||||
if (cmd.cmd & ITU_CMD_I2C_IO_BEGIN_F) tempsense_do_start();
|
|
||||||
// FIXME: fix status handling
|
|
||||||
int rv = tempsense_do_write(cmd.len > sizeof rxbuf ? sizeof rxbuf : cmd.len, rxbuf);
|
|
||||||
if (rv < 0 || rv != cmd.len)
|
|
||||||
status = ITU_STATUS_ADDR_NAK;
|
|
||||||
else
|
|
||||||
status = ITU_STATUS_ADDR_ACK;
|
|
||||||
if (cmd.cmd & ITU_CMD_I2C_IO_END_F) tempsense_do_stop();
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
status = i2ctu_dev_write(cmd.flags, cmd.cmd & ITU_CMD_I2C_IO_DIR_MASK, cmd.addr, rxbuf,
|
|
||||||
cmd.len > sizeof rxbuf ? sizeof rxbuf : cmd.len);
|
|
||||||
}
|
|
||||||
|
|
||||||
// cancel curcmd
|
// cancel curcmd
|
||||||
curcmd.cmd = 0xff;
|
curcmd.cmd = 0xff;
|
||||||
|
@ -140,44 +181,14 @@ bool i2ctu_ctl_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const*
|
||||||
|
|
||||||
if (cmd.flags & I2C_M_RD) { // read from I2C device
|
if (cmd.flags & I2C_M_RD) { // read from I2C device
|
||||||
// printf("read addr=%04hx len=%04hx ", cmd.addr, cmd.len);
|
// printf("read addr=%04hx len=%04hx ", cmd.addr, cmd.len);
|
||||||
#ifdef DBOARD_HAS_TEMPSENSOR
|
handle_read(&cmd);
|
||||||
if (tempsense_get_active() && tempsense_get_addr() == cmd.addr) {
|
|
||||||
if (cmd.cmd & ITU_CMD_I2C_IO_BEGIN_F) tempsense_do_start();
|
|
||||||
int rv = tempsense_do_read(
|
|
||||||
cmd.len > sizeof txbuf ? sizeof txbuf : cmd.len, txbuf);
|
|
||||||
if (rv < 0 || rv != cmd.len)
|
|
||||||
status = ITU_STATUS_ADDR_NAK;
|
|
||||||
else
|
|
||||||
status = ITU_STATUS_ADDR_ACK;
|
|
||||||
if (cmd.cmd & ITU_CMD_I2C_IO_END_F) tempsense_do_stop();
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
status = i2ctu_dev_read(cmd.flags, cmd.cmd & ITU_CMD_I2C_IO_DIR_MASK, cmd.addr,
|
|
||||||
txbuf, cmd.len > sizeof txbuf ? sizeof txbuf : cmd.len);
|
|
||||||
}
|
|
||||||
// printf("data=%02x %02x...\n", txbuf[0], txbuf[1]);
|
// printf("data=%02x %02x...\n", txbuf[0], txbuf[1]);
|
||||||
return tud_control_xfer(
|
return tud_control_xfer(
|
||||||
rhport, req, txbuf, cmd.len > sizeof txbuf ? sizeof txbuf : cmd.len);
|
rhport, req, txbuf, cmd.len > sizeof txbuf ? sizeof txbuf : cmd.len);
|
||||||
} else { // write
|
} else { // write
|
||||||
// printf("write addr=%04hx len=%04hx ", cmd.addr, cmd.len);
|
// printf("write addr=%04hx len=%04hx ", cmd.addr, cmd.len);
|
||||||
if (cmd.len == 0) { // address probe -> do this here
|
if (cmd.len == 0) { // address probe -> do this here
|
||||||
uint8_t bleh = 0;
|
handle_probe(&cmd);
|
||||||
#ifdef DBOARD_HAS_TEMPSENSOR
|
|
||||||
if (tempsense_get_active() && tempsense_get_addr() == cmd.addr) {
|
|
||||||
if (cmd.cmd & ITU_CMD_I2C_IO_BEGIN_F) tempsense_do_start();
|
|
||||||
int rv = tempsense_do_write(0, &bleh);
|
|
||||||
if (rv < 0 || rv != cmd.len)
|
|
||||||
status = ITU_STATUS_ADDR_NAK;
|
|
||||||
else
|
|
||||||
status = ITU_STATUS_ADDR_ACK;
|
|
||||||
if (cmd.cmd & ITU_CMD_I2C_IO_END_F) tempsense_do_stop();
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
status = i2ctu_dev_write(cmd.flags, cmd.cmd & ITU_CMD_I2C_IO_DIR_MASK,
|
|
||||||
cmd.addr, &bleh, 0);
|
|
||||||
}
|
|
||||||
// printf("probe -> %d\n", status);
|
// printf("probe -> %d\n", status);
|
||||||
return tud_control_status(rhport, req);
|
return tud_control_status(rhport, req);
|
||||||
} else {
|
} else {
|
||||||
|
@ -197,5 +208,77 @@ bool i2ctu_ctl_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const*
|
||||||
return true; // other stage...
|
return true; // other stage...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void i2ctu_bulk_cmd(void) {
|
||||||
|
uint16_t us;
|
||||||
|
uint32_t func, freq;
|
||||||
|
|
||||||
|
switch (vnd_cfg_read_byte()) {
|
||||||
|
case ITU_CMD_ECHO:
|
||||||
|
txbuf[0] = vnd_cfg_read_byte();
|
||||||
|
vnd_cfg_write_resp(cfg_resp_ok, 1, txbuf);
|
||||||
|
break;
|
||||||
|
case ITU_CMD_GET_FUNC:
|
||||||
|
func = i2ctu_dev_get_func();
|
||||||
|
|
||||||
|
txbuf[0] = func & 0xff;
|
||||||
|
txbuf[1] = (func >> 8) & 0xff;
|
||||||
|
txbuf[2] = (func >> 16) & 0xff;
|
||||||
|
txbuf[3] = (func >> 24) & 0xff;
|
||||||
|
vnd_cfg_write_resp(cfg_resp_ok, 4, txbuf);
|
||||||
|
break;
|
||||||
|
case ITU_CMD_SET_DELAY:
|
||||||
|
us = (uint16_t)vnd_cfg_read_byte();
|
||||||
|
us |= ((uint16_t)vnd_cfg_read_byte() << 8);
|
||||||
|
|
||||||
|
if (us == 0) us = 1;
|
||||||
|
freq = 1000 * 1000 / (uint32_t)us;
|
||||||
|
|
||||||
|
if (i2ctu_dev_set_freq(freq, us) != 0)
|
||||||
|
vnd_cfg_write_resp(cfg_resp_ok, 0, NULL);
|
||||||
|
else
|
||||||
|
vnd_cfg_write_resp(cfg_resp_badarg, 0, NULL);
|
||||||
|
break;
|
||||||
|
case ITU_CMD_GET_STATUS:
|
||||||
|
txbuf[0] = status;
|
||||||
|
vnd_cfg_write_resp(cfg_resp_ok, 1, txbuf);
|
||||||
|
break;
|
||||||
|
case ITU_CMD_I2C_IO:
|
||||||
|
case ITU_CMD_I2C_IO_BEGIN:
|
||||||
|
case ITU_CMD_I2C_IO_END:
|
||||||
|
case ITU_CMD_I2C_IO_BEGINEND: {
|
||||||
|
struct itu_cmd cmd;
|
||||||
|
cmd.cmd = vnd_cfg_read_byte();
|
||||||
|
cmd.flags = (uint16_t)vnd_cfg_read_byte();
|
||||||
|
cmd.flags |= (uint16_t)vnd_cfg_read_byte() << 8;
|
||||||
|
cmd.addr = (uint16_t)vnd_cfg_read_byte();
|
||||||
|
cmd.addr |= (uint16_t)vnd_cfg_read_byte() << 8;
|
||||||
|
cmd.len = (uint16_t)vnd_cfg_read_byte();
|
||||||
|
cmd.len |= (uint16_t)vnd_cfg_read_byte() << 8;
|
||||||
|
|
||||||
|
if (cmd.flags & I2C_M_RD) {
|
||||||
|
handle_read(&cmd);
|
||||||
|
us = cmd.len;
|
||||||
|
if (us > sizeof txbuf) us = sizeof txbuf;
|
||||||
|
vnd_cfg_write_resp(cfg_resp_ok, us, txbuf);
|
||||||
|
} else if (cmd.len == 0) {
|
||||||
|
handle_probe(&cmd);
|
||||||
|
txbuf[0] = status;
|
||||||
|
vnd_cfg_write_resp(cfg_resp_ok, 1, txbuf);
|
||||||
|
} else {
|
||||||
|
us = cmd.len;
|
||||||
|
if (us > sizeof rxbuf) us = sizeof rxbuf;
|
||||||
|
for (size_t i = 0; i < us; ++i)
|
||||||
|
rxbuf[i] = vnd_cfg_read_byte();
|
||||||
|
|
||||||
|
handle_write(&cmd);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* DBOARD_HAS_I2C */
|
#endif /* DBOARD_HAS_I2C */
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
.global tusb_plt
|
.global tusb_plt
|
||||||
tusb_plt:
|
tusb_plt:
|
||||||
|
|
||||||
@ sigh, thumb...
|
@ sigh, thumb... (cant do `ldr r12, ...`)
|
||||||
.type tud_hid_get_report_cb, %function
|
.type tud_hid_get_report_cb, %function
|
||||||
.global tud_hid_get_report_cb
|
.global tud_hid_get_report_cb
|
||||||
tud_hid_get_report_cb:
|
tud_hid_get_report_cb:
|
||||||
|
|
|
@ -28,6 +28,8 @@ enum mode_cmd {
|
||||||
mode_cmd_get_name = 0x00,
|
mode_cmd_get_name = 0x00,
|
||||||
mode_cmd_get_version = 0x01,
|
mode_cmd_get_version = 0x01,
|
||||||
mode_cmd_get_features = 0x02,
|
mode_cmd_get_features = 0x02,
|
||||||
|
|
||||||
|
mode_cmd__specific = 0x03
|
||||||
};
|
};
|
||||||
|
|
||||||
enum cfg_resp {
|
enum cfg_resp {
|
||||||
|
@ -35,6 +37,7 @@ enum cfg_resp {
|
||||||
cfg_resp_illcmd = 0x01,
|
cfg_resp_illcmd = 0x01,
|
||||||
cfg_resp_badmode = 0x02,
|
cfg_resp_badmode = 0x02,
|
||||||
cfg_resp_nosuchmode = 0x03,
|
cfg_resp_nosuchmode = 0x03,
|
||||||
|
cfg_resp_badarg = 0x04
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t vnd_cfg_read_byte (void);
|
uint8_t vnd_cfg_read_byte (void);
|
||||||
|
|
Loading…
Reference in New Issue