Skip to content

Commit

Permalink
PR #7437 from Nir: Identify L515 USB2 DFU mode
Browse files Browse the repository at this point in the history
  • Loading branch information
maloel authored Oct 12, 2020
2 parents ed1c1ef + 888b17a commit 7d95aba
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 20 deletions.
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;
}
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 @@ -244,10 +245,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

0 comments on commit 7d95aba

Please sign in to comment.