#!/bin/bash
frontend_device="rp1-cfe-csi2_ch0"


map_mediabus_to_fourcc() {
    local mediabus_code=$1
    local mediabusfmt=""
    case $mediabus_code in
        "0x3001")
            mediabusfmt="BA81" #MEDIA_BUS_FMT_SBGGR8_1X8
            ;;
        "0x3002")
            mediabusfmt="GRBG" #MEDIA_BUS_FMT_SGRBG8_1X8
            ;;
        "0x3013")
            mediabusfmt="GBRG" #MEDIA_BUS_FMT_SGBRG8_1X8
            ;;
        "0x3014")
            mediabusfmt="RGGB" #MEDIA_BUS_FMT_SRGGB8_1X8
            ;;
        "0x2001")
            mediabusfmt="GREY" #MEDIA_BUS_FMT_Y8_1X8
            ;;
        "0x300e")
            mediabusfmt="pGAA" #MEDIA_BUS_FMT_SGBRG10_1X10
            ;;
        "0x300f")
            mediabusfmt="pRAA" #MEDIA_BUS_FMT_SRGGB10_1X10
            ;;
        "0x200a")
            mediabusfmt="Y10P" #MEDIA_BUS_FMT_Y10_1X10 On the raspi Y10  is not used, but Y10P
            ;;
        "0x300a")
            mediabusfmt="pgAA" #MEDIA_BUS_FMT_SGRBG10_1X10
            ;;
        "0x3007") 
            mediabusfmt="pBAA" #MEDIA_BUS_FMT_SBGGR10_1X10
            ;;
        "0x3008")
            mediabusfmt="pBCC" #MEDIA_BUS_FMT_SBGGR12_1X12
            ;;
        "0x3010")
            mediabusfmt="pGCC" #MEDIA_BUS_FMT_SGBRG12_1X12 
            ;;
        "0x3011")
            mediabusfmt="pgCC" #MEDIA_BUS_FMT_SGRBG12_1X12
            ;;
        "0x3012")
            mediabusfmt="pRCC" #MEDIA_BUS_FMT_SRGGB12_1X12
            ;;
        "0x2013")
            mediabusfmt="Y12P" #MEDIA_BUS_FMT_Y12_1X12
            ;;       
        "0x3019")
            mediabusfmt="pBEE" #MEDIA_BUS_FMT_SBGGR14_1X14
            ;;
        "0x301a")
            mediabusfmt="pGEE" #MEDIA_BUS_FMT_SGBRG14_1X14
            ;;
        "0x301b")
            mediabusfmt="pgEE" #MEDIA_BUS_FMT_SGRBG14_1X14
            ;;
        "0x301c")
            mediabusfmt="pREE" #MEDIA_BUS_FMT_SRGGB14_1X14
            ;;
        "0x202d")
            mediabusfmt="Y14P" #MEDIA_BUS_FMT_Y14_1X14
            ;;	
        "0x301d")
            mediabusfmt="BYR2" #MEDIA_BUS_FMT_SBGGR16_1X16
            ;;
        "0x301e")
            mediabusfmt="GB16" #MEDIA_BUS_FMT_SGBRG16_1X16
            ;;
        "0x301f")
            mediabusfmt="GR16" #MEDIA_BUS_FMT_SGRBG16_1X16
            ;;
        "0x3020")
            mediabusfmt="RG16" #MEDIA_BUS_FMT_SRGGB16_1X16
            ;;
        "0x202e")
            mediabusfmt="Y16 " #MEDIA_BUS_FMT_Y16_1X16
            ;;       
       
        
        *)
            echo "Unknown mediabus code: $mediabus_code"
            exit 1
            ;;
    esac
    echo "$mediabusfmt"

}


map_mediabus_to_related_unpacked_fourcc() {
    local mediabus_code=$1
    local mediabusfmt=""
    case $mediabus_code in
        "0x300e")
            mediabusfmt="GB16" #MEDIA_BUS_FMT_SGBRG10_1X10
            ;;
        "0x300f")
            mediabusfmt="RG16" #MEDIA_BUS_FMT_SRGGB10_1X10
            ;;
        "0x200a")
            mediabusfmt="Y16 " #MEDIA_BUS_FMT_Y10_1X10 
            ;;
        "0x300a")
            mediabusfmt="GR16" #MEDIA_BUS_FMT_SGRBG10_1X10
            ;;
        "0x3007") 
            mediabusfmt="BG16" #MEDIA_BUS_FMT_SBGGR10_1X10
            ;;
        "0x3008")
            mediabusfmt="BG16" #MEDIA_BUS_FMT_SBGGR12_1X12
            ;;
        "0x3010")
            mediabusfmt="GB16" #MEDIA_BUS_FMT_SGBRG12_1X12 
            ;;
        "0x3011")
            mediabusfmt="GR16" #MEDIA_BUS_FMT_SGRBG12_1X12
            ;;
        "0x3012")
            mediabusfmt="RG16" #MEDIA_BUS_FMT_SRGGB12_1X12
            ;;
        "0x2013")
            mediabusfmt="Y16 " #MEDIA_BUS_FMT_Y12_1X12
            ;;       
        "0x3019")
            mediabusfmt="BG16" #MEDIA_BUS_FMT_SBGGR14_1X14
            ;;
        "0x301a")
            mediabusfmt="GB16" #MEDIA_BUS_FMT_SGBRG14_1X14
            ;;
        "0x301b")
            mediabusfmt="GR16" #MEDIA_BUS_FMT_SGRBG14_1X14
            ;;
        "0x301c")
            mediabusfmt="RG16" #MEDIA_BUS_FMT_SRGGB14_1X14
            ;;
        "0x202d")
            mediabusfmt="Y16 " #MEDIA_BUS_FMT_Y14_1X14
            ;;	
        "0x2001")
            mediabusfmt="Y16 " #MEDIA_BUS_FMT_Y8_1X8
            ;;
       
        
        *)
            echo "Unknown mediabus code: $mediabus_code"
            exit 1
            ;;
    esac
    echo "$mediabusfmt"

}
get_mediabus_code() {
    local subdev=$1

    # Use v4l2-ctl to get the format of the subdevice and extract the mediabus code
    v4l2-ctl --device=$subdev --get-subdev-fmt pad=0 | grep "Mediabus Code" | awk '{print $4}'
}
get_mediabus_code_string() {
    local subdev=$1
    v4l2-ctl -d "$subdev" --get-subdev-fmt pad=0 2>/dev/null \
      | grep -E 'MEDIA_BUS_FMT_' \
      | awk -F': ' '{print $2}' \
      | awk '{print $2}' \
      | sed 's/^MEDIA_BUS_FMT_//' \
      | grep -v '^_' \
      | awk -F'_' '{print $4}' 
}

get_pixelformat_fourcc() {
    local videodev=$1

    v4l2-ctl --device=$videodev --get-fmt-video | grep "Pixel Format" | awk -F "'" '{print $2}'

}

# Function to get stored configuration for a device
get_stored_config_for_dev() {
    local subdev=$1
    local mediadev=$2

    # Find the entity name that owns this subdev (two first tokens of entity line)
    local entity_name
    entity_name=$(media-ctl -d "$mediadev" -p | grep -B 3 "$subdev" | grep entity | awk -F ': ' '{ print $2 }' | awk -F ' ' '{ print $1, $2 }')
    local sanitized
    sanitized=$(tr -cs 'a-zA-Z0-9._-' '_' <<<"$entity_name")

    local cfg_dev="/etc/vc-mipi/formats.d/${sanitized}.conf"
    if [ -f "$cfg_dev" ]; then
        # shellcheck disable=SC1090
        . "$cfg_dev"
        printf "Subdev FourCC: '%s'\n" "$preferred_pixelformat_subdev"
        printf "VideoDev FourCC: '%s'\n" "$preferred_pixelformat_videodev"
        return 0
    fi

    echo "No stored configuration found"
    return 1
}
# Find all media devices and check for video0
# Extract the hardware information from /proc/cpuinfo
revision_info=$(grep -m 1 'Revision' /proc/cpuinfo | awk '{print $3}')
model_info=$(grep -m 1 'Model' /proc/cpuinfo | awk -F ': ' '{print $2}')

# Convert the revision code to binary and extract the PPPP part (bits 23 to 20)
revision_bin=$(printf "%032b\n" $((16#$revision_info)))
pppp=$(( ($revision_bin >> 12) & 0xf ))
# Convert the binary PPPP part back to hexadecimal
pppp_hex=$(echo "obase=16; ibase=2; $pppp" | bc)
ttt_hex=$(printf "%X\n" $(( ($revision_bin >> 4) & 0xFF )))

case $pppp_hex in
0) soc="BCM2835";;
1) soc="BCM2836";;
2) soc="BCM2837";;
3) soc="BCM2711";;
4) soc="BCM2712";;
*) soc="Unknown";;
esac

# Display the hardware information
printf -- "----- Hardware Information -----\n"
printf "%-10s %s\n" "Revision:" "$revision_info"
printf "%-10s %s\n" "Model:" "$model_info"
printf "%-10s %s\n" "SoC:" "$soc"
printf -- "---------------------------------\n"
configure_device_tree() {
    local change=false
        # Use whiptail to create a menu for selecting the camera
    while true; do
        camera=$(whiptail --menu "Select the camera:" 15 80 2 --cancel-button "Save and exit"\
        "cam0" "MIPI CSI Connector 0" \
        "cam1" "MIPI CSI Connector 1" 3>&1 1>&2 2>&3)
        if [ $? -ne 0 ]; then
            break       
        fi 

        config_file="/boot/firmware/config_vc-mipi-driver-bcm2712.txt"

        current_lanes=$(grep "^dtparam="$camera"_lanes" "$config_file" | awk -F 'lanes' '{print $2}')
        current_manu=$(grep "^dtparam="$camera"_manu_" "$config_file" | awk -F '_manu_' '{print $2}')
        current_libcamera=$(grep "^dtparam="$camera"_libcamera_" "$config_file" | awk -F '_libcamera_' '{print $2}')

        # Use whiptail to create a menu for selecting the number of lanes
        lanes=$(whiptail --menu "Select the number of lanes:" 15 200 3 --default-item "$current_lanes" --cancel-button "Cancel"\
        "1" "1 lane (i.e. OV7251, IMX296, IMX297)" \
        "2" "2 lanes (i.e.  OV9281, IMX264, IMX265, IMX178, IMX183, IMX226, IMX250, IMX252, IMX273, IMX290, IMX327, IMX335, IMX392)" \
        "4" "4 lanes (i.e. IMX178, IMX183, IMX226, IMX250, IMX252, IMX273, IMX290,  IMX327, IMX335, IMX392, IMX412, IMX415, IMX462, IMX565, IMX566, IMX567, IMX568, IMX900)" 3>&1 1>&2 2>&3)
        if [ $? -ne 0 ]; then
            break
        fi 
        if [ "$lanes" != "$current_lanes" ]; then
            change=true
            sudo sed -i "s/^dtparam=${camera}_lanes[0-9]*/dtparam=${camera}_lanes${lanes}/" "$config_file"
        fi
        manufacturer=$(whiptail --menu "Manufacturer:" 15 200 3  --default-item "$current_manu" \
        "sony" "SONY IMX" \
        "ov" "OMNIVISION" \
        "os" "ONSEMI" \
        3>&1 1>&2 2>&3)
        if [ $? -ne 0 ]; then
            break
        fi 
        if [ "$manufacturer" != "$current_manu" ]; then
            change=true
                sudo sed -i "s/^dtparam=${camera}_manu_.*/dtparam=${camera}_manu_${manufacturer}/" "$config_file"
        fi
        libcamera=$(whiptail --menu "Libcamera support:" 15 200 2  --default-item "$current_libcamera" \
        "on" "Libcamera support on" \
        "off" "Libcamera support off" \
        3>&1 1>&2 2>&3)
        if [ $? -ne 0 ]; then
            break
        fi 
        if [ "$libcamera" != "$current_libcamera" ]; then
            change=true
                sudo sed -i "s/^dtparam=${camera}_libcamera_.*/dtparam=${camera}_libcamera_${libcamera}/" "$config_file"
        fi
    done;
    if [ "$change" = true ]; then   
        whiptail --msgbox "Please reboot system" 8 40 --title "Success" 3>&1 1>&2 2>&3
        sleep 2
    fi
}
get_format_entity()
{
    local subdev=$1
    local entity_name=$(media-ctl -d "$mediadev" -p | grep -B 3 "$subdev" | grep entity | awk -F ': ' '{ print $2 }' | awk -F ' ' '{ print $1, $2 }')

    format=$(media-ctl -d "$mediadev" -p \
        | grep -A 2 "$subdev" \
        | grep fmt: \
        | awk -F 'fmt:' '{ print $2 }' \
        | awk '{ print $1 }')

    echo "$format"
}
get_mediadevice() {
    local subdev=$1
    subdev=${subdev#/dev/}
    for mediadev in /dev/media*; do
        if media-ctl -d "$mediadev" -p | grep -q "$subdev"; then
            echo "$mediadev"
            return
        fi
    done
    exit 1
    
}
get_cropping() {
    local subdev=$1
    local mediadev
    mediadev=$(get_mediadevice "$subdev")
    local entity_name=$(media-ctl -d "$mediadev" -p | grep -B 3 "$subdev" | grep entity | awk -F ': ' '{ print $2 }' | awk -F ' ' '{ print $1, $2 }')
    local cropping_line=$(media-ctl -d "$mediadev" -p | grep -A 6 "$entity_name" | grep crop: | awk -F ':' '{ print $2 }' | awk -F ' ' '{print $1}')
    local left=$(echo "$cropping_line" | awk -F '[(),]' '{print $2}')
    local top=$(echo "$cropping_line" | awk -F '[(),]' '{print $3}')
    local width=$(echo "$cropping_line" | awk -F '[x/]' '{print $2}')
    local height=$(echo "$cropping_line" | awk -F '[x/]' '{print $3}' | awk '{print $1}')
    echo "Cropping values: left=$left, top=$top, width=$width, height=$height" >&2
    echo "$left $top $width $height"
}

configure_video_device() {

    local subdev=$1
    local videodev=$2

        
    for mediadev in /dev/media*; do
        
        # Skip if not a valid media device
        if ! [ -e "$mediadev" ]; then
            continue
        fi
        
        # Get media device number
        media_num=$(echo "$mediadev" | grep -o '[0-9]*$')
        
        # Check if this media device has video0
        if media-ctl -d "$mediadev" -p | grep -q "$videodev"; then
            echo "Found $videodev on $mediadev"
            
            # Your existing script logic here
        
            media-ctl -d "$mediadev" -r

            mediabus_code=$(get_mediabus_code $subdev )

            # Print the mediabus code
            fmt=$(map_mediabus_to_fourcc $mediabus_code)

            resolution=$(v4l2-ctl -d $subdev --get-subdev-fmt | grep Width | awk -F ' ' '{ print $3 }' | tr '/' 'x' | xargs echo -n)
            width=$(echo $resolution | awk -F 'x' '{ print $1 }')
            height=$(echo $resolution | awk -F 'x' '{ print $2 }')
            mediabusfmt=$(v4l2-ctl -d $subdev --get-subdev-fmt | grep Mediabus | awk -F ' ' '{ print $5 }' | tr -d '()' | cut -c 15- | xargs echo -n)
            format="$mediabusfmt/$resolution"

            media-ctl -d "$mediadev" -V ''\''csi2'\'':4 [fmt:'"$format"' field:none colorspace:srgb]' 
            media-ctl -d "$mediadev" -V ''\''csi2'\'':0 [fmt:'"$format"' field:none colorspace:srgb]' 
            media-ctl -d "$mediadev" -l ''\''csi2'\'':4 -> '\''rp1-cfe-csi2_ch0'\'':0 [1]' 
            v4l2-ctl -d "$videodev" --set-fmt-video=width=$width,height=$height,pixelformat="$fmt",colorspace=srgb 
            if ! timeout 5 v4l2-ctl --verbose --stream-mmap --device=$videodev --stream-count=3; then
                echo "No image recorded for $videodev" | sudo tee /dev/kmsg
            fi
            
                                   
           
            return
        fi
    done
}
set_roi() {

    local subdev=$1
    local videodev=$2
    local width=$3
    local height=$4

    if [ $subdev = "" ]; then
        echo "No subdevice specified"
        return
    fi
    if [ $videodev = "" ]; then
        echo "No video device specified"
        return
    fi

        
    for mediadev in /dev/media*; do
        
        # Skip if not a valid media device
        if ! [ -e "$mediadev" ]; then
            continue
        fi
        
        # Get media device number
        media_num=$(echo "$mediadev" | grep -o '[0-9]*$')
        
        # Check if this media device has video0
        if media-ctl -d "$mediadev" -p | grep -q "$videodev"; then
            echo "Found $videodev on $mediadev"
            
        
            media-ctl -d "$mediadev" 

            mediabus_code=$(get_mediabus_code $subdev )

            fmt=$(map_mediabus_to_fourcc $mediabus_code)

            resolution=$(v4l2-ctl -d $subdev --get-subdev-fmt | grep Width | awk -F ' ' '{ print $3 }' | tr '/' 'x' | xargs echo -n)
          
            mediabusfmt=$(v4l2-ctl -d $subdev --get-subdev-fmt | grep Mediabus | awk -F ' ' '{ print $5 }' | tr -d '()' | cut -c 15- | xargs echo -n)
            format="$mediabusfmt/$resolution"
            entity_name=$(media-ctl -d "$mediadev" -p | grep -B 3 "$subdev" | grep entity | awk -F ': ' '{ print $2 }' | awk -F ' ' '{ print $1, $2 }')
            media-ctl -d "$mediadev" -l ''\''csi2'\'':4 -> '\''rp1-cfe-csi2_ch0'\'':0 [1]' 
            
            media-ctl -d $mediadev -V "'$entity_name':0 [fmt:$mediabusfmt/${width}x${height} field:none colorspace:srgb]" 
            v4l2-ctl -d "$videodev" --set-fmt-video=width=$width,height=$height,pixelformat="$fmt",colorspace=srgb 

            if v4l2-ctl --verbose  --stream-mmap --device=$videodev --stream-count=3;then
                whiptail --infobox "Successfully set ROI to $width x $height" 8 40 --title "Success"
                sleep 1
            else
                whiptail --infobox "Failed to set ROI to $width x $height" 8 40 --ok-button "OK" --title "Error"
                sleep 1
            fi
            return
        fi
    done
}
set_cropping()
{
    local subdev=$1
    local videodev=$2
    local width=$3
    local height=$4
    local left=$5
    local top=$6

    if [ $subdev = "" ]; then
        echo "No subdevice specified"
        return
    fi
    if [ $videodev = "" ]; then
        echo "No video device specified"
        return
    fi

        
     for mediadev in /dev/media*; do
        
        # Skip if not a valid media device
        if ! [ -e "$mediadev" ]; then
            continue
        fi
        
        media_num=$(echo "$mediadev" | grep -o '[0-9]*$')
        
        # Check if this media device has video0
        if media-ctl -d "$mediadev" -p | grep -q "$videodev"; then
            echo "Found $videodev on $mediadev"
            

            mediabus_code=$(get_mediabus_code $subdev )

            fmt=$(map_mediabus_to_fourcc $mediabus_code)

            mediabusfmt=$(v4l2-ctl -d $subdev --get-subdev-fmt | grep Mediabus | awk -F ' ' '{ print $5 }' | tr -d '()' | cut -c 15- | xargs echo -n)

            entity_name=$(media-ctl -d "$mediadev" -p | grep -B 3 "$subdev" | grep entity | awk -F ': ' '{ print $2 }' | awk -F ' ' '{ print $1, $2 }')
            media-ctl -d $mediadev --set-v4l2 "'$entity_name':0[crop:(${left},${top})/${width}x${height}]" 
            media-ctl -d $mediadev -V "'csi2':0 [fmt:$mediabusfmt/${width}x${height} field:none colorspace:srgb]" 

            v4l2-ctl -d "$videodev" --set-fmt-video=width=$width,height=$height,pixelformat="$fmt",colorspace=srgb 

            if v4l2-ctl --verbose  --stream-mmap --device=$videodev --stream-count=3;then
                whiptail --infobox "Successfully set ROI to $width x $height" 8 40 --title "Success"
                sleep 1
            else
                whiptail --infobox "Failed to set ROI to $width x $height" 8 40 --ok-button "OK" --title "Error"
                sleep 1
            fi
            return
        fi
    done

}
set_format() {

    local videodev=$1
    local mediabusfmt=$2
        
    for mediadev in /dev/media*; do
        echo "Checking $mediadev..."
        
        # Skip if not a valid media device
        if ! [ -e "$mediadev" ]; then
            continue
        fi
        
        media_num=$(echo "$mediadev" | grep -o '[0-9]*$')
        
        # Check if this media device has video0
        if media-ctl -d "$mediadev" -p | grep -q "$videodev"; then
            echo "Found $videodev on $mediadev"
            
            subdev=$(media-ctl -d "$mediadev" -p | grep "vc_mipi_camera" -A  2  | grep "device node name" | awk -F ' ' '{ print $4 }')

            media-ctl -d "$mediadev" -r          

            entity_name=$(get_entity_name $mediadev)

            resolution=$(v4l2-ctl -d $subdev --get-subdev-fmt | grep Width | awk -F ' ' '{ print $3 }' | tr '/' 'x' | xargs echo -n)
            width=$(echo $resolution | awk -F 'x' '{ print $1 }')
            height=$(echo $resolution | awk -F 'x' '{ print $2 }')
            format="$mediabusfmt/$resolution"
            
            media-ctl -d "$mediadev" -r
            media-ctl -d "$mediadev" -V ''\''vc_mipi_camera '$entity_name''\'':0 [fmt:'"$format"' field:none colorspace:srgb]'

            new_format=$(get_format_entity $subdev)
            echo "New format: '$new_format'"
            if([ "$new_format" != "$format" ]); then
                echo "Failed to set format to $mediabusfmt"
                whiptail --msgbox "Failed to set format to $mediabusfmt Format is probably not supported by sensor" 8 40 --ok-button "OK" --title "Error" 
                sleep 1
                media-ctl -d "$mediadev" -V ''\''csi2'\'':0 [fmt:'"$new_format"' field:none colorspace:srgb]' 
                media-ctl -d "$mediadev" -V ''\''csi2'\'':4 [fmt:'"$new_format"' field:none colorspace:srgb]' 
                media-ctl -d "$mediadev" -l ''\''csi2'\'':4 -> '\''rp1-cfe-csi2_ch0'\'':0 [1]' 
                return
            fi

            media-ctl -d "$mediadev" -V ''\''csi2'\'':0 [fmt:'"$format"' field:none colorspace:srgb]' 
            media-ctl -d "$mediadev" -V ''\''csi2'\'':4 [fmt:'"$format"' field:none colorspace:srgb]' 


            media-ctl -d "$mediadev" -l ''\''csi2'\'':4 -> '\''rp1-cfe-csi2_ch0'\'':0 [1]' 
            mediabus_code=$(get_mediabus_code $subdev )
            fmt=$(map_mediabus_to_fourcc $mediabus_code)

            v4l2-ctl -d "$videodev" --set-fmt-video=width=$width,height=$height,pixelformat="$fmt",colorspace=srgb 
 
            v4l2-ctl --verbose  --stream-mmap --device=$videodev --stream-count=3
            sleep 2
            
                                   
           
            return
        fi
    done
}

set_format_unpacked() {

    local videodev=$1
    local mediabusfmt=$2
        
    for mediadev in /dev/media*; do
        # Skip if not a valid media device
        if ! [ -e "$mediadev" ]; then
            continue
        fi
        
        # Get media device number
        media_num=$(echo "$mediadev" | grep -o '[0-9]*$')
        
        # Check if this media device has video0
        if media-ctl -d "$mediadev" -p | grep -q "$videodev"; then
            echo "Found $videodev on $mediadev"
            
            subdev=$(media-ctl -d "$mediadev" -p | grep "vc_mipi_camera" -A  2  | grep "device node name" | awk -F ' ' '{ print $4 }')

            media-ctl -d "$mediadev" -r


            entity_name=$(get_entity_name $mediadev)

            resolution=$(v4l2-ctl -d $subdev --get-subdev-fmt | grep Width | awk -F ' ' '{ print $3 }' | tr '/' 'x' | xargs echo -n)
            width=$(echo $resolution | awk -F 'x' '{ print $1 }')
            height=$(echo $resolution | awk -F 'x' '{ print $2 }')
            format="$mediabusfmt/$resolution"
            media-ctl -d "$mediadev" -r

            new_format=$(get_format_entity $subdev)
            
            # Determine the correct CFE format based on the mediabus format
            if [[ "$mediabusfmt" == *"Y1"* ]]; then
                cfe_fmt="Y16_1X16"
            elif [[ "$mediabusfmt" == *"SGBRG"* ]]; then
                cfe_fmt="SGBRG16_1X16"
            elif [[ "$mediabusfmt" == *"SGRBG"* ]]; then
                cfe_fmt="SGRBG16_1X16"
            elif [[ "$mediabusfmt" == *"SBGGR"* ]]; then
                cfe_fmt="SBGGR16_1X16"
            else
                cfe_fmt="SRGGB16_1X16"  # Default fallback (RGGB)
            fi

            new_format_cfe="$cfe_fmt/"$width"x"$height""
          
            echo "Setting format to $new_format_cfe"
            media-ctl -d "$mediadev" -V ''\''vc_mipi_camera '$entity_name''\'':0 [fmt:'"$format"' field:none colorspace:srgb]'
            media-ctl -d "$mediadev" -V "'csi2':0 [fmt:"$format" field:none colorspace:srgb]"

            media-ctl -d "$mediadev"  -V "'csi2':4 [fmt:"$new_format_cfe" field:none colorspace:srgb]"

            media-ctl -v  -d "$mediadev" -l "'csi2':4 -> 'rp1-cfe-csi2_ch0':0 [1]" 
            mediabus_code=$(get_mediabus_code $subdev )
            fmt=$(map_mediabus_to_related_unpacked_fourcc $mediabus_code)


            v4l2-ctl -d "$videodev" --set-fmt-video=width=$width,height=$height,pixelformat="$fmt",colorspace=srgb 

            v4l2-ctl --verbose  --stream-mmap --device=$videodev --stream-count=3
            sleep 2
            
                                   
           
            return
        fi
    done
}

dialog_set_roi() 
{
    local subdev=$1
    local videodev=$2

    resolution=$(v4l2-ctl -d $subdev --get-subdev-fmt | grep Width | awk -F ' ' '{ print $3 }' | tr '/' 'x' | xargs echo -n)
    cur_width=$(echo $resolution | awk -F 'x' '{ print $1 }')
    cur_height=$(echo $resolution | awk -F 'x' '{ print $2 }')

    width=$(whiptail --inputbox "Enter the desired width:" 8 40 $cur_width 3>&1 1>&2 2>&3)
    if [ $? -ne 0 ]; then
        return
    fi 
    height=$(whiptail --inputbox "Enter the desired height:" 8 40 $cur_height 3>&1 1>&2 2>&3)
    if [ $? -ne 0 ]; then
        return
    fi 

    echo "Selected subdevice: $subdev"
    echo "Width: $width, Height: $height, Subdevice: $subdev, Device: $videodev"
    set_roi "$subdev" "$videodev" "$width" "$height"
    
}
dialog_set_cropping()
{
    local subdev=$1
    local videodev=$2

    read cur_left cur_top cur_width cur_height <<< $(get_cropping "$subdev")


    width=$(whiptail --inputbox "Enter the desired width:" 8 40 $cur_width 3>&1 1>&2 2>&3)
    if [ $? -ne 0 ]; then
        return
    fi 
    height=$(whiptail --inputbox "Enter the desired height:" 8 40 $cur_height 3>&1 1>&2 2>&3)
    if [ $? -ne 0 ]; then
        return
    fi 
    left=$(whiptail --inputbox "Enter the left offset:" 8 40 $cur_left 3>&1 1>&2 2>&3)
    if [ $? -ne 0 ]; then
        return
    fi
    top=$(whiptail --inputbox "Enter the top offset:" 8 40 $cur_top 3>&1 1>&2 2>&3)

    echo "Selected subdevice: $subdev"
    echo "Width: $width, Height: $height, Subdevice: $subdev, Device: $videodev"
    set_cropping "$subdev" "$videodev" "$width" "$height" "$left" "$top"
}
dialog_set_debuglevel()
{


    currentlevel=$(cat "/sys/module/vc_mipi_core/parameters/debug")

    echo "Current debug level: $currentlevel"

    debuglevel=$(whiptail --menu "At least Logging level:" 15 200 6  --default-item "$currentlevel" \
     "1" "Errors" \
     "2" "Warnings" \
     "3" "Notices" \
     "4" "Infos" \
     "5" "Debug" \
     "6" "Registers" \
        3>&1 1>&2 2>&3)
    if [ $? -ne 0 ]; then
        break
    fi 
    echo "Selected subdevice: $subdev"
    echo "Debug level: $debuglevel"
    echo $debuglevel | sudo tee /sys/module/vc_mipi_core/parameters/debug
}
dialog_set_format() 
{
       local videodev=$1

    declare -A format_map
    format_map=(
        ["Y8 "]="Y8_1X8"      
        ["BGGR8"]="SBGGR8_1X8"
        ["GRBG8"]="SGRBG8_1X8"
        ["GBRG8"]="SGBRG8_1X8"
        ["RGGB8"]="SRGGB8_1X8"
        ["Y10 "]="Y10_1X10"
        ["Y10P"]="Y10_1X10"
        ["GRBG10"]="SGRBG10_1X10"
        ["BGGR10"]="SBGGR10_1X10"
        ["GBRG10"]="SGBRG10_1X10"
        ["RGGB10"]="SRGGB10_1X10"
        ["BGGR10P"]="SBGGR10_1X10"
        ["GBRG10P"]="SGBRG10_1X10"
        ["GRBG10P"]="SGRBG10_1X10"
        ["RGGB10P"]="SRGGB10_1X10"
        ["Y12 "]="Y12_1X12"
        ["Y12P"]="Y12_1X12"
        ["BGGR12"]="SBGGR12_1X12"
        ["GBRG12"]="SGBRG12_1X12"
        ["GRBG12"]="SGRBG12_1X12"
        ["RGGB12"]="SRGGB12_1X12"
        ["BGGR12P"]="SBGGR12_1X12"
        ["GBRG12P"]="SGBRG12_1X12"
        ["GRBG12P"]="SGRBG12_1X12"
        ["RGGB12P"]="SRGGB12_1X12"
        ["Y14 "]="Y14_1X14"
        ["Y14P"]="Y14_1X14"
        ["BGGR14"]="SBGGR14_1X14"
        ["GBRG14"]="SGBRG14_1X14"
        ["GRBG14"]="SGRBG14_1X14"
        ["RGGB14"]="SRGGB14_1X14"
        ["BGGR14P"]="SBGGR14_1X14"
        ["GBRG14P"]="SGBRG14_1X14"
        ["GRBG14P"]="SGRBG14_1X14"
        ["RGGB14P"]="SRGGB14_1X14"   
        ["BGGR16"]="SBGGR16_1X16"
        ["GB16"]="SGBRG16_1X16"
        ["GR16"]="SGRBG16_1X16"
        ["RG16"]="SRGGB16_1X16"
        ["Y16 "]="Y16_1X16"
    )

    menu_options_format=(
        "Y8 " "Greyscale 8-bit"
        "Y10 " "Greyscale 10-bit"
        "Y10P" "Greyscale 10-bit packed"
        "Y12 " "Greyscale 12-bit"
        "Y12P" "Greyscale 12-bit packed"
        "Y14 " "Bayer Y14 14-bit"
        "Y14P" "Greyscale 14-bit packed"
        "Y16 " "Greyscale 16-bit"
        "BGGR8" "Bayer BGGR 8-bit"
        "GRBG8" "Bayer GRBG 8-bit"
        "GBRG8" "Bayer GBRG 8-bit"
        "RGGB8" "Bayer RGGB 8-bit"
        "GBRG10" "Bayer GBRG 10-bit"
        "RGGB10" "Bayer RGGB 10-bit"
        "GRBG10" "Bayer GRBG 10-bit"
        "BGGR10" "Bayer BGGR 10-bit"
        "BGGR10P" "Bayer BGGR 10-bit packed"
        "GBRG10P" "Bayer GBRG 10-bit packed"
        "GRBG10P" "Bayer GRBG 10-bit packed"
        "RGGB10P" "Bayer RGGB 10-bit packed"
        "BGGR12" "Bayer BGGR 12-bit"
        "GBRG12" "Bayer GBRG 12-bit"
        "GRBG12" "Bayer GRBG 12-bit"
        "RGGB12" "Bayer RGGB 12-bit"
        "BGGR12P" "Bayer BGGR 12-bit packed"
        "GBRG12P" "Bayer GBRG 12-bit packed"
        "GRBG12P" "Bayer GRBG 12-bit packed"
        "RGGB12P" "Bayer RGGB 12-bit packed"
        "BGGR14" "Bayer BGGR 14-bit"
        "GBRG14" "Bayer GBRG 14-bit"
        "GRBG14" "Bayer GRBG 14-bit"
        "RGGB14" "Bayer RGGB 14-bit"
        "BGGR14P" "Bayer BGGR 14-bit packed"
        "GBRG14P" "Bayer GBRG 14-bit packed"
        "GRBG14P" "Bayer GRBG 14-bit packed"
        "RGGB14P" "Bayer RGGB 14-bit packed"   
        "BGGR16" "Bayer BGGR 16-bit"
        "GB16" "Bayer GBRG 16-bit"
        "GR16" "Bayer GRBG 16-bit"
        "RG16" "Bayer RGGB 16-bit"
        
       
      
    )

       # Build reverse map: full mediabus -> short code
    declare -A reverse_format_map
    for k in "${!format_map[@]}"; do
        if [[ ! "$k" =~ P$ ]]; then

        reverse_format_map["${format_map[$k]}"]="$k"
        fi
    done

    # Build description map from the menu options pairs
    declare -A format_desc_map
    for ((i=0; i<${#menu_options_format[@]}; i+=2)); do
        key="${menu_options_format[i]}"
        val="${menu_options_format[i+1]}"
        format_desc_map["$key"]="$val"
    done

    # Try to fetch supported MEDIA_BUS_FMT_* from subdev pad 0 and convert to short keys
    get_supported_short_codes() {
        local sd=$1
        v4l2-ctl -d "$sd" --list-subdev-mbus-codes pad=0 2>/dev/null \
          | grep -E 'MEDIA_BUS_FMT_' \
          | awk -F': ' '{print $2}' \
          | awk '{print $1}' \
          | sed 's/^MEDIA_BUS_FMT_//'
    }

    mapfile -t supported_full < <(get_supported_short_codes "$subdev")

    # After building supported_full, add packed variants for 10, 12, 14 bits
    supported_with_packed=()
    declare -A packed_map=(
        ["Y10 "]="Y10P"
        ["Y12 "]="Y12P"
        ["Y14 "]="Y14P"
        ["BGGR10"]="BGGR10P"
        ["GBRG10"]="GBRG10P"
        ["GRBG10"]="GRBG10P"
        ["RGGB10"]="RGGB10P"
        ["BGGR12"]="BGGR12P"
        ["GBRG12"]="GBRG12P"
        ["GRBG12"]="GRBG12P"
        ["RGGB12"]="RGGB12P"
        ["BGGR14"]="BGGR14P"
        ["GBRG14"]="GBRG14P"
        ["GRBG14"]="GRBG14P"
        ["RGGB14"]="RGGB14P"
    )
    declare -A already_in
    for fmt in "${supported_full[@]}"; do
        short="${reverse_format_map[$fmt]:-}"
        supported_with_packed+=("$short")

        if [[ -n "${packed_map[$short]:-}" ]] && [[ -z "${already_in[${packed_map[$short]}]:-}" ]]; then
            supported_with_packed+=("${packed_map[$short]}")
            already_in["${packed_map[$short]}"]=1
        fi

    done
    echo "Supported formats (with packed variants): ${supported_with_packed[*]}" >&2
    # Use supported_with_packed instead of supported_full below
    declare -A seen
    ordered_menu=()
    if [ ${#supported_with_packed[@]} -gt 0 ]; then
        ordered_menu+=(" " " --- Supported formats --- ")
    fi

    if [ ${#supported_with_packed[@]} -gt 0 ]; then
        for short in "${supported_with_packed[@]}"; do
            if [ -n "$short" ] && [ -z "${seen[$short]:-}" ] && [ -n "${format_desc_map[$short]:-}" ]; then
                ordered_menu+=("$short" "${format_desc_map[$short]}")
                seen[$short]=1
            fi
        done
    fi
        # Add a non-selectable spacer between supported formats and the rest
    if [ ${#supported_with_packed[@]} -gt 0 ]; then
        ordered_menu+=(" " " --- Other Formats --- ")
    fi

    # Append the rest (still avoiding duplicates)
    for ((i=0; i<${#menu_options_format[@]}; i+=2)); do
        key="${menu_options_format[i]}"
        val="${menu_options_format[i+1]}"
        if [ -z "${seen[$key]:-}" ]; then
            ordered_menu+=("$key" "$val")
            seen[$key]=1
        fi
    done


    # Use whiptail to prompt the user to select the format (supported-first ordering)
    mediabusfmt=$(whiptail --menu "Select the sensor format" 25 60 16 "${ordered_menu[@]}" 3>&1 1>&2 2>&3)

    if [ $? -ne 0 ]; then
        return
    fi
    # If spacer was selected, inform the user and rerun the selection
    if [ "$mediabusfmt" = " " ]; then
        whiptail --msgbox "Please select a concrete format from the list." 8 50 --title "Info"
        dialog_set_format "$videodev"
        return
    fi

    full_mediabusfmt=${format_map[$mediabusfmt]}
    echo "Selected format: $full_mediabusfmt"   


    if [[ -n "$mediabusfmt" && -v packed_map[$mediabusfmt] ]]; then
        echo "Selected format {$mediabusfmt} is unpacked, output set to unpacked with 16 bits." >&2
        set_format_unpacked "$videodev" "$full_mediabusfmt"

    else
        echo "Selected format '$mediabusfmt' is packed, output set to packed." >&2
        set_format "$videodev" "$full_mediabusfmt"
    fi

    if whiptail --yesno "Persist the selected format so it is applied automatically at boot for this camera?" 10 80 --title "Persist format"; then
        
                sudo mkdir -p /etc/vc-mipi/formats.d 2>/dev/null

            mediadev=$(get_mediadevice "$subdev")

            entity_name=$(media-ctl -d "$mediadev" -p | grep -B 3 "$subdev" | grep entity | awk -F ': ' '{ print $2 }' | awk '{ print $1, $2 }')
            sanitized_entity=$(tr -cs 'a-zA-Z0-9._-' '_' <<<"$entity_name")
            
            # Get the current pixelformat that would be used
            subdev_format=$(get_mediabus_code_string "$subdev")

            video_format=$(get_pixelformat_fourcc "$videodev")
           {
            echo "# Auto-generated by vc-config for entity: $entity_name"
            printf 'preferred_pixelformat_subdev="%s"\n' "$subdev_format"
            printf 'preferred_pixelformat_videodev="%s"\n' "$video_format"
           
            } |  sudo tee "/etc/vc-mipi/formats.d/${sanitized_entity}.conf" >/dev/null
    fi
    

}

dialog_show_config()
{
    local subdev=$1
    local videodev=$2

    # Find the media device for this video device
    local mediadev_for_vdev=""
    for m in /dev/media*; do
        if media-ctl -d "$m" -p | grep -q "$videodev"; then
            mediadev_for_vdev="$m"; break
        fi
    done

    if [ -n "$mediadev_for_vdev" ]; then
        stored_config=$(get_stored_config_for_dev "$subdev" "$mediadev_for_vdev")
        if [ $? -eq 0 ]; then
            current_format=$(v4l2-ctl -d "$subdev" --get-subdev-fmt | grep Mediabus | awk -F ' ' '{ print $5 }' | tr -d '()' | cut -c 15-)
            current_resolution=$(v4l2-ctl -d "$subdev" --get-subdev-fmt | grep Width | awk -F ' ' '{ print $3 }' | tr '/' 'x')
            current_pixelformat=$(v4l2-ctl -d "$videodev" --get-fmt-video | grep "Pixel Format" | awk -F "'" '{print $2}')
            
            whiptail --msgbox "=== Stored Configuration ===\n$stored_config\n\n=== Current Settings ===\nFormat: $current_format\nResolution: $current_resolution\nPixel Format: $current_pixelformat" 15 60 --title "Configuration" 3>&1 1>&2 2>&3
        else
            whiptail --msgbox "No stored configuration found for this device." 8 50 --title "Configuration" 3>&1 1>&2 2>&3
        fi
    else
        whiptail --msgbox "Could not find media device for $videodev" 8 50 --title "Error" 3>&1 1>&2 2>&3
    fi
}

dialog_get_versions()
{
    core_version=$(cat /sys/module/vc_mipi_core/version)
    modules_version=$(cat /sys/module/vc_mipi_modules/version)
    camera_version=$(cat /sys/module/vc_mipi_camera/version)

    whiptail --msgbox "vc_mipi_core version:    $core_version\nvc_mipi_modules version: $modules_version\nvc_mipi_camera version:  $camera_version" 15 50 --title "Version Information" 3>&1 1>&2 2>&3

}

dialog_test_gstreamer()
{
    local subdev=$1

    # Get the mDNS hostname
    mdns_name=$(hostname).local

    if whiptail --yesno "This will start a GStreamer pipeline with libcamerasrc that streams video over TCP on port 5000.\n\nTo view the stream from another device, run:\ngst-launch-1.0 tcpclientsrc host=$mdns_name port=5000 ! multipartdemux ! jpegdec ! autovideosink\n\nThe pipeline will run until you press Ctrl+C.\n\nDo you want to continue?" 16 90 --title "GStreamer Test"; then
        echo "Starting GStreamer pipeline..."
        echo "You can view the stream by connecting to this device on port 5000"
        echo "Client command: gst-launch-1.0 tcpclientsrc host=$mdns_name port=5000 ! multipartdemux ! jpegdec ! autovideosink"
        echo "Press Ctrl+C to stop the stream"
        sleep 3

        # Large-sensor + non-native-aspect requests (e.g. a 20 MP 3:2 sensor
        # asked for 1280x720) make the PiSP backend crop to 16:9 *and*
        # downscale by >4x in one step, which can exceed its tiling limits
        # and abort with "Tile height too small at output". Downscaling the
        # ISP output by only 2x (same aspect as the sensor, no crop) is safe,
        # then videoscale does the final resize/crop-to-16:9 in software.
        local native_wh
        native_wh=$(v4l2-ctl -d "$subdev" --get-subdev-fmt 2>/dev/null | sed -n 's#.*Width/Height *: *\([0-9]*\)/\([0-9]*\).*#\1 \2#p')
        local native_w=${native_wh% *}
        local native_h=${native_wh#* }

        local isp_caps="width=1280,height=720"
        if [[ "$native_w" =~ ^[0-9]+$ && "$native_h" =~ ^[0-9]+$ && "$native_w" -gt 1280 && "$native_h" -gt 720 ]]; then
            local mid_w=$(( (native_w / 4) * 2 ))
            local mid_h=$(( (native_h / 4) * 2 ))
            isp_caps="width=${mid_w},height=${mid_h}"
        fi

        # No fixed framerate here on purpose: pinning caps to an exact fps
        # (e.g. 30/1) forces libcamera to enforce that frame duration even
        # when the sensor's current auto-exposure needs longer per frame
        # (observed: default exposure ~44.5ms -> only ~22fps achievable).
        # That mismatch starves out capture completion and the stream goes
        # silent seconds after "Start streaming" with no error printed.
        # Leaving framerate unconstrained lets libcamera negotiate whatever
        # rate the current exposure/gain actually support.
        gst-launch-1.0 libcamerasrc ! \
            video/x-raw,colorimetry=bt709,format=NV12,$isp_caps ! \
            videoscale ! video/x-raw,width=1280,height=720 ! \
            queue ! jpegenc ! multipartmux ! \
            tcpserversink host=0.0.0.0 port=5000

        whiptail --msgbox "GStreamer pipeline stopped." 8 40 --title "Info" 3>&1 1>&2 2>&3
    fi
}
 

get_entity_name() {
    local mediadev=$1
    local entity_name=$(media-ctl -d "$mediadev" -p | grep " vc_mipi_camera " | awk -F 'vc_mipi_camera ' '{print $2}' | awk '{print $1}'  |head -n 1)
    if [ -z "$entity_name" ]; then
        echo "Error: vc_mipi_camera not found in $mediadev" >&2
        exit 1
    fi
    echo "$entity_name"
}

configure_subdev_controls() {
    local subdev=$1
    local videodev=$2

    # Get all available controls for the subdevice
    controls=$(v4l2-ctl --device=$subdev --list-ctrls | grep -v "flags=read-only" | grep -v " Controls" | grep -v "(button)" | awk '{print $1}' | grep -v '^$')

    while true; do
        # Create menu options for whiptail
        menu_options=()
        menu_options+=("Set ROI" "Set the region of interest")
        menu_options+=("Set Cropping" "Set the cropping area")
        menu_options+=("Configure Device Tree" "Configure the lanes for the mipi sensors")
        menu_options+=("Format" "Set the format of the camera")
        menu_options+=("Show Config" "Show stored configuration")
        menu_options+=("Logging" "Set logging level")
        menu_options+=("Version" "Get modules versions")
        menu_options+=("GStreamer Test" "Test camera with GStreamer libcamerasrc")

        for control in $controls; do
            if ! v4l2-ctl --device=$subdev --get-ctrl=$control;then
                continue
            fi
            current_value=$(v4l2-ctl --device=$subdev --get-ctrl=$control | awk '{print $NF}')
            control_info=$(v4l2-ctl --device=$subdev --list-ctrls | grep "$control")
            if [[ "$current_value" != "denied"* && "$control_info" != *"flags=read-only"* && "$control_info" != *"Controls"* ]]; then
                menu_options+=("$control" "$current_value")
            fi
        done

        # Show the menu with controls
        selected_control=$(whiptail --menu "Select the control to adjust:" 20 80 10 "${menu_options[@]}" 3>&1 1>&2 2>&3)
        # Check if cancel was pressed
        if [ $? -ne 0 ]; then
            exit 0
        fi    
        if([ "$selected_control" == "Set ROI" ]); then
            dialog_set_roi "$subdev" "$videodev"
            continue
        fi
        if([ "$selected_control" == "Set Cropping" ]); then
            dialog_set_cropping "$subdev" "$videodev"
            continue
        fi
        if([ "$selected_control" == "Logging" ]); then
            dialog_set_debuglevel 
            continue
        fi
        if([ "$selected_control" == "Configure Device Tree" ]); then
            configure_device_tree
            continue
        fi
        if([ "$selected_control" == "Format" ]); then
            dialog_set_format "$videodev"
            continue
        fi
        if([ "$selected_control" == "Show Config" ]); then
            dialog_show_config "$subdev" "$videodev"
            continue
        fi
        if([ "$selected_control" == "Version" ]); then
            dialog_get_versions 
            continue
        fi
        if([ "$selected_control" == "GStreamer Test" ]); then
            dialog_test_gstreamer "$subdev"
            continue
        fi


        # Get the current value of the selected control
        current_value=$(v4l2-ctl --device=$subdev --get-ctrl=$selected_control | awk '{print $NF}')
        
        # Prompt the user to enter a new value for the control
        new_value=$(whiptail --inputbox "Enter the value for $selected_control (current: $current_value):" 8 40 "$current_value" 3>&1 1>&2 2>&3)
        
        # Check if cancel was pressed
        if [ $? -ne 0 ]; then
            continue
        fi
        
        # Set the new value for the control
        if v4l2-ctl --device=$subdev --set-ctrl=$selected_control=$new_value; then
            TERM=ansi whiptail --infobox "Successfully set $selected_control to $new_value" 8 40 --title "Success" 
            sleep 1
        else
            whiptail --infobox "Failed to set $selected_control to $new_value" 8 40 --ok-button "OK" --title "Error"  
            sleep 1

        fi

        if([ "$selected_control" == "binning_mode" ]); then
            configure_video_device "$subdev" "$videodev"
        fi
    done
}

declare -A dev_subdev_map

# Scan all media devices and collect subdevice names
subdevices=()
menu_options=()
for mediadev in /dev/media*; do
    if media-ctl -d "$mediadev" -p | grep -q "vc_mipi_camera"; then
        subdev=$(media-ctl -d "$mediadev" -p | grep "vc_mipi_camera" -A  2  | grep "device node name" | awk -F ' ' '{ print $4 }')
        dev=$(media-ctl -d "$mediadev" -p | grep "$frontend_device" -A  2  | grep "device node name" | awk -F ' ' '{ print $4 }')
        bus=$(media-ctl -d "$mediadev" -p | grep "vc_mipi_camera" | sed -n 's/.*vc_mipi_camera \([0-9][0-9]*\)-[0-9a-fA-F]\+.*/\1/p')
        sensor=$(v4l2-ctl --device=$subdev --get-ctrl="sensor_info" | awk -F' ' '{print $NF}' | tr -d "'")

        dev_subdev_map["$dev"]="$subdev"

        menu_options+=( "$dev" "$subdev $sensor" )

    fi
done
if [ ${#menu_options[@]} -eq 0 ]; then
echo "No camera detected"
    whiptail --msgbox "No camera detected \nCheck the setup or the lanes configuration" 8 40 --title "Error" 3>&1 1>&2 2>&3
    if [ $? -ne 0 ]; then
        exit 1
    fi
    configure_device_tree
    sleep 1
    exit 1
fi
# Use whiptail to create a menu with the collected subdevice names
selected_dev=$(whiptail --menu "Select the sensor" 10 80 3 "${menu_options[@]}" 3>&1 1>&2 2>&3)
if [ $? -ne 0 ]; then
    exit 1
fi
selected_subdev=${dev_subdev_map["$selected_dev"]}
configure_subdev_controls "$selected_subdev" "$selected_dev"

