diff --git a/tools/rootcanal/Android.bp b/tools/rootcanal/Android.bp
index 67dd3afa78a4aeab923662aef16fffc6bca21cc4..d1dade64603fdc1d46de82bde7b34bef422d05fe 100644
--- a/tools/rootcanal/Android.bp
+++ b/tools/rootcanal/Android.bp
@@ -448,6 +448,13 @@ genrule {
     ],
 }
 
+genrule {
+    name: "rootcanal_link_layer_packets_rust_gen",
+    defaults: ["pdl_rust_generator_defaults"],
+    srcs: ["packets/link_layer_packets.pdl"],
+    out: ["link_layer_packets.rs"],
+}
+
 genrule {
     name: "rootcanal_bredr_bb_packets_cxx_gen",
     tools: [
diff --git a/tools/rootcanal/CMakeLists.txt b/tools/rootcanal/CMakeLists.txt
index 53aec54b739b0239e5996293bc755b2fae05fd67..f263a48cad1cd836c943567457f916b42c08b16e 100644
--- a/tools/rootcanal/CMakeLists.txt
+++ b/tools/rootcanal/CMakeLists.txt
@@ -51,7 +51,7 @@ function(pdl_gen)
   get_filename_component(pdl_INPUT_ABSOLUTE ${pdl_INPUT} ABSOLUTE)
   get_filename_component(pdl_OUTPUT_ABSOLUTE ${pdl_OUTPUT} ABSOLUTE)
   get_filename_component(pdl_OUTPUT_DIR ${pdl_OUTPUT_ABSOLUTE} DIRECTORY)
-  set(${pdl_NAME} "${pdl_OUTPUT_ABSOLUTE}" PARENT_SCOPE)
+  set(${pdl_NAME} "${pdl_OUTPUT_ABSOLUTE}" CACHE STRING "PDL output filepath for ${pdl_NAME}" FORCE)
 
   file(MAKE_DIRECTORY ${pdl_OUTPUT_DIR})
 
@@ -105,6 +105,8 @@ function(pdl_gen)
         VERBATIM
         DEPENDS pdlc ${pdl_OUTPUT_ABSOLUTE}.json)
   endif()
+
+  add_custom_target("pdl_gen-${pdl_NAME}" DEPENDS ${pdl_OUTPUT_ABSOLUTE})
 endfunction()
 
 pdl_gen(
@@ -124,6 +126,12 @@ pdl_gen(
   INCLUDE "hci/address.h"
   USING "bluetooth::hci")
 
+pdl_gen(
+  NAME RootCanalGeneratedPackets_rs
+  INPUT ${ROOTCANAL_ROOT}/packets/link_layer_packets.pdl
+  OUTPUT link_layer_packets.rs
+  LANG rust)
+
 android_add_library(
   TARGET libscriptedbeaconpayload-protos-lite LICENSE Apache-2.0
   SOURCE_DIR ${ROOTCANAL_ROOT} SRC ${libscriptedbeaconpayload_protos_lite_src})