DFU: fix code to accept tinyDFU implementation (where not altsettings have an DFU descriptor)
This commit is contained in:
parent
d5dcf03fc7
commit
3165552994
48
src/dfu.cpp
48
src/dfu.cpp
|
|
@ -358,23 +358,35 @@ int DFU::searchIfDFU(struct libusb_device_handle *handle,
|
||||||
/* configuration interface iteration */
|
/* configuration interface iteration */
|
||||||
for (int if_idx=0; if_idx < cfg->bNumInterfaces; if_idx++) {
|
for (int if_idx=0; if_idx < cfg->bNumInterfaces; if_idx++) {
|
||||||
const struct libusb_interface *uif = &cfg->interface[if_idx];
|
const struct libusb_interface *uif = &cfg->interface[if_idx];
|
||||||
|
std::vector<struct dfu_dev> dfu_dev_tmp;
|
||||||
|
struct dfu_desc *dfu_desc;
|
||||||
|
bool dfu_found = false;
|
||||||
|
|
||||||
/* altsettings interation */
|
/* altsettings interation */
|
||||||
for (int intf_idx = 0; intf_idx < uif->num_altsetting; intf_idx++) {
|
for (int intf_idx = 0; intf_idx < uif->num_altsetting; intf_idx++) {
|
||||||
const struct libusb_interface_descriptor *intf = &uif->altsetting[intf_idx];
|
const struct libusb_interface_descriptor *intf = &uif->altsetting[intf_idx];
|
||||||
uint8_t intfClass = intf->bInterfaceClass;
|
uint8_t intfClass = intf->bInterfaceClass;
|
||||||
uint8_t intfSubClass = intf->bInterfaceSubClass;
|
uint8_t intfSubClass = intf->bInterfaceSubClass;
|
||||||
if (_altsetting != -1 && _altsetting != intf_idx)
|
|
||||||
continue;
|
|
||||||
if (intfClass == 0xfe && intfSubClass == 0x01) {
|
if (intfClass == 0xfe && intfSubClass == 0x01) {
|
||||||
struct dfu_dev my_dev;
|
struct dfu_dev my_dev;
|
||||||
if (_verbose)
|
if (_verbose)
|
||||||
printInfo("DFU found");
|
printInfo("DFU found");
|
||||||
|
|
||||||
/* dfu functional descriptor */
|
/* dfu functional descriptor */
|
||||||
|
/* not all DFU implementations provides a descriptor per altsettings
|
||||||
|
* so don't stop directly.
|
||||||
|
*/
|
||||||
if (parseDFUDescriptor(intf, reinterpret_cast<uint8_t *>(&my_dev.dfu_desc),
|
if (parseDFUDescriptor(intf, reinterpret_cast<uint8_t *>(&my_dev.dfu_desc),
|
||||||
sizeof(my_dev.dfu_desc)) != 0)
|
sizeof(my_dev.dfu_desc))) {
|
||||||
continue; // not compatible
|
dfu_desc = &my_dev.dfu_desc;
|
||||||
|
dfu_found = true;
|
||||||
|
}
|
||||||
|
/* this altsetting is a DFU interface:
|
||||||
|
* - if user has selected one altsetting current is only stored if it match
|
||||||
|
* - otherwise all are stored
|
||||||
|
*/
|
||||||
|
if (_altsetting != -1 && _altsetting != intf_idx)
|
||||||
|
continue;
|
||||||
my_dev.vid = desc->idVendor;
|
my_dev.vid = desc->idVendor;
|
||||||
my_dev.pid = desc->idProduct;
|
my_dev.pid = desc->idProduct;
|
||||||
my_dev.altsettings = intf_idx;
|
my_dev.altsettings = intf_idx;
|
||||||
|
|
@ -397,9 +409,22 @@ int DFU::searchIfDFU(struct libusb_device_handle *handle,
|
||||||
|
|
||||||
int r = libusb_get_port_numbers(dev, my_dev.path, sizeof(my_dev.path));
|
int r = libusb_get_port_numbers(dev, my_dev.path, sizeof(my_dev.path));
|
||||||
my_dev.path[r] = '\0';
|
my_dev.path[r] = '\0';
|
||||||
dfu_dev.push_back(my_dev);
|
dfu_dev_tmp.push_back(my_dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* At least one altsetting has a DFU descriptor */
|
||||||
|
if (dfu_found) {
|
||||||
|
/* with tinyDFU only one (the first) altsetting contains a descriptor
|
||||||
|
* fill others with this information
|
||||||
|
*/
|
||||||
|
for (struct dfu_dev &d: dfu_dev_tmp) {
|
||||||
|
if (d.dfu_desc.bDescriptorType == 0)
|
||||||
|
memcpy(&d.dfu_desc, dfu_desc, sizeof(struct dfu_desc));
|
||||||
|
}
|
||||||
|
std::move(dfu_dev_tmp.begin(), dfu_dev_tmp.end(), std::back_inserter(dfu_dev));
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
libusb_free_config_descriptor(cfg);
|
libusb_free_config_descriptor(cfg);
|
||||||
|
|
@ -413,24 +438,29 @@ int DFU::searchIfDFU(struct libusb_device_handle *handle,
|
||||||
* Since libusb has no support for those structure
|
* Since libusb has no support for those structure
|
||||||
* fill a custom structure
|
* fill a custom structure
|
||||||
*/
|
*/
|
||||||
int DFU::parseDFUDescriptor(const struct libusb_interface_descriptor *intf,
|
bool DFU::parseDFUDescriptor(const struct libusb_interface_descriptor *intf,
|
||||||
uint8_t *dfu_desc, int dfu_desc_size)
|
uint8_t *dfu_desc, int dfu_desc_size)
|
||||||
{
|
{
|
||||||
const uint8_t *extra = intf->extra;
|
const uint8_t *extra = intf->extra;
|
||||||
int extra_len = intf->extra_length;
|
int extra_len = intf->extra_length;
|
||||||
|
|
||||||
|
/* not all altsettings for a DFU device have a DFU descriptor
|
||||||
|
* set to 0 to be able to detect a missing descriptor
|
||||||
|
*/
|
||||||
|
memset(dfu_desc, 0, 9);
|
||||||
|
|
||||||
if (extra_len < 9)
|
if (extra_len < 9)
|
||||||
return -1;
|
return false;
|
||||||
|
|
||||||
/* map memory to structure */
|
/* map memory to structure */
|
||||||
for (int j = 0; j + 1 < extra_len; j++) {
|
for (int j = 0; j + 1 < extra_len; j++) {
|
||||||
if (extra[j+1] == 0x21) {
|
if (extra[j+1] == 0x21) {
|
||||||
memcpy(dfu_desc, (const void *)&extra[j], dfu_desc_size);
|
memcpy(dfu_desc, (const void *)&extra[j], dfu_desc_size);
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* abstraction to send/receive to control */
|
/* abstraction to send/receive to control */
|
||||||
|
|
|
||||||
|
|
@ -206,9 +206,9 @@ class DFU {
|
||||||
* \param[in] intf: interface descriptor with extra area
|
* \param[in] intf: interface descriptor with extra area
|
||||||
* \param[out] dfu_desc: DFU descriptor
|
* \param[out] dfu_desc: DFU descriptor
|
||||||
* \param[in] dfu_desc_size: DFU descriptor structure size
|
* \param[in] dfu_desc_size: DFU descriptor structure size
|
||||||
* \return -1 if extra len is too small, 0 otherwise
|
* \return false if extra len is too small, true otherwise
|
||||||
* */
|
* */
|
||||||
int parseDFUDescriptor(const struct libusb_interface_descriptor *intf,
|
bool parseDFUDescriptor(const struct libusb_interface_descriptor *intf,
|
||||||
uint8_t *dfu_desc, int dfu_desc_size);
|
uint8_t *dfu_desc, int dfu_desc_size);
|
||||||
/*!
|
/*!
|
||||||
* \brief try to open device specified by vid and pid. If found
|
* \brief try to open device specified by vid and pid. If found
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue