better vnd interface probing

This commit is contained in:
Triss 2021-07-13 03:41:38 +02:00
parent ca1c1caafd
commit 2e235770d3
4 changed files with 45 additions and 24 deletions

View File

@ -230,6 +230,7 @@ libco is licensed under the [ISC license](https://opensource.org/licenses/ISC)
## TODO
- [ ] A name
- [ ] A (VID and) PID, and maybe better subclass & protocol IDs for the vnd cfg itf
- [x] CMSIS-DAP JTAG implementation
- [x] Flashrom/SPI support using Serprog
- Parallel ROM flashing support, too, by having the device switch into a
@ -254,7 +255,7 @@ libco is licensed under the [ISC license](https://opensource.org/licenses/ISC)
it'll be used for other stuff anyway, etc.). Means a custom Linux driver but
oh well, I2C-Tiny-USB needs patching either way.
- [ ] 1-wire using ↑
- [ ] A proper interface for sending commands etc. instead of shoehorning it
- [x] A proper interface for sending commands etc. instead of shoehorning it
into Serprog.
- Can probably be included in the "Better USB interface stuff".
- [ ] JTAG pinout detector

View File

@ -287,10 +287,14 @@ static int dmj_check_hw(struct dmj_dev *dmj)
ret = dmj_xfer_internal(dmj, DMJ_CMD_CFG_GET_VERSION,
DMJ_XFER_FLAGS_PARSE_RESP, NULL, 0, &protover, &len);
if (ret < 0) { /* TODO: positive error codes from respstat */
if (ret < 0) {
dev_err(dev, "USB fail: %d\n", ret);
return ret;
}
if (ret) {
dev_err(dev, "USB protocol fail: %s (%d)\n", dmj_get_protoerr(ret), ret);
return -EIO;
}
if (len < sizeof(protover)) {
dev_err(dev, "USB fail remoteio: %d\n", len);
return -EREMOTEIO;
@ -321,7 +325,11 @@ static int dmj_print_info(struct dmj_dev *dmj)
len = sizeof(strinfo)-1;
ret = dmj_xfer_internal(dmj, DMJ_CMD_CFG_GET_INFOSTR,
DMJ_XFER_FLAGS_PARSE_RESP, NULL, 0, strinfo, &len);
if (ret < 0) return ret; /* TODO: positive error codes from respstat */
if (ret < 0) return ret;
if (ret) {
dev_err(dev, "USB protocol fail: %s (%d)\n", dmj_get_protoerr(ret), ret);
return -EIO;
}
if (len >= sizeof(strinfo)) return -EMSGSIZE;
strinfo[len] = 0; /*strinfo[64] = 0;*/
dev_info(dev, HARDWARE_NAME " '%s'\n", strinfo);
@ -418,32 +426,35 @@ static const struct mfd_cell dmj_mfd_i2c[] = {
static int dmj_probe(struct usb_interface *itf, const struct usb_device_id *usb_id)
{
struct usb_host_interface *hostitf = itf->cur_altsetting;
struct usb_endpoint_descriptor *epin, *epout;
struct usb_endpoint_descriptor *epin = NULL, *epout = NULL, *curep;
struct device *dev = &itf->dev;
struct dmj_dev *dmj;
int ret;
int ret, i;
/*dev_dbg(dev, "dmj probe itfn=%d nendp=%d\n",
hostitf->desc.bInterfaceNumber, hostitf->desc.bNumEndpoints);*/
if (hostitf->desc.bInterfaceNumber != 0 || hostitf->desc.bNumEndpoints < 2)
if (hostitf->desc.bNumEndpoints < 2)
return -ENODEV;
/* TODO: query endpoints in a better way */
epout = &hostitf->endpoint[DMJ_VND_CFG_EP_OUT].desc;
epin = &hostitf->endpoint[DMJ_VND_CFG_EP_IN].desc;
for (i = 0; i < hostitf->desc.bNumEndpoints; ++i) {
curep = &hostitf->endpoint[i].desc;
/*dev_dbg(dev, "epout addr=0x%02x, epin addr=0x%02x\n",
epout->bEndpointAddress, epin->bEndpointAddress);*/
if (!epin && usb_endpoint_is_bulk_in (curep)) epin = curep;
if (!epout && usb_endpoint_is_bulk_out(curep)) epout = curep;
if (!usb_endpoint_is_bulk_out(epout)) { dev_warn(dev, "aaa1\n"); return -ENODEV; }
if (!usb_endpoint_is_bulk_in(epin)) { dev_warn(dev, "aaa1\n"); return -ENODEV; }
if (epin && epout) break;
}
if (!epin) {
dev_warn(dev, "found suitable device but no ep in\n");
return -ENODEV;
}
if (!epout) {
dev_warn(dev, "found suitable device but no ep out\n");
return -ENODEV;
}
dmj = kzalloc(sizeof(*dmj), GFP_KERNEL);
if (!dmj) return -ENOMEM;
/*dev_dbg(dev, "hi there!\n");*/
dmj->ep_out = epout->bEndpointAddress;
dmj->ep_in = epin->bEndpointAddress;
dmj->usb_dev = usb_get_dev(interface_to_usbdev(itf));
@ -525,7 +536,7 @@ static int dmj_resume(struct usb_interface *itf)
}
static const struct usb_device_id dmj_table[] = {
{ USB_DEVICE(0xcafe, 0x1312) },
{ USB_DEVICE_AND_INTERFACE_INFO(0xcafe, 0x1312, USB_CLASS_VENDOR_SPEC, 42, 69) },
{ }
};
MODULE_DEVICE_TABLE(usb, dmj_table);

View File

@ -164,7 +164,6 @@ static void handle_cmd_cb(uint8_t cmd) {
#define TUD_I2CTINYUSB_DESCRIPTOR(_itfnum, _stridx) \
9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, 0, 0, 0, _stridx \
enum {
STRID_LANGID = 0,
STRID_MANUFACTURER,
@ -264,8 +263,8 @@ static const uint8_t desc_configuration[] = {
TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
#if CFG_TUD_VENDOR > 0
TUD_VENDOR_DESCRIPTOR(ITF_NUM_VND_CFG, STRID_IF_VND_CFG, EPNUM_VND_CFG_OUT,
EPNUM_VND_CFG_IN, CFG_TUD_VENDOR_RX_BUFSIZE),
TUD_VENDOR_DESCRIPTOR_EX(ITF_NUM_VND_CFG, STRID_IF_VND_CFG, EPNUM_VND_CFG_OUT,
EPNUM_VND_CFG_IN, CFG_TUD_VENDOR_RX_BUFSIZE, VND_CFG_SUBCLASS, VND_CFG_PROTOCOL),
#endif
#if defined(DBOARD_HAS_I2C) && defined(MODE_ENABLE_I2CTINYUSB)

View File

@ -5,8 +5,18 @@
#include <stdint.h>
/* the configuration vendor interface must always be the first vendor itf, and
* have endpoint number 1. */
/* the configuration vendor interface has a specific subclass and protocol
* number that can be useful for identification */
#define VND_CFG_SUBCLASS 42
#define VND_CFG_PROTOCOL 69
#define TUD_VENDOR_DESCRIPTOR_EX(_itfnum, _stridx, _epout, _epin, _epsize, _subclass, _protocol) \
/* Interface */\
9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_VENDOR_SPECIFIC, _subclass, _protocol, _stridx,\
/* Endpoint Out */\
7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\
/* Endpoint In */\
7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0
#define VND_CFG_PROTO_VER 0x0010