Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Identify L515 USB2 DFU mode #7437

Merged
Merged
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
4 changes: 2 additions & 2 deletions src/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,8 @@ namespace librealsense
std::copy(begin(tm2_devices), end(tm2_devices), std::back_inserter(list));
}
#endif

if (mask & RS2_PRODUCT_LINE_D400 || mask & RS2_PRODUCT_LINE_SR300)//supported recovery devices
// Supported recovery devices
if (mask & RS2_PRODUCT_LINE_D400 || mask & RS2_PRODUCT_LINE_SR300 || mask & RS2_PRODUCT_LINE_L500)
{
auto recovery_devices = fw_update_info::pick_recovery_devices(ctx, devices.usb_devices, mask);
std::copy(begin(recovery_devices), end(recovery_devices), std::back_inserter(list));
Expand Down
5 changes: 3 additions & 2 deletions src/fw-update/fw-update-device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ namespace librealsense

std::string lock_status = _is_dfu_locked ? "device is locked" : "device is unlocked";
LOG_INFO("This device is in DFU mode, previously-installed firmware: " << _last_fw_version <<
", the highest firmware ever installed: " << _highest_fw_version <<
", DFU status: " << lock_status);
", the highest firmware ever installed: " << _highest_fw_version);

LOG_INFO("DFU status: " << lock_status << " , DFU version is: " << payload.dfu_version);
}

bool update_device::wait_for_state(std::shared_ptr<platform::usb_messenger> messenger, const rs2_dfu_state state, size_t timeout) const
Expand Down
103 changes: 96 additions & 7 deletions src/fw-update/fw-update-factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,111 @@
#include "l500/l500-private.h"
#include "l500/l500-fw-update-device.h"

#define FW_UPDATE_INTERFACE_NUMBER 0
#define DEFAULT_TIMEOUT 100

namespace librealsense
{
int get_product_line(uint16_t pid, platform::usb_class cls)
bool is_l500_recovery(platform::rs_usb_device usb, bool &is_l500_device)
{
dfu_fw_status_payload payload;

auto messenger = usb->open(FW_UPDATE_INTERFACE_NUMBER);
if (!messenger)
{
LOG_ERROR("Unable to open USB device: " << usb->get_info().id);
return false;
}

// Step 1 - Detach device - mandatory before communicating with the DFU
{
auto timeout = 1000;
uint32_t transferred = 0;
auto res = messenger->control_transfer(0x21, RS2_DFU_DETACH, timeout, 0, NULL, 0, transferred, timeout);
if (res != platform::RS2_USB_STATUS_SUCCESS)
LOG_WARNING("DFU - failed to detach device: " << platform::usb_status_to_string.at(res));
}

// Step 2 - Verify device entered DFU idle state and ready to communicate with the host
{
uint8_t state = RS2_DFU_STATE_DFU_ERROR;
uint32_t transferred = 0;
auto res = messenger->control_transfer(0xa1, RS2_DFU_GET_STATE, 0, 0, &state, 1, transferred, DEFAULT_TIMEOUT);
if (res != platform::RS2_USB_STATUS_SUCCESS)
{
LOG_ERROR("Failed to get DFU device state! status is : " << platform::usb_status_to_string.at(res) << ", device ID is : " << usb->get_info().id);
return false;
}

if (state != RS2_DFU_STATE_DFU_IDLE)
{
LOG_ERROR("DFU is not on detach state! state is : " << state << ", device ID is : " << usb->get_info().id);
return false;
}
}
// Step 3 - Query DFU information
{
uint32_t transferred = 0;
auto sts = messenger->control_transfer(0xa1, RS2_DFU_UPLOAD, 0, 0, reinterpret_cast<uint8_t*>(&payload), sizeof(payload), transferred, DEFAULT_TIMEOUT);
if (sts != platform::RS2_USB_STATUS_SUCCESS)
{
LOG_ERROR("Failed to read info from DFU device! , status is :" << platform::usb_status_to_string.at(sts));
return false;
}
}

is_l500_device = ((payload.dfu_version & l500_update_device::DFU_VERSION_MASK) == l500_update_device::DFU_VERSION_VALUE);
return true;
}

int get_product_line(const platform::usb_device_info &usb_info)
{
if (SR300_RECOVERY == pid && platform::RS2_USB_CLASS_VENDOR_SPECIFIC == cls)
if( SR300_RECOVERY == usb_info.pid && platform::RS2_USB_CLASS_VENDOR_SPECIFIC == usb_info.cls )
return RS2_PRODUCT_LINE_SR300;
if(ds::RS_RECOVERY_PID == pid || ds::RS_USB2_RECOVERY_PID == pid)
if( ds::RS_RECOVERY_PID == usb_info.pid )
return RS2_PRODUCT_LINE_D400;
if (L500_RECOVERY_PID == pid)
if( L500_RECOVERY_PID == usb_info.pid )
return RS2_PRODUCT_LINE_L500;
if( ds::RS_USB2_RECOVERY_PID == usb_info.pid || L500_USB2_RECOVERY_PID_OLD == usb_info.pid )
{
bool is_l500 = false;
{
auto usb = platform::usb_enumerator::create_usb_device(usb_info);
if (usb)
{
// This function is a SW patch that overcome a problem found on FW of old L515 devices.
// The L515 units declare DS-5 PID while on DFU and connected as USB2
// Using the DFU version we identify L515 VS DS-5 devices.
// This issue is fixed on newer unit
if (!is_l500_recovery(usb, is_l500))
return 0;
}
}

if (is_l500)
return RS2_PRODUCT_LINE_L500;
else
return RS2_PRODUCT_LINE_D400;
}
Nir-Az marked this conversation as resolved.
Show resolved Hide resolved
return 0;
}


std::vector<std::shared_ptr<device_info>> fw_update_info::pick_recovery_devices(
std::shared_ptr<context> ctx,
const std::vector<platform::usb_device_info>& usb_devices, int mask)
{
std::vector<std::shared_ptr<device_info>> list;
for (auto&& usb : usb_devices)
{
auto pl = get_product_line(usb.pid, usb.cls);
auto pl = get_product_line(usb);
if(pl & mask)
list.push_back(std::make_shared<fw_update_info>(ctx, usb));
}
return list;
}


std::shared_ptr<device_interface> fw_update_info::create(std::shared_ptr<context> ctx, bool register_device_notifications) const
{
auto devices = platform::usb_enumerator::query_devices_info();
Expand All @@ -48,12 +126,23 @@ namespace librealsense
auto usb = platform::usb_enumerator::create_usb_device(info);
if (!usb)
continue;
if (ds::RS_RECOVERY_PID == info.pid || ds::RS_USB2_RECOVERY_PID == info.pid)
return std::make_shared<ds_update_device>(ctx, register_device_notifications, usb);
if (ds::RS_RECOVERY_PID == info.pid)
return std::make_shared<ds_update_device>(ctx, register_device_notifications, usb);
if (SR300_RECOVERY == info.pid)
return std::make_shared<sr300_update_device>(ctx, register_device_notifications, usb);
if (L500_RECOVERY_PID == info.pid)
return std::make_shared<l500_update_device>(ctx, register_device_notifications, usb);
if (ds::RS_USB2_RECOVERY_PID == info.pid || L500_USB2_RECOVERY_PID_OLD == info.pid)
{
bool dev_is_l500 = false;
if (is_l500_recovery(usb, dev_is_l500))
{
if (dev_is_l500)
return std::make_shared<l500_update_device>(ctx, register_device_notifications, usb);
else
return std::make_shared<ds_update_device>(ctx, register_device_notifications, usb);
}
}
}
}
throw std::runtime_error(to_string() << "Failed to create FW update device, device id: " << _dfu.id);
Expand Down
5 changes: 4 additions & 1 deletion src/l500/l500-fw-update-device.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// License: Apache 2.0. See LICENSE file in root directory.
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2019 Intel Corporation. All Rights Reserved.

#pragma once
Expand All @@ -10,6 +10,9 @@ namespace librealsense
class l500_update_device : public update_device
{
public:
static const uint16_t DFU_VERSION_MASK = 0xFE;
static const uint16_t DFU_VERSION_VALUE = 0x4A; // On Units with old DFU payload can be 74/75 decimal

// The L515 device EEPROM has different bytes order then D4xx device.
// this struct overrides the generic serial_number_data struct at fw-update-device.h
struct serial_number_data
Expand Down
18 changes: 10 additions & 8 deletions src/l500/l500-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ static const int MAX_NUM_OF_DEPTH_RESOLUTIONS = 5;

namespace librealsense
{
const uint16_t L500_RECOVERY_PID = 0x0b55;
const uint16_t L500_PID = 0x0b0d;
const uint16_t L515_PID_PRE_PRQ = 0x0b3d;
const uint16_t L515_PID = 0x0b64;
const uint16_t L500_RECOVERY_PID = 0x0b55;
const uint16_t L500_USB2_RECOVERY_PID_OLD = 0x0adc; // Units with old DFU_PAYLAOD on USB2 report ds5 PID (RS_USB2_RECOVERY_PID)
const uint16_t L500_PID = 0x0b0d;
const uint16_t L515_PID_PRE_PRQ = 0x0b3d;
const uint16_t L515_PID = 0x0b64;

class l500_device;

Expand Down Expand Up @@ -232,10 +233,11 @@ namespace librealsense
};

static const std::map<std::uint16_t, std::string> rs500_sku_names = {
{ L500_RECOVERY_PID, "Intel RealSense L5xx Recovery"},
{ L500_PID, "Intel RealSense L500"},
{ L515_PID_PRE_PRQ, "Intel RealSense L515 (pre-PRQ)"},
{ L515_PID, "Intel RealSense L515"},
{ L500_RECOVERY_PID, "Intel RealSense L5xx Recovery"},
{ L500_USB2_RECOVERY_PID_OLD, "Intel RealSense L5xx Recovery"},
{ L500_PID, "Intel RealSense L500"},
{ L515_PID_PRE_PRQ, "Intel RealSense L515 (pre-PRQ)"},
{ L515_PID, "Intel RealSense L515"},
};

enum l500_notifications_types
Expand Down