ID Workflow Result Correct Bug Created Started Finished Revision
ef5baa3e repro πŸ’₯ KASAN: slab-use-after-free Read in i2c_adapter_lock_bus 2026/07/30 11:51 2026/07/30 11:51 2026/07/30 13:36 2377cd3d
Agent: prod-syz-agent-5
External Bug ID: ---

Inputs:
BaseBranch master
BaseCommit RC
BaseRepository git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
BugTitle KASAN: slab-use-after-free Read in i2c_adapter_lock_bus
CrashLogID 6533455099199488
CrashReportID 4717006642741248
KernelCommit fc02acf6ac0ccde0c805c2daa9148683cdd01ba8
KernelConfig
Show (272107 bytes)
#
# Automatically generated file; DO NOT EDIT.
# Linux/x86_64 syzkaller Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77)"
CONFIG_GCC_VERSION=0
CONFIG_CC_IS_CLANG=y
CONFIG_CLANG_VERSION=220108
CONFIG_AS_IS_LLVM=y
CONFIG_AS_VERSION=220108
CONFIG_LD_VERSION=0
CONFIG_LD_IS_LLD=y
CONFIG_LLD_VERSION=220108
CONFIG_RUSTC_VERSION=109600
CONFIG_RUST_IS_AVAILABLE=y
CONFIG_RUSTC_LLVM_VERSION=220102
CONFIG_RUSTC_LLVM_MAJOR_VERSION=22
CONFIG_RUSTC_CLANG_LLVM_COMPATIBLE=y
CONFIG_CC_CAN_LINK=y
CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y
CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y
CONFIG_TOOLS_SUPPORT_RELR=y
CONFIG_CC_HAS_ASM_INLINE=y
CONFIG_CC_HAS_ASSUME=y
CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
CONFIG_CC_HAS_COUNTED_BY=y
CONFIG_CC_HAS_COUNTED_BY_PTR=y
CONFIG_CC_HAS_ALLOC_TOKEN=y
CONFIG_CC_HAS_MULTIDIMENSIONAL_NONSTRING=y
CONFIG_LD_CAN_USE_KEEP_IN_OVERLAY=y
CONFIG_RUSTC_HAS_SPAN_FILE=y
CONFIG_RUSTC_HAS_UNNECESSARY_TRANSMUTES=y
CONFIG_RUSTC_HAS_FILE_WITH_NUL=y
CONFIG_RUSTC_HAS_FILE_AS_C_STR=y
CONFIG_PAHOLE_VERSION=130
CONFIG_CONSTRUCTORS=y
CONFIG_IRQ_WORK=y
CONFIG_BUILDTIME_TABLE_SORT=y
CONFIG_THREAD_INFO_IN_TASK=y

#
# General setup
#
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_BUILD_SALT=""
CONFIG_HAVE_KERNEL_GZIP=y
CONFIG_HAVE_KERNEL_BZIP2=y
CONFIG_HAVE_KERNEL_LZMA=y
CONFIG_HAVE_KERNEL_XZ=y
CONFIG_HAVE_KERNEL_LZO=y
CONFIG_HAVE_KERNEL_LZ4=y
CONFIG_HAVE_KERNEL_ZSTD=y
CONFIG_KERNEL_GZIP=y
# CONFIG_KERNEL_BZIP2 is not set
# CONFIG_KERNEL_LZMA is not set
# CONFIG_KERNEL_XZ is not set
# CONFIG_KERNEL_LZO is not set
# CONFIG_KERNEL_LZ4 is not set
# CONFIG_KERNEL_ZSTD is not set
CONFIG_DEFAULT_INIT=""
CONFIG_DEFAULT_HOSTNAME="(none)"
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_SYSVIPC_COMPAT=y
CONFIG_POSIX_MQUEUE=y
CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_WATCH_QUEUE=y
CONFIG_CROSS_MEMORY_ATTACH=y
CONFIG_AUDIT=y
CONFIG_HAVE_ARCH_AUDITSYSCALL=y
CONFIG_AUDITSYSCALL=y

#
# IRQ subsystem
#
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
CONFIG_GENERIC_PENDING_IRQ=y
CONFIG_GENERIC_IRQ_MIGRATION=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_DOMAIN_HIERARCHY=y
CONFIG_GENERIC_MSI_IRQ=y
CONFIG_GENERIC_IRQ_MATRIX_ALLOCATOR=y
CONFIG_GENERIC_IRQ_RESERVATION_MODE=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_SPARSE_IRQ=y
# CONFIG_GENERIC_IRQ_DEBUGFS is not set
# end of IRQ subsystem

CONFIG_CLOCKSOURCE_WATCHDOG=y
CONFIG_ARCH_CLOCKSOURCE_INIT=y
CONFIG_ARCH_WANTS_CLOCKSOURCE_READ_INLINE=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST_IDLE=y
CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y
CONFIG_GENERIC_CLOCKEVENTS_COUPLED=y
CONFIG_GENERIC_CLOCKEVENTS_COUPLED_INLINE=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_HRTIMER_REARM_DEFERRED=y
CONFIG_HAVE_POSIX_CPU_TIMERS_TASK_WORK=y
CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
CONFIG_CONTEXT_TRACKING=y
CONFIG_CONTEXT_TRACKING_IDLE=y

#
# Timers subsystem
#
CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ_COMMON=y
# CONFIG_HZ_PERIODIC is not set
CONFIG_NO_HZ_IDLE=y
# CONFIG_NO_HZ_FULL is not set
CONFIG_CONTEXT_TRACKING_USER=y
# CONFIG_CONTEXT_TRACKING_USER_FORCE is not set
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_POSIX_AUX_CLOCKS=y
# end of Timers subsystem

CONFIG_BPF=y
CONFIG_HAVE_EBPF_JIT=y
CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y

#
# BPF subsystem
#
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_BPF_JIT_ALWAYS_ON=y
CONFIG_BPF_JIT_DEFAULT_ON=y
# CONFIG_BPF_UNPRIV_DEFAULT_OFF is not set
CONFIG_BPF_PRELOAD=y
CONFIG_BPF_PRELOAD_UMD=y
CONFIG_BPF_LSM=y
# end of BPF subsystem

CONFIG_PREEMPT_BUILD=y
CONFIG_ARCH_HAS_PREEMPT_LAZY=y
CONFIG_PREEMPT=y
# CONFIG_PREEMPT_LAZY is not set
CONFIG_PREEMPT_RT=y
# CONFIG_PREEMPT_RT_NEEDS_BH_LOCK is not set
CONFIG_PREEMPT_COUNT=y
CONFIG_PREEMPTION=y
CONFIG_PREEMPT_DYNAMIC=y
CONFIG_SCHED_CORE=y

#
# CPU/Task time and stats accounting
#
CONFIG_VIRT_CPU_ACCOUNTING=y
# CONFIG_TICK_CPU_ACCOUNTING is not set
CONFIG_VIRT_CPU_ACCOUNTING_GEN=y
CONFIG_IRQ_TIME_ACCOUNTING=y
CONFIG_HAVE_SCHED_AVG_IRQ=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_PSI=y
# CONFIG_PSI_DEFAULT_DISABLED is not set
# end of CPU/Task time and stats accounting

CONFIG_CPU_ISOLATION=y

#
# RCU Subsystem
#
CONFIG_TREE_RCU=y
CONFIG_PREEMPT_RCU=y
# CONFIG_RCU_EXPERT is not set
CONFIG_TREE_SRCU=y
CONFIG_TASKS_RCU_GENERIC=y
CONFIG_NEED_TASKS_RCU=y
CONFIG_TASKS_RCU=y
CONFIG_TASKS_TRACE_RCU=y
CONFIG_RCU_STALL_COMMON=y
CONFIG_RCU_NEED_SEGCBLIST=y
# CONFIG_RCU_BOOST is not set
# end of RCU Subsystem

CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_IKHEADERS is not set
CONFIG_LOG_BUF_SHIFT=18
CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
# CONFIG_PRINTK_INDEX is not set
CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y

#
# Scheduler features
#
# CONFIG_UCLAMP_TASK is not set
# end of Scheduler features

CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y
CONFIG_CC_HAS_INT128=y
CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough"
CONFIG_CC_MS_EXTENSIONS="-fms-extensions"
CONFIG_GCC10_NO_ARRAY_BOUNDS=y
CONFIG_GCC_NO_STRINGOP_OVERFLOW=y
CONFIG_ARCH_SUPPORTS_INT128=y
CONFIG_SCHED_CACHE=y
CONFIG_SLAB_OBJ_EXT=y
CONFIG_CGROUPS=y
CONFIG_PAGE_COUNTER=y
# CONFIG_CGROUP_FAVOR_DYNMODS is not set
CONFIG_MEMCG=y
CONFIG_MEMCG_V1=y
CONFIG_BLK_CGROUP=y
CONFIG_CGROUP_WRITEBACK=y
CONFIG_CGROUP_SCHED=y
CONFIG_GROUP_SCHED_WEIGHT=y
CONFIG_GROUP_SCHED_BANDWIDTH=y
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_CFS_BANDWIDTH=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_SCHED_MM_CID=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_RDMA=y
# CONFIG_CGROUP_DMEM is not set
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CPUSETS=y
# CONFIG_CPUSETS_V1 is not set
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
# CONFIG_CGROUP_BPF is not set
CONFIG_CGROUP_MISC=y
CONFIG_CGROUP_DEBUG=y
CONFIG_SOCK_CGROUP_DATA=y
CONFIG_NAMESPACES=y
CONFIG_UTS_NS=y
CONFIG_TIME_NS=y
CONFIG_TIME_NS_VDSO=y
CONFIG_IPC_NS=y
CONFIG_USER_NS=y
CONFIG_PID_NS=y
CONFIG_NET_NS=y
CONFIG_CHECKPOINT_RESTORE=y
# CONFIG_SCHED_AUTOGROUP is not set
CONFIG_RELAY=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
CONFIG_RD_BZIP2=y
CONFIG_RD_LZMA=y
CONFIG_RD_XZ=y
CONFIG_RD_LZO=y
CONFIG_RD_LZ4=y
CONFIG_RD_ZSTD=y
# CONFIG_BOOT_CONFIG is not set
CONFIG_CMDLINE_LOG_WRAP_IDEAL_LEN=1021
CONFIG_INITRAMFS_PRESERVE_MTIME=y
CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_LD_ORPHAN_WARN=y
CONFIG_LD_ORPHAN_WARN_LEVEL="warn"
CONFIG_SYSCTL=y
CONFIG_HAVE_UID16=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
CONFIG_SYSFS_SYSCALL=y
CONFIG_HAVE_PCSPKR_PLATFORM=y
CONFIG_EXPERT=y
CONFIG_UID16=y
CONFIG_MULTIUSER=y
CONFIG_SGETMASK_SYSCALL=y
CONFIG_FHANDLE=y
CONFIG_POSIX_TIMERS=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_PCSPKR_PLATFORM=y
# CONFIG_BASE_SMALL is not set
CONFIG_FUTEX=y
CONFIG_FUTEX_PI=y
CONFIG_FUTEX_PRIVATE_HASH=y
CONFIG_FUTEX_MPOL=y
CONFIG_HAVE_FUTEX_ROBUST_UNLOCK=y
CONFIG_FUTEX_ROBUST_UNLOCK=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_IO_URING=y
CONFIG_IO_URING_MOCK_FILE=y
CONFIG_ADVISE_SYSCALLS=y
CONFIG_MEMBARRIER=y
CONFIG_KCMP=y
CONFIG_RSEQ=y
CONFIG_RSEQ_SLICE_EXTENSION=y
# CONFIG_RSEQ_STATS is not set
# CONFIG_RSEQ_DEBUG_DEFAULT_ENABLE is not set
CONFIG_CACHESTAT_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_SELFTEST is not set
CONFIG_KALLSYMS_ALL=y
CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
CONFIG_ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS=y
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_GUEST_PERF_EVENTS=y
CONFIG_PERF_GUEST_MEDIATED_PMU=y

#
# Kernel Performance Events And Counters
#
CONFIG_PERF_EVENTS=y
# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
# end of Kernel Performance Events And Counters

CONFIG_SYSTEM_DATA_VERIFICATION=y
CONFIG_PROFILING=y
# CONFIG_RUST is not set
CONFIG_TRACEPOINTS=y

#
# Kexec and crash features
#
CONFIG_CRASH_RESERVE=y
CONFIG_VMCORE_INFO=y
CONFIG_KEXEC_CORE=y
CONFIG_KEXEC=y
# CONFIG_KEXEC_FILE is not set
# CONFIG_KEXEC_JUMP is not set
CONFIG_CRASH_DUMP=y
CONFIG_CRASH_HOTPLUG=y
CONFIG_CRASH_MAX_MEMORY_RANGES=8192
# end of Kexec and crash features

#
# Live Update and Kexec HandOver
#
# CONFIG_KEXEC_HANDOVER is not set
# end of Live Update and Kexec HandOver
# end of General setup

CONFIG_64BIT=y
CONFIG_X86_64=y
CONFIG_X86=y
CONFIG_INSTRUCTION_DECODER=y
CONFIG_OUTPUT_FORMAT="elf64-x86-64"
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_MMU=y
CONFIG_ARCH_MMAP_RND_BITS_MIN=28
CONFIG_ARCH_MMAP_RND_BITS_MAX=32
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16
CONFIG_GENERIC_ISA_DMA=y
CONFIG_GENERIC_CSUM=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARCH_HAS_CPU_RELAX=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_AUDIT_ARCH=y
CONFIG_KASAN_SHADOW_OFFSET=0xdffffc0000000000
CONFIG_HAVE_INTEL_TXT=y
CONFIG_ARCH_SUPPORTS_UPROBES=y
CONFIG_FIX_EARLYCON_MEM=y
CONFIG_PGTABLE_LEVELS=5

#
# Processor type and features
#
CONFIG_SMP=y
CONFIG_X86_X2APIC=y
# CONFIG_X86_POSTED_MSI is not set
CONFIG_X86_MPPARSE=y
# CONFIG_X86_CPU_RESCTRL is not set
CONFIG_X86_FRED=y
CONFIG_X86_EXTENDED_PLATFORM=y
# CONFIG_X86_NUMACHIP is not set
# CONFIG_X86_VSMP is not set
# CONFIG_X86_INTEL_MID is not set
# CONFIG_X86_GOLDFISH is not set
# CONFIG_X86_INTEL_LPSS is not set
# CONFIG_X86_AMD_PLATFORM_DEVICE is not set
CONFIG_IOSF_MBI=y
# CONFIG_IOSF_MBI_DEBUG is not set
CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y
CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_HYPERVISOR_GUEST=y
CONFIG_PARAVIRT=y
CONFIG_PARAVIRT_SPINLOCKS=y
CONFIG_X86_HV_CALLBACK_VECTOR=y
# CONFIG_XEN is not set
CONFIG_KVM_GUEST=y
CONFIG_ARCH_CPUIDLE_HALTPOLL=y
CONFIG_PVH=y
# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
CONFIG_PARAVIRT_CLOCK=y
# CONFIG_JAILHOUSE_GUEST is not set
# CONFIG_ACRN_GUEST is not set
# CONFIG_BHYVE_GUEST is not set
CONFIG_CC_HAS_MARCH_NATIVE=y
# CONFIG_X86_NATIVE_CPU is not set
CONFIG_X86_INTERNODE_CACHE_SHIFT=6
CONFIG_X86_L1_CACHE_SHIFT=6
CONFIG_X86_TSC=y
CONFIG_X86_HAVE_PAE=y
CONFIG_X86_CX8=y
CONFIG_X86_CMOV=y
CONFIG_X86_MINIMUM_CPU_FAMILY=64
CONFIG_X86_DEBUGCTLMSR=y
CONFIG_IA32_FEAT_CTL=y
CONFIG_X86_VMX_FEATURE_NAMES=y
CONFIG_PROCESSOR_SELECT=y
CONFIG_CPU_SUP_INTEL=y
CONFIG_CPU_SUP_AMD=y
# CONFIG_CPU_SUP_HYGON is not set
# CONFIG_CPU_SUP_CENTAUR is not set
# CONFIG_CPU_SUP_ZHAOXIN is not set
CONFIG_BROADCAST_TLB_FLUSH=y
CONFIG_HPET_TIMER=y
CONFIG_HPET_EMULATE_RTC=y
CONFIG_DMI=y
# CONFIG_GART_IOMMU is not set
CONFIG_BOOT_VESA_SUPPORT=y
# CONFIG_MAXSMP is not set
CONFIG_NR_CPUS_RANGE_BEGIN=2
CONFIG_NR_CPUS_RANGE_END=512
CONFIG_NR_CPUS_DEFAULT=64
CONFIG_NR_CPUS=8
CONFIG_SCHED_MC_PRIO=y
CONFIG_X86_LOCAL_APIC=y
CONFIG_ACPI_MADT_WAKEUP=y
CONFIG_X86_IO_APIC=y
CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
CONFIG_X86_MCE=y
# CONFIG_X86_MCELOG_LEGACY is not set
CONFIG_X86_MCE_INTEL=y
CONFIG_X86_MCE_AMD=y
CONFIG_X86_MCE_THRESHOLD=y
# CONFIG_X86_MCE_INJECT is not set

#
# Performance monitoring
#
CONFIG_PERF_EVENTS_INTEL_UNCORE=y
CONFIG_PERF_EVENTS_INTEL_RAPL=y
CONFIG_PERF_EVENTS_INTEL_CSTATE=y
# CONFIG_PERF_EVENTS_AMD_POWER is not set
CONFIG_PERF_EVENTS_AMD_UNCORE=y
# CONFIG_PERF_EVENTS_AMD_BRS is not set
# end of Performance monitoring

CONFIG_X86_16BIT=y
CONFIG_X86_ESPFIX64=y
CONFIG_X86_VSYSCALL_EMULATION=y
CONFIG_X86_IOPL_IOPERM=y
CONFIG_MICROCODE=y
# CONFIG_MICROCODE_LATE_LOADING is not set
# CONFIG_MICROCODE_DBG is not set
CONFIG_X86_MSR=y
CONFIG_X86_CPUID=y
CONFIG_X86_DIRECT_GBPAGES=y
# CONFIG_X86_CPA_STATISTICS is not set
CONFIG_NUMA=y
CONFIG_AMD_NUMA=y
CONFIG_X86_64_ACPI_NUMA=y
CONFIG_NODES_SHIFT=6
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_DEFAULT=y
# CONFIG_ARCH_MEMORY_PROBE is not set
CONFIG_ARCH_PROC_KCORE_TEXT=y
CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
# CONFIG_X86_PMEM_LEGACY is not set
# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set
CONFIG_MTRR=y
# CONFIG_MTRR_SANITIZER is not set
CONFIG_X86_PAT=y
CONFIG_X86_UMIP=y
CONFIG_CC_HAS_IBT=y
CONFIG_X86_CET=y
CONFIG_X86_KERNEL_IBT=y
CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS=y
CONFIG_ARCH_PKEY_BITS=4
# CONFIG_X86_INTEL_TSX_MODE_OFF is not set
CONFIG_X86_INTEL_TSX_MODE_ON=y
# CONFIG_X86_INTEL_TSX_MODE_AUTO is not set
CONFIG_X86_SGX=y
CONFIG_X86_USER_SHADOW_STACK=y
# CONFIG_INTEL_TDX_HOST is not set
# CONFIG_EFI is not set
CONFIG_HZ_100=y
# CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
CONFIG_SCHED_HRTICK=y
CONFIG_ARCH_SUPPORTS_KEXEC=y
CONFIG_ARCH_SUPPORTS_KEXEC_FILE=y
CONFIG_ARCH_SUPPORTS_KEXEC_PURGATORY=y
CONFIG_ARCH_SUPPORTS_KEXEC_SIG=y
CONFIG_ARCH_SUPPORTS_KEXEC_SIG_FORCE=y
CONFIG_ARCH_SUPPORTS_KEXEC_BZIMAGE_VERIFY_SIG=y
CONFIG_ARCH_SUPPORTS_KEXEC_JUMP=y
CONFIG_ARCH_SUPPORTS_KEXEC_HANDOVER=y
CONFIG_ARCH_SUPPORTS_CRASH_DUMP=y
CONFIG_ARCH_DEFAULT_CRASH_DUMP=y
CONFIG_ARCH_SUPPORTS_CRASH_HOTPLUG=y
CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION=y
CONFIG_PHYSICAL_START=0x1000000
# CONFIG_RELOCATABLE is not set
CONFIG_PHYSICAL_ALIGN=0x200000
CONFIG_HOTPLUG_CPU=y
# CONFIG_COMPAT_VDSO is not set
CONFIG_LEGACY_VSYSCALL_XONLY=y
# CONFIG_LEGACY_VSYSCALL_NONE is not set
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="earlyprintk=serial net.ifnames=0 sysctl.kernel.hung_task_all_cpu_backtrace=1 ima_policy=tcb nf-conntrack-ftp.ports=20000 nf-conntrack-tftp.ports=20000 nf-conntrack-sip.ports=20000 nf-conntrack-irc.ports=20000 nf-conntrack-sane.ports=20000 binder.debug_mask=0 rcupdate.rcu_expedited=1 rcupdate.rcu_cpu_stall_cputime=1 no_hash_pointers page_owner=on sysctl.vm.nr_hugepages=4 sysctl.vm.nr_overcommit_hugepages=4 secretmem.enable=1 sysctl.max_rcu_stall_to_panic=1 msr.allow_writes=off coredump_filter=0xffff root=/dev/sda console=ttyS0 vsyscall=native numa=fake=2 kvm-intel.nested=1 spec_store_bypass_disable=prctl nopcid vivid.n_devs=64 vivid.multiplanar=1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2 netrom.nr_ndevs=32 rose.rose_ndevs=32 smp.csd_lock_timeout=100000 watchdog_thresh=55 workqueue.watchdog_thresh=140 sysctl.net.core.netdev_unregister_timeout_secs=140 dummy_hcd.num=32 max_loop=32 nbds_max=32 comedi.comedi_num_legacy_minors=4 panic_on_warn=1"
# CONFIG_CMDLINE_OVERRIDE is not set
CONFIG_MODIFY_LDT_SYSCALL=y
# CONFIG_STRICT_SIGALTSTACK_SIZE is not set
CONFIG_HAVE_LIVEPATCH=y
CONFIG_HAVE_KLP_BUILD=y
CONFIG_X86_BUS_LOCK_DETECT=y
# end of Processor type and features

CONFIG_CC_HAS_SLS=y
CONFIG_CC_HAS_RETURN_THUNK=y
CONFIG_CC_HAS_ENTRY_PADDING=y
CONFIG_CC_HAS_KCFI_ARITY=y
CONFIG_FUNCTION_PADDING_CFI=11
CONFIG_FUNCTION_PADDING_BYTES=16
CONFIG_CALL_PADDING=y
CONFIG_HAVE_CALL_THUNKS=y
CONFIG_CALL_THUNKS=y
CONFIG_CPU_MITIGATIONS=y
CONFIG_MITIGATION_PAGE_TABLE_ISOLATION=y
CONFIG_MITIGATION_RETPOLINE=y
CONFIG_MITIGATION_RETHUNK=y
CONFIG_MITIGATION_UNRET_ENTRY=y
CONFIG_MITIGATION_CALL_DEPTH_TRACKING=y
# CONFIG_CALL_THUNKS_DEBUG is not set
CONFIG_MITIGATION_IBPB_ENTRY=y
CONFIG_MITIGATION_IBRS_ENTRY=y
CONFIG_MITIGATION_SRSO=y
# CONFIG_MITIGATION_SLS is not set
CONFIG_MITIGATION_GDS=y
CONFIG_MITIGATION_RFDS=y
CONFIG_MITIGATION_SPECTRE_BHI=y
CONFIG_MITIGATION_MDS=y
CONFIG_MITIGATION_TAA=y
CONFIG_MITIGATION_MMIO_STALE_DATA=y
CONFIG_MITIGATION_L1TF=y
CONFIG_MITIGATION_RETBLEED=y
CONFIG_MITIGATION_SPECTRE_V1=y
CONFIG_MITIGATION_SPECTRE_V2=y
CONFIG_MITIGATION_SRBDS=y
CONFIG_MITIGATION_SSB=y
CONFIG_MITIGATION_ITS=y
CONFIG_MITIGATION_TSA=y
# CONFIG_MITIGATION_VMSCAPE is not set
CONFIG_ARCH_HAS_ADD_PAGES=y

#
# Power management and ACPI options
#
CONFIG_ARCH_HIBERNATION_HEADER=y
CONFIG_SUSPEND=y
CONFIG_SUSPEND_FREEZER=y
# CONFIG_SUSPEND_SKIP_SYNC is not set
CONFIG_HIBERNATE_CALLBACKS=y
CONFIG_HIBERNATION=y
CONFIG_HIBERNATION_SNAPSHOT_DEV=y
CONFIG_HIBERNATION_COMP_LZO=y
# CONFIG_HIBERNATION_COMP_LZ4 is not set
CONFIG_HIBERNATION_DEF_COMP="lzo"
CONFIG_PM_STD_PARTITION=""
CONFIG_PM_SLEEP=y
CONFIG_PM_SLEEP_SMP=y
# CONFIG_PM_AUTOSLEEP is not set
# CONFIG_PM_USERSPACE_AUTOSLEEP is not set
# CONFIG_PM_WAKELOCKS is not set
# CONFIG_PM_QOS_CPU_SYSTEM_WAKEUP is not set
CONFIG_PM=y
CONFIG_PM_DEBUG=y
# CONFIG_PM_ADVANCED_DEBUG is not set
# CONFIG_PM_TEST_SUSPEND is not set
CONFIG_PM_SLEEP_DEBUG=y
# CONFIG_DPM_WATCHDOG is not set
CONFIG_PM_TRACE=y
CONFIG_PM_TRACE_RTC=y
CONFIG_PM_CLK=y
# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
# CONFIG_ENERGY_MODEL is not set
CONFIG_ARCH_SUPPORTS_ACPI=y
CONFIG_ACPI=y
CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y
CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y
CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y
CONFIG_ACPI_THERMAL_LIB=y
# CONFIG_ACPI_DEBUGGER is not set
CONFIG_ACPI_SPCR_TABLE=y
# CONFIG_ACPI_FPDT is not set
CONFIG_ACPI_LPIT=y
CONFIG_ACPI_SLEEP=y
CONFIG_ACPI_REV_OVERRIDE_POSSIBLE=y
CONFIG_ACPI_EC=y
# CONFIG_ACPI_EC_DEBUGFS is not set
CONFIG_ACPI_AC=y
CONFIG_ACPI_BATTERY=y
CONFIG_ACPI_BUTTON=y
CONFIG_ACPI_VIDEO=y
CONFIG_ACPI_FAN=y
# CONFIG_ACPI_TAD is not set
CONFIG_ACPI_DOCK=y
CONFIG_ACPI_CPU_FREQ_PSS=y
CONFIG_ACPI_PROCESSOR_CSTATE=y
CONFIG_ACPI_PROCESSOR_IDLE=y
CONFIG_ACPI_CPPC_LIB=y
CONFIG_ACPI_PROCESSOR=y
CONFIG_ACPI_HOTPLUG_CPU=y
# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set
CONFIG_ACPI_THERMAL=y
CONFIG_ACPI_PLATFORM_PROFILE=y
CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y
CONFIG_ACPI_TABLE_UPGRADE=y
CONFIG_ACPI_DEBUG=y
# CONFIG_ACPI_PCI_SLOT is not set
CONFIG_ACPI_CONTAINER=y
# CONFIG_ACPI_HOTPLUG_MEMORY is not set
CONFIG_ACPI_HOTPLUG_IOAPIC=y
# CONFIG_ACPI_SBS is not set
# CONFIG_ACPI_HED is not set
# CONFIG_ACPI_REDUCED_HARDWARE_ONLY is not set
CONFIG_ACPI_NHLT=y
CONFIG_ACPI_NFIT=y
# CONFIG_NFIT_SECURITY_DEBUG is not set
CONFIG_ACPI_NUMA=y
# CONFIG_ACPI_HMAT is not set
CONFIG_HAVE_ACPI_APEI=y
CONFIG_HAVE_ACPI_APEI_NMI=y
# CONFIG_ACPI_APEI is not set
# CONFIG_ACPI_DPTF is not set
# CONFIG_ACPI_EXTLOG is not set
# CONFIG_ACPI_CONFIGFS is not set
# CONFIG_ACPI_PFRUT is not set
CONFIG_ACPI_PCC=y
# CONFIG_ACPI_FFH is not set
CONFIG_ACPI_MRRM=y
CONFIG_PMIC_OPREGION=y
CONFIG_BXT_WC_PMIC_OPREGION=y
# CONFIG_CHT_WC_PMIC_OPREGION is not set
CONFIG_X86_PM_TIMER=y

#
# CPU Frequency scaling
#
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_GOV_ATTR_SET=y
CONFIG_CPU_FREQ_GOV_COMMON=y
# CONFIG_CPU_FREQ_STAT is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y

#
# CPU frequency scaling drivers
#
# CONFIG_CPUFREQ_DT is not set
# CONFIG_CPUFREQ_DT_PLATDEV is not set
CONFIG_X86_INTEL_PSTATE=y
# CONFIG_X86_PCC_CPUFREQ is not set
CONFIG_X86_AMD_PSTATE=y
CONFIG_X86_AMD_PSTATE_DEFAULT_MODE=3
# CONFIG_X86_AMD_PSTATE_UT is not set
CONFIG_X86_ACPI_CPUFREQ=y
CONFIG_X86_ACPI_CPUFREQ_CPB=y
# CONFIG_X86_POWERNOW_K8 is not set
# CONFIG_X86_AMD_FREQ_SENSITIVITY is not set
# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
# CONFIG_X86_P4_CLOCKMOD is not set

#
# shared options
#
CONFIG_CPUFREQ_ARCH_CUR_FREQ=y
# end of CPU Frequency scaling

#
# CPU Idle
#
CONFIG_CPU_IDLE=y
# CONFIG_CPU_IDLE_GOV_LADDER is not set
CONFIG_CPU_IDLE_GOV_MENU=y
# CONFIG_CPU_IDLE_GOV_TEO is not set
CONFIG_CPU_IDLE_GOV_HALTPOLL=y
CONFIG_HALTPOLL_CPUIDLE=y
# end of CPU Idle

CONFIG_INTEL_IDLE=y
# end of Power management and ACPI options

#
# Bus options (PCI etc.)
#
CONFIG_PCI_DIRECT=y
CONFIG_PCI_MMCONFIG=y
CONFIG_MMCONF_FAM10H=y
CONFIG_ISA_BUS=y
CONFIG_ISA_DMA_API=y
CONFIG_AMD_NB=y
CONFIG_AMD_NODE=y
# end of Bus options (PCI etc.)

#
# Binary Emulations
#
CONFIG_IA32_EMULATION=y
# CONFIG_IA32_EMULATION_DEFAULT_DISABLED is not set
CONFIG_COMPAT_32=y
CONFIG_COMPAT=y
CONFIG_COMPAT_FOR_U64_ALIGNMENT=y
# end of Binary Emulations

CONFIG_KVM_COMMON=y
CONFIG_HAVE_KVM_PFNCACHE=y
CONFIG_HAVE_KVM_IRQCHIP=y
CONFIG_HAVE_KVM_IRQ_ROUTING=y
CONFIG_HAVE_KVM_DIRTY_RING=y
CONFIG_HAVE_KVM_DIRTY_RING_TSO=y
CONFIG_HAVE_KVM_DIRTY_RING_ACQ_REL=y
CONFIG_KVM_MMIO=y
CONFIG_KVM_ASYNC_PF=y
CONFIG_HAVE_KVM_MSI=y
CONFIG_HAVE_KVM_READONLY_MEM=y
CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y
CONFIG_KVM_VFIO=y
CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y
CONFIG_KVM_GENERIC_PRE_FAULT_MEMORY=y
CONFIG_KVM_COMPAT=y
CONFIG_HAVE_KVM_IRQ_BYPASS=y
CONFIG_HAVE_KVM_NO_POLL=y
CONFIG_VIRT_XFER_TO_GUEST_WORK=y
CONFIG_HAVE_KVM_PM_NOTIFIER=y
CONFIG_KVM_GENERIC_HARDWARE_ENABLING=y
CONFIG_KVM_ELIDE_TLB_FLUSH_IF_YOUNG=y
CONFIG_KVM_MMU_LOCKLESS_AGING=y
CONFIG_KVM_GENERIC_MEMORY_ATTRIBUTES=y
CONFIG_KVM_GUEST_MEMFD=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM_X86=y
CONFIG_KVM=y
CONFIG_KVM_SW_PROTECTED_VM=y
CONFIG_KVM_INTEL=y
# CONFIG_KVM_INTEL_PROVE_VE is not set
CONFIG_X86_SGX_KVM=y
CONFIG_KVM_AMD=y
CONFIG_KVM_IOAPIC=y
CONFIG_KVM_SMM=y
CONFIG_KVM_HYPERV=y
CONFIG_KVM_XEN=y
CONFIG_KVM_PROVE_MMU=y
CONFIG_KVM_MAX_NR_VCPUS=1024
CONFIG_X86_REQUIRED_FEATURE_ALWAYS=y
CONFIG_X86_REQUIRED_FEATURE_NOPL=y
CONFIG_X86_REQUIRED_FEATURE_CX8=y
CONFIG_X86_REQUIRED_FEATURE_CMOV=y
CONFIG_X86_REQUIRED_FEATURE_CPUID=y
CONFIG_X86_REQUIRED_FEATURE_FPU=y
CONFIG_X86_REQUIRED_FEATURE_PAE=y
CONFIG_X86_REQUIRED_FEATURE_PSE=y
CONFIG_X86_REQUIRED_FEATURE_PGE=y
CONFIG_X86_REQUIRED_FEATURE_MSR=y
CONFIG_X86_REQUIRED_FEATURE_FXSR=y
CONFIG_X86_REQUIRED_FEATURE_XMM=y
CONFIG_X86_REQUIRED_FEATURE_XMM2=y
CONFIG_X86_REQUIRED_FEATURE_LM=y
CONFIG_X86_DISABLED_FEATURE_VME=y
CONFIG_X86_DISABLED_FEATURE_K6_MTRR=y
CONFIG_X86_DISABLED_FEATURE_CYRIX_ARR=y
CONFIG_X86_DISABLED_FEATURE_CENTAUR_MCR=y
CONFIG_X86_DISABLED_FEATURE_LAM=y
CONFIG_X86_DISABLED_FEATURE_XENPV=y
CONFIG_X86_DISABLED_FEATURE_TDX_GUEST=y
CONFIG_X86_DISABLED_FEATURE_SEV_SNP=y
CONFIG_AS_WRUSS=y
CONFIG_ARCH_CONFIGURES_CPU_MITIGATIONS=y

#
# General architecture-dependent options
#
CONFIG_HOTPLUG_SMT=y
CONFIG_ARCH_SUPPORTS_SCHED_SMT=y
CONFIG_ARCH_SUPPORTS_SCHED_CLUSTER=y
CONFIG_ARCH_SUPPORTS_SCHED_MC=y
CONFIG_SCHED_SMT=y
CONFIG_SCHED_CLUSTER=y
CONFIG_SCHED_MC=y
CONFIG_HOTPLUG_CORE_SYNC=y
CONFIG_HOTPLUG_CORE_SYNC_DEAD=y
CONFIG_HOTPLUG_CORE_SYNC_FULL=y
CONFIG_HOTPLUG_SPLIT_STARTUP=y
CONFIG_HOTPLUG_PARALLEL=y
CONFIG_GENERIC_IRQ_ENTRY=y
CONFIG_GENERIC_SYSCALL=y
CONFIG_GENERIC_ENTRY=y
# CONFIG_KPROBES is not set
CONFIG_JUMP_LABEL=y
# CONFIG_STATIC_KEYS_SELFTEST is not set
# CONFIG_STATIC_CALL_SELFTEST is not set
CONFIG_UPROBES=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_ARCH_USE_BUILTIN_BSWAP=y
CONFIG_USER_RETURN_NOTIFIER=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_OPTPROBES=y
CONFIG_HAVE_KPROBES_ON_FTRACE=y
CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y
CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y
CONFIG_HAVE_NMI=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_DMA_CONTIGUOUS=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
CONFIG_ARCH_HAS_SET_MEMORY=y
CONFIG_ARCH_HAS_SET_DIRECT_MAP=y
CONFIG_ARCH_HAS_CPU_FINALIZE_INIT=y
CONFIG_ARCH_HAS_CPU_PASID=y
CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y
CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y
CONFIG_ARCH_WANTS_NO_INSTR=y
CONFIG_ARCH_MEMORY_ORDER_TSO=y
CONFIG_HAVE_ASM_MODVERSIONS=y
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
CONFIG_HAVE_RSEQ=y
CONFIG_HAVE_RUST=y
CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y
CONFIG_HAVE_HW_BREAKPOINT=y
CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
CONFIG_HAVE_USER_RETURN_NOTIFIER=y
CONFIG_HAVE_PERF_EVENTS_NMI=y
CONFIG_HAVE_HARDLOCKUP_DETECTOR_PERF=y
CONFIG_UNWIND_USER=y
CONFIG_HAVE_UNWIND_USER_FP=y
CONFIG_HAVE_PERF_REGS=y
CONFIG_HAVE_PERF_USER_STACK_DUMP=y
CONFIG_HAVE_ARCH_JUMP_LABEL=y
CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y
CONFIG_MMU_GATHER_TABLE_FREE=y
CONFIG_MMU_GATHER_RCU_TABLE_FREE=y
CONFIG_MMU_GATHER_MERGE_VMAS=y
CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM=y
CONFIG_MMU_LAZY_TLB_REFCOUNT=y
CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
CONFIG_ARCH_HAVE_EXTRA_ELF_NOTES=y
CONFIG_ARCH_HAS_NMI_SAFE_THIS_CPU_OPS=y
CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
CONFIG_HAVE_CMPXCHG_LOCAL=y
CONFIG_HAVE_CMPXCHG_DOUBLE=y
CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
CONFIG_ARCH_WANT_OLD_COMPAT_IPC=y
CONFIG_HAVE_ARCH_SECCOMP=y
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
CONFIG_SECCOMP=y
CONFIG_SECCOMP_FILTER=y
# CONFIG_SECCOMP_CACHE_DEBUG is not set
CONFIG_HAVE_ARCH_KSTACK_ERASE=y
CONFIG_HAVE_STACKPROTECTOR=y
CONFIG_STACKPROTECTOR=y
CONFIG_STACKPROTECTOR_STRONG=y
CONFIG_ARCH_SUPPORTS_LTO_CLANG=y
CONFIG_ARCH_SUPPORTS_LTO_CLANG_THIN=y
CONFIG_HAS_LTO_CLANG=y
CONFIG_LTO_NONE=y
# CONFIG_LTO_CLANG_FULL is not set
# CONFIG_LTO_CLANG_THIN is not set
# CONFIG_LTO_CLANG_THIN_DIST is not set
CONFIG_AUTOFDO_CLANG=y
CONFIG_PROPELLER_CLANG=y
CONFIG_ARCH_SUPPORTS_CFI=y
# CONFIG_CFI is not set
CONFIG_HAVE_CFI_ICALL_NORMALIZE_INTEGERS=y
CONFIG_HAVE_CFI_ICALL_NORMALIZE_INTEGERS_RUSTC=y
CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y
CONFIG_HAVE_CONTEXT_TRACKING_USER=y
CONFIG_HAVE_CONTEXT_TRACKING_USER_OFFSTACK=y
CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
CONFIG_HAVE_PV_STEAL_CLOCK_GEN=y
CONFIG_HAVE_MOVE_PUD=y
CONFIG_HAVE_MOVE_PMD=y
CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD=y
CONFIG_HAVE_ARCH_HUGE_VMAP=y
CONFIG_HAVE_ARCH_HUGE_VMALLOC=y
CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
CONFIG_HAVE_ARCH_SOFT_DIRTY=y
CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
CONFIG_MODULES_USE_ELF_RELA=y
CONFIG_ARCH_HAS_EXECMEM_ROX=y
CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y
CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK=y
CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
CONFIG_HAVE_EXIT_THREAD=y
CONFIG_ARCH_MMAP_RND_BITS=28
CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y
CONFIG_ARCH_MMAP_RND_COMPAT_BITS=8
CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES=y
CONFIG_HAVE_PAGE_SIZE_4KB=y
CONFIG_PAGE_SIZE_4KB=y
CONFIG_PAGE_SIZE_LESS_THAN_64KB=y
CONFIG_PAGE_SIZE_LESS_THAN_256KB=y
CONFIG_PAGE_SHIFT=12
CONFIG_HAVE_OBJTOOL=y
CONFIG_HAVE_JUMP_LABEL_HACK=y
CONFIG_HAVE_NOINSTR_HACK=y
CONFIG_HAVE_NOINSTR_VALIDATION=y
CONFIG_HAVE_UACCESS_VALIDATION=y
CONFIG_HAVE_STACK_VALIDATION=y
CONFIG_HAVE_RELIABLE_STACKTRACE=y
CONFIG_OLD_SIGSUSPEND3=y
CONFIG_COMPAT_OLD_SIGACTION=y
CONFIG_COMPAT_32BIT_TIME=y
CONFIG_ARCH_SUPPORTS_RT=y
CONFIG_HAVE_ARCH_VMAP_STACK=y
CONFIG_VMAP_STACK=y
CONFIG_HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET=y
CONFIG_RANDOMIZE_KSTACK_OFFSET=y
# CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT is not set
CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
CONFIG_STRICT_KERNEL_RWX=y
CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
CONFIG_STRICT_MODULE_RWX=y
CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y
# CONFIG_LOCK_EVENT_COUNTS is not set
CONFIG_ARCH_HAS_MEM_ENCRYPT=y
CONFIG_HAVE_STATIC_CALL=y
CONFIG_HAVE_STATIC_CALL_INLINE=y
CONFIG_HAVE_PREEMPT_DYNAMIC=y
CONFIG_HAVE_PREEMPT_DYNAMIC_CALL=y
CONFIG_ARCH_WANT_LD_ORPHAN_WARN=y
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_ARCH_SUPPORTS_PAGE_TABLE_CHECK=y
CONFIG_ARCH_HAS_ELFCORE_COMPAT=y
CONFIG_ARCH_HAS_PARANOID_L1D_FLUSH=y
CONFIG_DYNAMIC_SIGFRAME=y
CONFIG_HAVE_ARCH_NODE_DEV_GROUP=y
CONFIG_ARCH_HAS_HW_PTE_YOUNG=y
CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG=y
CONFIG_ARCH_HAS_KERNEL_FPU_SUPPORT=y
CONFIG_HAVE_GENERIC_TIF_BITS=y

#
# GCOV-based kernel profiling
#
# CONFIG_GCOV_KERNEL is not set
CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
# end of GCOV-based kernel profiling

CONFIG_HAVE_GCC_PLUGINS=y
CONFIG_FUNCTION_ALIGNMENT_4B=y
CONFIG_FUNCTION_ALIGNMENT_16B=y
CONFIG_FUNCTION_ALIGNMENT=16
CONFIG_CC_HAS_SANE_FUNCTION_ALIGNMENT=y
CONFIG_ARCH_HAS_CPU_ATTACK_VECTORS=y
# end of General architecture-dependent options

CONFIG_RT_MUTEXES=y
CONFIG_MODULE_SIG_FORMAT=y
CONFIG_MODULES=y
# CONFIG_MODULE_DEBUG is not set
# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_MODULE_UNLOAD_TAINT_TRACKING is not set
CONFIG_MODVERSIONS=y
# CONFIG_GENKSYMS is not set
CONFIG_GENDWARFKSYMS=y
CONFIG_ASM_MODVERSIONS=y
# CONFIG_EXTENDED_MODVERSIONS is not set
# CONFIG_BASIC_MODVERSIONS is not set
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_MODULE_SIG=y
# CONFIG_MODULE_SIG_FORCE is not set
# CONFIG_MODULE_SIG_ALL is not set
CONFIG_MODULE_SIG_SHA256=y
# CONFIG_MODULE_SIG_SHA384 is not set
# CONFIG_MODULE_SIG_SHA512 is not set
# CONFIG_MODULE_SIG_SHA3_256 is not set
# CONFIG_MODULE_SIG_SHA3_384 is not set
# CONFIG_MODULE_SIG_SHA3_512 is not set
CONFIG_MODULE_SIG_HASH="sha256"
# CONFIG_MODULE_COMPRESS is not set
# CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is not set
CONFIG_MODPROBE_PATH="/sbin/modprobe"
# CONFIG_TRIM_UNUSED_KSYMS is not set
CONFIG_MODULES_TREE_LOOKUP=y
CONFIG_BLOCK=y
CONFIG_BLOCK_LEGACY_AUTOLOAD=y
CONFIG_BLK_RQ_ALLOC_TIME=y
CONFIG_BLK_CGROUP_RWSTAT=y
CONFIG_BLK_CGROUP_PUNT_BIO=y
CONFIG_BLK_DEV_BSG_COMMON=y
CONFIG_BLK_ICQ=y
CONFIG_BLK_DEV_BSGLIB=y
CONFIG_BLK_DEV_INTEGRITY=y
# CONFIG_BLK_DEV_WRITE_MOUNTED is not set
CONFIG_BLK_DEV_ZONED=y
CONFIG_BLK_DEV_THROTTLING=y
CONFIG_BLK_WBT=y
CONFIG_BLK_WBT_MQ=y
CONFIG_BLK_CGROUP_IOLATENCY=y
# CONFIG_BLK_CGROUP_FC_APPID is not set
CONFIG_BLK_CGROUP_IOCOST=y
CONFIG_BLK_CGROUP_IOPRIO=y
CONFIG_BLK_DEBUG_FS=y
# CONFIG_BLK_SED_OPAL is not set
CONFIG_BLK_INLINE_ENCRYPTION=y
CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y

#
# Partition Types
#
CONFIG_PARTITION_ADVANCED=y
CONFIG_ACORN_PARTITION=y
CONFIG_ACORN_PARTITION_CUMANA=y
CONFIG_ACORN_PARTITION_EESOX=y
CONFIG_ACORN_PARTITION_ICS=y
CONFIG_ACORN_PARTITION_ADFS=y
CONFIG_ACORN_PARTITION_POWERTEC=y
CONFIG_ACORN_PARTITION_RISCIX=y
CONFIG_AIX_PARTITION=y
CONFIG_OSF_PARTITION=y
CONFIG_AMIGA_PARTITION=y
CONFIG_ATARI_PARTITION=y
CONFIG_MAC_PARTITION=y
CONFIG_MSDOS_PARTITION=y
CONFIG_BSD_DISKLABEL=y
CONFIG_MINIX_SUBPARTITION=y
CONFIG_SOLARIS_X86_PARTITION=y
CONFIG_UNIXWARE_DISKLABEL=y
CONFIG_LDM_PARTITION=y
# CONFIG_LDM_DEBUG is not set
CONFIG_SGI_PARTITION=y
CONFIG_ULTRIX_PARTITION=y
CONFIG_SUN_PARTITION=y
CONFIG_KARMA_PARTITION=y
CONFIG_EFI_PARTITION=y
CONFIG_SYSV68_PARTITION=y
CONFIG_CMDLINE_PARTITION=y
# CONFIG_OF_PARTITION is not set
# end of Partition Types

CONFIG_BLK_PM=y
CONFIG_BLOCK_HOLDER_DEPRECATED=y
CONFIG_BLK_MQ_STACKING=y
# CONFIG_BLK_ERROR_INJECTION is not set

#
# IO Schedulers
#
CONFIG_MQ_IOSCHED_DEADLINE=y
CONFIG_MQ_IOSCHED_KYBER=y
CONFIG_IOSCHED_BFQ=y
CONFIG_BFQ_GROUP_IOSCHED=y
CONFIG_BFQ_CGROUP_DEBUG=y
# end of IO Schedulers

CONFIG_PREEMPT_NOTIFIERS=y
CONFIG_PADATA=y
CONFIG_ASN1=y
CONFIG_UNINLINE_SPIN_UNLOCK=y
CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
CONFIG_LOCK_SPIN_ON_OWNER=y
CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
CONFIG_QUEUED_SPINLOCKS=y
CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE=y
CONFIG_ARCH_HAS_SYNC_CORE_BEFORE_USERMODE=y
CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y
CONFIG_FREEZER=y

#
# Executable file formats
#
CONFIG_BINFMT_ELF=y
CONFIG_COMPAT_BINFMT_ELF=y
CONFIG_ELFCORE=y
CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
CONFIG_BINFMT_SCRIPT=y
CONFIG_BINFMT_MISC=y
CONFIG_COREDUMP=y
# end of Executable file formats

#
# Memory Management options
#
CONFIG_SWAP=y
CONFIG_ZSWAP=y
CONFIG_ZSWAP_DEFAULT_ON=y
CONFIG_ZSWAP_SHRINKER_DEFAULT_ON=y
# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_DEFLATE is not set
# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZO is not set
CONFIG_ZSWAP_COMPRESSOR_DEFAULT_842=y
# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZ4 is not set
# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZ4HC is not set
# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_ZSTD is not set
CONFIG_ZSWAP_COMPRESSOR_DEFAULT="842"
CONFIG_ZSMALLOC=y

#
# Zsmalloc allocator options
#

#
# Zsmalloc is a common backend allocator for zswap & zram
#
# CONFIG_ZSMALLOC_STAT is not set
CONFIG_ZSMALLOC_CHAIN_SIZE=8
# end of Zsmalloc allocator options

#
# Slab allocator options
#
CONFIG_SLUB=y
CONFIG_KVFREE_RCU_BATCHED=y
# CONFIG_SLUB_TINY is not set
CONFIG_SLAB_MERGE_DEFAULT=y
# CONFIG_SLAB_FREELIST_RANDOM is not set
# CONFIG_SLAB_FREELIST_HARDENED is not set
# CONFIG_SLAB_BUCKETS is not set
# CONFIG_SLUB_STATS is not set
# CONFIG_KMALLOC_PARTITION_CACHES is not set
# end of Slab allocator options

# CONFIG_SHUFFLE_PAGE_ALLOCATOR is not set
# CONFIG_COMPAT_BRK is not set
CONFIG_SPARSEMEM=y
CONFIG_SPARSEMEM_EXTREME=y
CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
CONFIG_SPARSEMEM_VMEMMAP=y
CONFIG_SPARSEMEM_VMEMMAP_PREINIT=y
CONFIG_ARCH_WANT_OPTIMIZE_DAX_VMEMMAP=y
CONFIG_ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP=y
CONFIG_ARCH_WANT_HUGETLB_VMEMMAP_PREINIT=y
CONFIG_HAVE_GUP_FAST=y
CONFIG_NUMA_KEEP_MEMINFO=y
CONFIG_MEMORY_ISOLATION=y
CONFIG_EXCLUSIVE_SYSTEM_RAM=y
CONFIG_HAVE_BOOTMEM_INFO_NODE=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_MEMORY_HOTPLUG=y
# CONFIG_MHP_DEFAULT_ONLINE_TYPE_OFFLINE is not set
CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_AUTO=y
# CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_KERNEL is not set
# CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_MOVABLE is not set
CONFIG_MEMORY_HOTREMOVE=y
CONFIG_MHP_MEMMAP_ON_MEMORY=y
CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y
CONFIG_SPLIT_PTE_PTLOCKS=y
CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y
CONFIG_SPLIT_PMD_PTLOCKS=y
CONFIG_BALLOON=y
# CONFIG_BALLOON_MIGRATION is not set
CONFIG_COMPACTION=y
CONFIG_COMPACT_UNEVICTABLE_DEFAULT=0
CONFIG_PAGE_REPORTING=y
CONFIG_NUMA_MIGRATION=y
CONFIG_MIGRATION=y
CONFIG_DEVICE_MIGRATION=y
CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION=y
CONFIG_CONTIG_ALLOC=y
CONFIG_PCP_BATCH_SCALE_MAX=5
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_MMU_NOTIFIER=y
CONFIG_KSM=y
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
# CONFIG_MEMORY_FAILURE is not set
CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
CONFIG_ARCH_WANTS_THP_SWAP=y
CONFIG_PAGE_MAPCOUNT=y
CONFIG_PGTABLE_HAS_HUGE_LEAVES=y
CONFIG_HAVE_GIGANTIC_FOLIOS=y
CONFIG_ASYNC_KERNEL_PGTABLE_FREE=y
CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
CONFIG_USE_PERCPU_NUMA_NODE_ID=y
CONFIG_HAVE_SETUP_PER_CPU_AREA=y
CONFIG_CMA=y
# CONFIG_CMA_DEBUGFS is not set
# CONFIG_CMA_SYSFS is not set
CONFIG_CMA_AREAS=20
CONFIG_PAGE_BLOCK_MAX_ORDER=10
CONFIG_MEM_SOFT_DIRTY=y
CONFIG_GENERIC_EARLY_IOREMAP=y
# CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set
CONFIG_PAGE_IDLE_FLAG=y
# CONFIG_IDLE_PAGE_TRACKING is not set
CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
CONFIG_ARCH_HAS_CURRENT_STACK_POINTER=y
CONFIG_ARCH_HAS_ZONE_DMA_SET=y
CONFIG_ZONE_DMA=y
CONFIG_ZONE_DMA32=y
CONFIG_ZONE_DEVICE=y
CONFIG_HMM_MIRROR=y
CONFIG_GET_FREE_REGION=y
CONFIG_DEVICE_PRIVATE=y
CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y
CONFIG_ARCH_HAS_PKEYS=y
CONFIG_ARCH_USES_PG_ARCH_2=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_PERCPU_STATS=y
# CONFIG_GUP_TEST is not set
# CONFIG_DMAPOOL_TEST is not set
CONFIG_ARCH_HAS_PTE_SPECIAL=y
CONFIG_MAPPING_DIRTY_HELPERS=y
CONFIG_KMAP_LOCAL=y
CONFIG_MEMFD_CREATE=y
CONFIG_SECRETMEM=y
CONFIG_ANON_VMA_NAME=y
CONFIG_HAVE_ARCH_USERFAULTFD_WP=y
CONFIG_HAVE_ARCH_USERFAULTFD_MINOR=y
CONFIG_USERFAULTFD=y
# CONFIG_PTE_MARKER_UFFD_WP is not set
# CONFIG_LRU_GEN is not set
CONFIG_ARCH_SUPPORTS_PER_VMA_LOCK=y
CONFIG_PER_VMA_LOCK=y
CONFIG_LOCK_MM_AND_FIND_VMA=y
CONFIG_IOMMU_MM_DATA=y
CONFIG_EXECMEM=y
CONFIG_NUMA_MEMBLKS=y
CONFIG_NUMA_EMU=y
CONFIG_ARCH_HAS_USER_SHADOW_STACK=y
CONFIG_PT_RECLAIM=y

#
# Data Access Monitoring
#
CONFIG_DAMON=y
# CONFIG_DAMON_DEBUG_SANITY is not set
CONFIG_DAMON_VADDR=y
CONFIG_DAMON_PADDR=y
# CONFIG_DAMON_SYSFS is not set
CONFIG_DAMON_RECLAIM=y
# CONFIG_DAMON_LRU_SORT is not set
# CONFIG_DAMON_STAT is not set
# end of Data Access Monitoring
# end of Memory Management options

CONFIG_NET=y
CONFIG_WANT_COMPAT_NETLINK_MESSAGES=y
CONFIG_COMPAT_NETLINK_MESSAGES=y
CONFIG_NET_INGRESS=y
CONFIG_NET_EGRESS=y
CONFIG_NET_XGRESS=y
CONFIG_NET_REDIRECT=y
CONFIG_SKB_DECRYPTED=y
CONFIG_SKB_EXTENSIONS=y
CONFIG_NET_DEVMEM=y
CONFIG_NET_SHAPER=y
CONFIG_NET_CRC32C=y

#
# Networking options
#
CONFIG_PACKET=y
CONFIG_PACKET_DIAG=y
CONFIG_INET_PSP=y
CONFIG_UNIX=y
CONFIG_AF_UNIX_OOB=y
CONFIG_UNIX_DIAG=y
CONFIG_TLS=y
CONFIG_TLS_DEVICE=y
CONFIG_XFRM=y
CONFIG_XFRM_OFFLOAD=y
CONFIG_XFRM_ALGO=y
CONFIG_XFRM_USER=y
CONFIG_XFRM_USER_COMPAT=y
CONFIG_XFRM_INTERFACE=y
CONFIG_XFRM_SUB_POLICY=y
CONFIG_XFRM_MIGRATE=y
CONFIG_XFRM_STATISTICS=y
CONFIG_XFRM_AH=y
CONFIG_XFRM_ESP=y
CONFIG_XFRM_IPCOMP=y
CONFIG_NET_KEY=y
CONFIG_NET_KEY_MIGRATE=y
# CONFIG_XFRM_IPTFS is not set
CONFIG_XFRM_ESPINTCP=y
CONFIG_SMC=y
CONFIG_SMC_DIAG=y
# CONFIG_SMC_HS_CTRL_BPF is not set
CONFIG_DIBS=y
CONFIG_DIBS_LO=y
CONFIG_XDP_SOCKETS=y
CONFIG_XDP_SOCKETS_DIAG=y
CONFIG_NET_HANDSHAKE=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_FIB_TRIE_STATS=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_ROUTE_MULTIPATH=y
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_ROUTE_CLASSID=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y
CONFIG_NET_IPIP=y
CONFIG_NET_IPGRE_DEMUX=y
CONFIG_NET_IP_TUNNEL=y
CONFIG_NET_IPGRE=y
CONFIG_NET_IPGRE_BROADCAST=y
CONFIG_IP_MROUTE_COMMON=y
CONFIG_IP_MROUTE=y
CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
CONFIG_IP_PIMSM_V1=y
CONFIG_IP_PIMSM_V2=y
CONFIG_SYN_COOKIES=y
CONFIG_NET_IPVTI=y
CONFIG_NET_UDP_TUNNEL=y
CONFIG_NET_FOU=y
CONFIG_NET_FOU_IP_TUNNELS=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
CONFIG_INET_ESP_OFFLOAD=y
CONFIG_INET_ESPINTCP=y
CONFIG_INET_IPCOMP=y
CONFIG_INET_TABLE_PERTURB_ORDER=16
CONFIG_INET_XFRM_TUNNEL=y
CONFIG_INET_TUNNEL=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
CONFIG_INET_UDP_DIAG=y
CONFIG_INET_RAW_DIAG=y
CONFIG_INET_DIAG_DESTROY=y
CONFIG_TCP_CONG_ADVANCED=y
CONFIG_TCP_CONG_BIC=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_TCP_CONG_WESTWOOD=y
CONFIG_TCP_CONG_HTCP=y
CONFIG_TCP_CONG_HSTCP=y
CONFIG_TCP_CONG_HYBLA=y
CONFIG_TCP_CONG_VEGAS=y
CONFIG_TCP_CONG_NV=y
CONFIG_TCP_CONG_SCALABLE=y
CONFIG_TCP_CONG_LP=y
CONFIG_TCP_CONG_VENO=y
CONFIG_TCP_CONG_YEAH=y
CONFIG_TCP_CONG_ILLINOIS=y
CONFIG_TCP_CONG_DCTCP=y
CONFIG_TCP_CONG_CDG=y
CONFIG_TCP_CONG_BBR=y
# CONFIG_DEFAULT_BIC is not set
CONFIG_DEFAULT_CUBIC=y
# CONFIG_DEFAULT_HTCP is not set
# CONFIG_DEFAULT_HYBLA is not set
# CONFIG_DEFAULT_VEGAS is not set
# CONFIG_DEFAULT_VENO is not set
# CONFIG_DEFAULT_WESTWOOD is not set
# CONFIG_DEFAULT_DCTCP is not set
# CONFIG_DEFAULT_CDG is not set
# CONFIG_DEFAULT_BBR is not set
# CONFIG_DEFAULT_RENO is not set
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_AO is not set
CONFIG_TCP_MD5SIG=y
CONFIG_IPV6=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
CONFIG_IPV6_OPTIMISTIC_DAD=y
CONFIG_INET6_AH=y
CONFIG_INET6_ESP=y
CONFIG_INET6_ESP_OFFLOAD=y
CONFIG_INET6_ESPINTCP=y
CONFIG_INET6_IPCOMP=y
CONFIG_IPV6_MIP6=y
CONFIG_IPV6_ILA=y
CONFIG_INET6_XFRM_TUNNEL=y
CONFIG_INET6_TUNNEL=y
CONFIG_IPV6_VTI=y
CONFIG_IPV6_SIT=y
CONFIG_IPV6_SIT_6RD=y
CONFIG_IPV6_NDISC_NODETYPE=y
CONFIG_IPV6_TUNNEL=y
CONFIG_IPV6_GRE=y
CONFIG_IPV6_FOU=y
CONFIG_IPV6_FOU_TUNNEL=y
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_IPV6_SUBTREES=y
CONFIG_IPV6_MROUTE=y
CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
CONFIG_IPV6_PIMSM_V2=y
CONFIG_IPV6_SEG6_LWTUNNEL=y
CONFIG_IPV6_SEG6_HMAC=y
CONFIG_IPV6_SEG6_BPF=y
CONFIG_IPV6_RPL_LWTUNNEL=y
# CONFIG_IPV6_IOAM6_LWTUNNEL is not set
CONFIG_NETLABEL=y
CONFIG_MPTCP=y
CONFIG_INET_MPTCP_DIAG=y
CONFIG_MPTCP_IPV6=y
CONFIG_NETWORK_SECMARK=y
CONFIG_NET_PTP_CLASSIFY=y
# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
CONFIG_NETFILTER=y
CONFIG_NETFILTER_ADVANCED=y
CONFIG_BRIDGE_NETFILTER=y

#
# Core Netfilter Configuration
#
CONFIG_NETFILTER_INGRESS=y
CONFIG_NETFILTER_EGRESS=y
CONFIG_NETFILTER_SKIP_EGRESS=y
CONFIG_NETFILTER_NETLINK=y
CONFIG_NETFILTER_FAMILY_BRIDGE=y
CONFIG_NETFILTER_FAMILY_ARP=y
CONFIG_NETFILTER_BPF_LINK=y
# CONFIG_NETFILTER_NETLINK_HOOK is not set
CONFIG_NETFILTER_NETLINK_ACCT=y
CONFIG_NETFILTER_NETLINK_QUEUE=y
CONFIG_NETFILTER_NETLINK_LOG=y
CONFIG_NETFILTER_NETLINK_OSF=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_LOG_SYSLOG=y
CONFIG_NETFILTER_CONNCOUNT=y
CONFIG_NF_CONNTRACK_MARK=y
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_ZONES=y
# CONFIG_NF_CONNTRACK_PROCFS is not set
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CONNTRACK_TIMEOUT=y
CONFIG_NF_CONNTRACK_TIMESTAMP=y
CONFIG_NF_CONNTRACK_LABELS=y
CONFIG_NF_CONNTRACK_OVS=y
CONFIG_NF_CT_PROTO_GRE=y
CONFIG_NF_CT_PROTO_SCTP=y
CONFIG_NF_CONNTRACK_AMANDA=y
CONFIG_NF_CONNTRACK_FTP=y
CONFIG_NF_CONNTRACK_H323=y
CONFIG_NF_CONNTRACK_IRC=y
CONFIG_NF_CONNTRACK_BROADCAST=y
CONFIG_NF_CONNTRACK_NETBIOS_NS=y
CONFIG_NF_CONNTRACK_SNMP=y
CONFIG_NF_CONNTRACK_PPTP=y
CONFIG_NF_CONNTRACK_SANE=y
CONFIG_NF_CONNTRACK_SIP=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
CONFIG_NF_CT_NETLINK_TIMEOUT=y
CONFIG_NF_CT_NETLINK_HELPER=y
CONFIG_NETFILTER_NETLINK_GLUE_CT=y
CONFIG_NF_NAT=y
CONFIG_NF_NAT_AMANDA=y
CONFIG_NF_NAT_FTP=y
CONFIG_NF_NAT_IRC=y
CONFIG_NF_NAT_SIP=y
CONFIG_NF_NAT_TFTP=y
CONFIG_NF_NAT_REDIRECT=y
CONFIG_NF_NAT_MASQUERADE=y
CONFIG_NF_NAT_OVS=y
CONFIG_NETFILTER_SYNPROXY=y
CONFIG_NF_TABLES=y
CONFIG_NF_TABLES_INET=y
CONFIG_NF_TABLES_NETDEV=y
CONFIG_NFT_NUMGEN=y
CONFIG_NFT_CT=y
CONFIG_NFT_EXTHDR_DCCP=y
CONFIG_NFT_FLOW_OFFLOAD=y
CONFIG_NFT_CONNLIMIT=y
CONFIG_NFT_LOG=y
CONFIG_NFT_LIMIT=y
CONFIG_NFT_MASQ=y
CONFIG_NFT_REDIR=y
CONFIG_NFT_NAT=y
CONFIG_NFT_TUNNEL=y
CONFIG_NFT_QUEUE=y
CONFIG_NFT_QUOTA=y
CONFIG_NFT_REJECT=y
CONFIG_NFT_REJECT_INET=y
CONFIG_NFT_COMPAT=y
CONFIG_NFT_HASH=y
CONFIG_NFT_FIB=y
CONFIG_NFT_FIB_INET=y
CONFIG_NFT_XFRM=y
CONFIG_NFT_SOCKET=y
CONFIG_NFT_OSF=y
CONFIG_NFT_TPROXY=y
CONFIG_NFT_SYNPROXY=y
CONFIG_NF_DUP_NETDEV=y
CONFIG_NFT_DUP_NETDEV=y
CONFIG_NFT_FWD_NETDEV=y
CONFIG_NFT_FIB_NETDEV=y
CONFIG_NFT_REJECT_NETDEV=y
CONFIG_NF_FLOW_TABLE_INET=y
CONFIG_NF_FLOW_TABLE=y
# CONFIG_NF_FLOW_TABLE_PROCFS is not set
CONFIG_NETFILTER_XTABLES=y
CONFIG_NETFILTER_XTABLES_COMPAT=y

#
# Xtables combined modules
#
CONFIG_NETFILTER_XT_MARK=y
CONFIG_NETFILTER_XT_CONNMARK=y
CONFIG_NETFILTER_XT_SET=y

#
# Xtables targets
#
CONFIG_NETFILTER_XT_TARGET_AUDIT=y
CONFIG_NETFILTER_XT_TARGET_CHECKSUM=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
# CONFIG_NETFILTER_XT_TARGET_CT is not set
CONFIG_NETFILTER_XT_TARGET_DSCP=y
# CONFIG_NETFILTER_XT_TARGET_HL is not set
CONFIG_NETFILTER_XT_TARGET_HMARK=y
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
CONFIG_NETFILTER_XT_TARGET_LED=y
CONFIG_NETFILTER_XT_TARGET_LOG=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_NAT=y
# CONFIG_NETFILTER_XT_TARGET_NETMAP is not set
CONFIG_NETFILTER_XT_TARGET_NFLOG=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
CONFIG_NETFILTER_XT_TARGET_RATEEST=y
# CONFIG_NETFILTER_XT_TARGET_REDIRECT is not set
CONFIG_NETFILTER_XT_TARGET_MASQUERADE=y
CONFIG_NETFILTER_XT_TARGET_TEE=y
CONFIG_NETFILTER_XT_TARGET_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=y

#
# Xtables matches
#
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
CONFIG_NETFILTER_XT_MATCH_BPF=y
CONFIG_NETFILTER_XT_MATCH_CGROUP=y
CONFIG_NETFILTER_XT_MATCH_CLUSTER=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y
CONFIG_NETFILTER_XT_MATCH_CONNLABEL=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
CONFIG_NETFILTER_XT_MATCH_CPU=y
CONFIG_NETFILTER_XT_MATCH_DCCP=y
CONFIG_NETFILTER_XT_MATCH_DEVGROUP=y
CONFIG_NETFILTER_XT_MATCH_DSCP=y
CONFIG_NETFILTER_XT_MATCH_ECN=y
CONFIG_NETFILTER_XT_MATCH_ESP=y
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
CONFIG_NETFILTER_XT_MATCH_HELPER=y
CONFIG_NETFILTER_XT_MATCH_HL=y
CONFIG_NETFILTER_XT_MATCH_IPCOMP=y
CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
CONFIG_NETFILTER_XT_MATCH_IPVS=y
CONFIG_NETFILTER_XT_MATCH_L2TP=y
CONFIG_NETFILTER_XT_MATCH_LENGTH=y
CONFIG_NETFILTER_XT_MATCH_LIMIT=y
CONFIG_NETFILTER_XT_MATCH_MAC=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
CONFIG_NETFILTER_XT_MATCH_NFACCT=y
CONFIG_NETFILTER_XT_MATCH_OSF=y
CONFIG_NETFILTER_XT_MATCH_OWNER=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
CONFIG_NETFILTER_XT_MATCH_RATEEST=y
CONFIG_NETFILTER_XT_MATCH_REALM=y
CONFIG_NETFILTER_XT_MATCH_RECENT=y
CONFIG_NETFILTER_XT_MATCH_SCTP=y
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
CONFIG_NETFILTER_XT_MATCH_STRING=y
CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
CONFIG_NETFILTER_XT_MATCH_TIME=y
CONFIG_NETFILTER_XT_MATCH_U32=y
# end of Core Netfilter Configuration

CONFIG_IP_SET=y
CONFIG_IP_SET_MAX=256
CONFIG_IP_SET_BITMAP_IP=y
CONFIG_IP_SET_BITMAP_IPMAC=y
CONFIG_IP_SET_BITMAP_PORT=y
CONFIG_IP_SET_HASH_IP=y
CONFIG_IP_SET_HASH_IPMARK=y
CONFIG_IP_SET_HASH_IPPORT=y
CONFIG_IP_SET_HASH_IPPORTIP=y
CONFIG_IP_SET_HASH_IPPORTNET=y
CONFIG_IP_SET_HASH_IPMAC=y
CONFIG_IP_SET_HASH_MAC=y
CONFIG_IP_SET_HASH_NETPORTNET=y
CONFIG_IP_SET_HASH_NET=y
CONFIG_IP_SET_HASH_NETNET=y
CONFIG_IP_SET_HASH_NETPORT=y
CONFIG_IP_SET_HASH_NETIFACE=y
CONFIG_IP_SET_LIST_SET=y
CONFIG_IP_VS=y
CONFIG_IP_VS_IPV6=y
# CONFIG_IP_VS_DEBUG is not set
CONFIG_IP_VS_TAB_BITS=12

#
# IPVS transport protocol load balancing support
#
CONFIG_IP_VS_PROTO_TCP=y
CONFIG_IP_VS_PROTO_UDP=y
CONFIG_IP_VS_PROTO_AH_ESP=y
CONFIG_IP_VS_PROTO_ESP=y
CONFIG_IP_VS_PROTO_AH=y
CONFIG_IP_VS_PROTO_SCTP=y

#
# IPVS scheduler
#
CONFIG_IP_VS_RR=y
CONFIG_IP_VS_WRR=y
CONFIG_IP_VS_LC=y
CONFIG_IP_VS_WLC=y
CONFIG_IP_VS_FO=y
CONFIG_IP_VS_OVF=y
CONFIG_IP_VS_LBLC=y
CONFIG_IP_VS_LBLCR=y
CONFIG_IP_VS_DH=y
CONFIG_IP_VS_SH=y
CONFIG_IP_VS_MH=y
CONFIG_IP_VS_SED=y
CONFIG_IP_VS_NQ=y
CONFIG_IP_VS_TWOS=y

#
# IPVS SH scheduler
#
CONFIG_IP_VS_SH_TAB_BITS=8

#
# IPVS MH scheduler
#
CONFIG_IP_VS_MH_TAB_INDEX=12

#
# IPVS application helper
#
CONFIG_IP_VS_FTP=y
CONFIG_IP_VS_NFCT=y
CONFIG_IP_VS_PE_SIP=y

#
# IP: Netfilter Configuration
#
CONFIG_NF_DEFRAG_IPV4=y
CONFIG_NF_SOCKET_IPV4=y
CONFIG_NF_TPROXY_IPV4=y
CONFIG_NF_TABLES_IPV4=y
CONFIG_NFT_REJECT_IPV4=y
CONFIG_NFT_DUP_IPV4=y
CONFIG_NFT_FIB_IPV4=y
CONFIG_NF_TABLES_ARP=y
CONFIG_NF_DUP_IPV4=y
CONFIG_NF_LOG_ARP=y
CONFIG_NF_LOG_IPV4=y
CONFIG_NF_REJECT_IPV4=y
CONFIG_NF_NAT_SNMP_BASIC=y
CONFIG_NF_NAT_PPTP=y
CONFIG_NF_NAT_H323=y
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_MATCH_AH=y
CONFIG_IP_NF_MATCH_ECN=y
CONFIG_IP_NF_MATCH_RPFILTER=y
CONFIG_IP_NF_MATCH_TTL=y
CONFIG_IP_NF_TARGET_REJECT=y
CONFIG_IP_NF_TARGET_SYNPROXY=y
CONFIG_IP_NF_TARGET_ECN=y
CONFIG_NFT_COMPAT_ARP=y
CONFIG_IP_NF_ARP_MANGLE=y
# end of IP: Netfilter Configuration

#
# IPv6: Netfilter Configuration
#
CONFIG_NF_SOCKET_IPV6=y
CONFIG_NF_TPROXY_IPV6=y
CONFIG_NF_TABLES_IPV6=y
CONFIG_NFT_REJECT_IPV6=y
CONFIG_NFT_DUP_IPV6=y
CONFIG_NFT_FIB_IPV6=y
CONFIG_NF_DUP_IPV6=y
CONFIG_NF_REJECT_IPV6=y
CONFIG_NF_LOG_IPV6=y
CONFIG_IP6_NF_IPTABLES=y
CONFIG_IP6_NF_MATCH_AH=y
CONFIG_IP6_NF_MATCH_EUI64=y
CONFIG_IP6_NF_MATCH_FRAG=y
CONFIG_IP6_NF_MATCH_OPTS=y
CONFIG_IP6_NF_MATCH_HL=y
CONFIG_IP6_NF_MATCH_IPV6HEADER=y
CONFIG_IP6_NF_MATCH_MH=y
CONFIG_IP6_NF_MATCH_RPFILTER=y
CONFIG_IP6_NF_MATCH_RT=y
CONFIG_IP6_NF_MATCH_SRH=y
CONFIG_IP6_NF_TARGET_REJECT=y
CONFIG_IP6_NF_TARGET_SYNPROXY=y
CONFIG_IP6_NF_TARGET_NPT=y
# end of IPv6: Netfilter Configuration

CONFIG_NF_DEFRAG_IPV6=y
CONFIG_NF_TABLES_BRIDGE=y
CONFIG_NFT_BRIDGE_META=y
CONFIG_NFT_BRIDGE_REJECT=y
CONFIG_NF_CONNTRACK_BRIDGE=y
CONFIG_BRIDGE_NF_EBTABLES=y
CONFIG_BRIDGE_EBT_802_3=y
CONFIG_BRIDGE_EBT_AMONG=y
CONFIG_BRIDGE_EBT_ARP=y
CONFIG_BRIDGE_EBT_IP=y
CONFIG_BRIDGE_EBT_IP6=y
CONFIG_BRIDGE_EBT_LIMIT=y
CONFIG_BRIDGE_EBT_MARK=y
CONFIG_BRIDGE_EBT_PKTTYPE=y
CONFIG_BRIDGE_EBT_STP=y
CONFIG_BRIDGE_EBT_VLAN=y
CONFIG_BRIDGE_EBT_ARPREPLY=y
CONFIG_BRIDGE_EBT_DNAT=y
CONFIG_BRIDGE_EBT_MARK_T=y
CONFIG_BRIDGE_EBT_REDIRECT=y
CONFIG_BRIDGE_EBT_SNAT=y
CONFIG_BRIDGE_EBT_LOG=y
CONFIG_BRIDGE_EBT_NFLOG=y
CONFIG_IP_SCTP=y
# CONFIG_SCTP_DBG_OBJCNT is not set
CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA256=y
# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set
CONFIG_INET_SCTP_DIAG=y
CONFIG_RDS=y
CONFIG_RDS_RDMA=y
CONFIG_RDS_TCP=y
# CONFIG_RDS_DEBUG is not set
CONFIG_TIPC=y
CONFIG_TIPC_MEDIA_IB=y
CONFIG_TIPC_MEDIA_UDP=y
CONFIG_TIPC_CRYPTO=y
CONFIG_TIPC_DIAG=y
CONFIG_ATM=y
CONFIG_ATM_BR2684=y
# CONFIG_ATM_BR2684_IPFILTER is not set
CONFIG_L2TP=y
# CONFIG_L2TP_DEBUGFS is not set
CONFIG_L2TP_V3=y
CONFIG_L2TP_IP=y
CONFIG_L2TP_ETH=y
CONFIG_STP=y
CONFIG_GARP=y
CONFIG_MRP=y
CONFIG_BRIDGE=y
CONFIG_BRIDGE_IGMP_SNOOPING=y
CONFIG_BRIDGE_VLAN_FILTERING=y
CONFIG_BRIDGE_MRP=y
CONFIG_BRIDGE_CFM=y
CONFIG_NET_DSA=y
# CONFIG_NET_DSA_TAG_NONE is not set
# CONFIG_NET_DSA_TAG_AR9331 is not set
CONFIG_NET_DSA_TAG_BRCM_COMMON=y
CONFIG_NET_DSA_TAG_BRCM=y
# CONFIG_NET_DSA_TAG_BRCM_LEGACY is not set
# CONFIG_NET_DSA_TAG_BRCM_LEGACY_FCS is not set
CONFIG_NET_DSA_TAG_BRCM_PREPEND=y
# CONFIG_NET_DSA_TAG_HELLCREEK is not set
# CONFIG_NET_DSA_TAG_GSWIP is not set
# CONFIG_NET_DSA_TAG_DSA is not set
# CONFIG_NET_DSA_TAG_EDSA is not set
CONFIG_NET_DSA_TAG_MTK=y
# CONFIG_NET_DSA_TAG_MXL_862XX is not set
# CONFIG_NET_DSA_TAG_MXL_GSW1XX is not set
# CONFIG_NET_DSA_TAG_KSZ is not set
# CONFIG_NET_DSA_TAG_NETC is not set
# CONFIG_NET_DSA_TAG_OCELOT is not set
# CONFIG_NET_DSA_TAG_OCELOT_8021Q is not set
CONFIG_NET_DSA_TAG_QCA=y
CONFIG_NET_DSA_TAG_RTL4_A=y
# CONFIG_NET_DSA_TAG_RTL8_4 is not set
# CONFIG_NET_DSA_TAG_RZN1_A5PSW is not set
# CONFIG_NET_DSA_TAG_LAN9303 is not set
# CONFIG_NET_DSA_TAG_SJA1105 is not set
# CONFIG_NET_DSA_TAG_TRAILER is not set
# CONFIG_NET_DSA_TAG_VSC73XX_8021Q is not set
# CONFIG_NET_DSA_TAG_XRS700X is not set
# CONFIG_NET_DSA_TAG_YT921X is not set
CONFIG_VLAN_8021Q=y
CONFIG_VLAN_8021Q_GVRP=y
CONFIG_VLAN_8021Q_MVRP=y
CONFIG_LLC=y
CONFIG_LLC2=y
CONFIG_X25=y
CONFIG_LAPB=y
CONFIG_PHONET=y
CONFIG_6LOWPAN=y
# CONFIG_6LOWPAN_DEBUGFS is not set
CONFIG_6LOWPAN_NHC=y
CONFIG_6LOWPAN_NHC_DEST=y
CONFIG_6LOWPAN_NHC_FRAGMENT=y
CONFIG_6LOWPAN_NHC_HOP=y
CONFIG_6LOWPAN_NHC_IPV6=y
CONFIG_6LOWPAN_NHC_MOBILITY=y
CONFIG_6LOWPAN_NHC_ROUTING=y
CONFIG_6LOWPAN_NHC_UDP=y
CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=y
CONFIG_6LOWPAN_GHC_UDP=y
CONFIG_6LOWPAN_GHC_ICMPV6=y
CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=y
CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=y
CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=y
CONFIG_IEEE802154=y
CONFIG_IEEE802154_NL802154_EXPERIMENTAL=y
CONFIG_IEEE802154_SOCKET=y
CONFIG_IEEE802154_6LOWPAN=y
CONFIG_MAC802154=y
CONFIG_NET_SCHED=y

#
# Queueing/Scheduling
#
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_HFSC=y
CONFIG_NET_SCH_PRIO=y
CONFIG_NET_SCH_MULTIQ=y
CONFIG_NET_SCH_RED=y
CONFIG_NET_SCH_SFB=y
CONFIG_NET_SCH_SFQ=y
CONFIG_NET_SCH_TEQL=y
CONFIG_NET_SCH_TBF=y
CONFIG_NET_SCH_CBS=y
CONFIG_NET_SCH_ETF=y
CONFIG_NET_SCH_MQPRIO_LIB=y
CONFIG_NET_SCH_TAPRIO=y
CONFIG_NET_SCH_GRED=y
CONFIG_NET_SCH_NETEM=y
CONFIG_NET_SCH_DRR=y
CONFIG_NET_SCH_MQPRIO=y
CONFIG_NET_SCH_SKBPRIO=y
CONFIG_NET_SCH_CHOKE=y
CONFIG_NET_SCH_QFQ=y
CONFIG_NET_SCH_CODEL=y
CONFIG_NET_SCH_FQ_CODEL=y
CONFIG_NET_SCH_CAKE=y
CONFIG_NET_SCH_FQ=y
CONFIG_NET_SCH_HHF=y
CONFIG_NET_SCH_PIE=y
CONFIG_NET_SCH_FQ_PIE=y
CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_SCH_PLUG=y
CONFIG_NET_SCH_ETS=y
# CONFIG_NET_SCH_DUALPI2 is not set
CONFIG_NET_SCH_DEFAULT=y
# CONFIG_DEFAULT_FQ is not set
CONFIG_DEFAULT_CODEL=y
# CONFIG_DEFAULT_FQ_CODEL is not set
# CONFIG_DEFAULT_FQ_PIE is not set
# CONFIG_DEFAULT_SFQ is not set
# CONFIG_DEFAULT_PFIFO_FAST is not set
CONFIG_DEFAULT_NET_SCH="pfifo_fast"

#
# Classification
#
CONFIG_NET_CLS=y
CONFIG_NET_CLS_BASIC=y
CONFIG_NET_CLS_ROUTE4=y
CONFIG_NET_CLS_FW=y
CONFIG_NET_CLS_U32=y
CONFIG_CLS_U32_PERF=y
CONFIG_CLS_U32_MARK=y
CONFIG_NET_CLS_FLOW=y
CONFIG_NET_CLS_CGROUP=y
CONFIG_NET_CLS_BPF=y
CONFIG_NET_CLS_FLOWER=y
CONFIG_NET_CLS_MATCHALL=y
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_STACK=32
CONFIG_NET_EMATCH_CMP=y
CONFIG_NET_EMATCH_NBYTE=y
CONFIG_NET_EMATCH_U32=y
CONFIG_NET_EMATCH_META=y
CONFIG_NET_EMATCH_TEXT=y
CONFIG_NET_EMATCH_CANID=y
CONFIG_NET_EMATCH_IPSET=y
CONFIG_NET_EMATCH_IPT=y
CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=y
CONFIG_NET_ACT_GACT=y
CONFIG_GACT_PROB=y
CONFIG_NET_ACT_MIRRED=y
CONFIG_NET_ACT_SAMPLE=y
CONFIG_NET_ACT_NAT=y
CONFIG_NET_ACT_PEDIT=y
CONFIG_NET_ACT_SIMP=y
CONFIG_NET_ACT_SKBEDIT=y
CONFIG_NET_ACT_CSUM=y
CONFIG_NET_ACT_MPLS=y
CONFIG_NET_ACT_VLAN=y
CONFIG_NET_ACT_BPF=y
CONFIG_NET_ACT_CONNMARK=y
CONFIG_NET_ACT_CTINFO=y
CONFIG_NET_ACT_SKBMOD=y
CONFIG_NET_ACT_IFE=y
CONFIG_NET_ACT_TUNNEL_KEY=y
CONFIG_NET_ACT_CT=y
CONFIG_NET_ACT_GATE=y
CONFIG_NET_IFE_SKBMARK=y
CONFIG_NET_IFE_SKBPRIO=y
CONFIG_NET_IFE_SKBTCINDEX=y
CONFIG_NET_TC_SKB_EXT=y
CONFIG_NET_SCH_FIFO=y
CONFIG_DCB=y
CONFIG_DNS_RESOLVER=y
CONFIG_BATMAN_ADV=y
CONFIG_BATMAN_ADV_BATMAN_V=y
CONFIG_BATMAN_ADV_BLA=y
CONFIG_BATMAN_ADV_DAT=y
CONFIG_BATMAN_ADV_MCAST=y
# CONFIG_BATMAN_ADV_DEBUG is not set
# CONFIG_BATMAN_ADV_TRACING is not set
CONFIG_OPENVSWITCH=y
CONFIG_OPENVSWITCH_GRE=y
CONFIG_OPENVSWITCH_VXLAN=y
CONFIG_OPENVSWITCH_GENEVE=y
CONFIG_VSOCKETS=y
CONFIG_VSOCKETS_DIAG=y
CONFIG_VSOCKETS_LOOPBACK=y
# CONFIG_VMWARE_VMCI_VSOCKETS is not set
CONFIG_VIRTIO_VSOCKETS=y
CONFIG_VIRTIO_VSOCKETS_COMMON=y
CONFIG_NETLINK_DIAG=y
CONFIG_MPLS=y
CONFIG_NET_MPLS_GSO=y
CONFIG_MPLS_ROUTING=y
CONFIG_MPLS_IPTUNNEL=y
CONFIG_NET_NSH=y
CONFIG_HSR=y
CONFIG_NET_SWITCHDEV=y
CONFIG_NET_L3_MASTER_DEV=y
CONFIG_QRTR=y
CONFIG_QRTR_TUN=y
# CONFIG_QRTR_MHI is not set
CONFIG_NET_NCSI=y
# CONFIG_NCSI_OEM_CMD_GET_MAC is not set
# CONFIG_NCSI_OEM_CMD_KEEP_PHY is not set
# CONFIG_PCPU_DEV_REFCNT is not set
CONFIG_MAX_SKB_FRAGS=17
CONFIG_RPS=y
CONFIG_RFS_ACCEL=y
CONFIG_SOCK_RX_QUEUE_MAPPING=y
CONFIG_XPS=y
CONFIG_CGROUP_NET_PRIO=y
CONFIG_CGROUP_NET_CLASSID=y
CONFIG_BQL=y
CONFIG_NET_FLOW_LIMIT=y

#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
CONFIG_NET_DROP_MONITOR=y
# end of Network testing
# end of Networking options

CONFIG_CAN=y
CONFIG_CAN_RAW=y
CONFIG_CAN_BCM=y
CONFIG_CAN_GW=y
CONFIG_CAN_J1939=y
CONFIG_CAN_ISOTP=y
CONFIG_BT=y
CONFIG_BT_BREDR=y
CONFIG_BT_RFCOMM=y
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_BNEP=y
CONFIG_BT_BNEP_MC_FILTER=y
CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_HIDP=y
CONFIG_BT_LE=y
CONFIG_BT_LE_L2CAP_ECRED=y
CONFIG_BT_6LOWPAN=y
CONFIG_BT_LEDS=y
CONFIG_BT_MSFTEXT=y
# CONFIG_BT_AOSPEXT is not set
# CONFIG_BT_DEBUGFS is not set
# CONFIG_BT_SELFTEST is not set

#
# Bluetooth device drivers
#
CONFIG_BT_INTEL=y
CONFIG_BT_BCM=y
CONFIG_BT_RTL=y
CONFIG_BT_QCA=y
CONFIG_BT_MTK=y
CONFIG_BT_HCIBTUSB=y
CONFIG_BT_HCIBTUSB_AUTOSUSPEND=y
CONFIG_BT_HCIBTUSB_POLL_SYNC=y
CONFIG_BT_HCIBTUSB_BCM=y
CONFIG_BT_HCIBTUSB_MTK=y
CONFIG_BT_HCIBTUSB_RTL=y
# CONFIG_BT_HCIBTSDIO is not set
CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_SERDEV=y
CONFIG_BT_HCIUART_H4=y
# CONFIG_BT_HCIUART_NOKIA is not set
CONFIG_BT_HCIUART_BCSP=y
# CONFIG_BT_HCIUART_ATH3K is not set
CONFIG_BT_HCIUART_LL=y
CONFIG_BT_HCIUART_3WIRE=y
# CONFIG_BT_HCIUART_INTEL is not set
# CONFIG_BT_HCIUART_BCM is not set
# CONFIG_BT_HCIUART_RTL is not set
CONFIG_BT_HCIUART_QCA=y
CONFIG_BT_HCIUART_AG6XX=y
CONFIG_BT_HCIUART_MRVL=y
# CONFIG_BT_HCIUART_AML is not set
CONFIG_BT_HCIBCM203X=y
# CONFIG_BT_HCIBCM4377 is not set
CONFIG_BT_HCIBPA10X=y
CONFIG_BT_HCIBFUSB=y
CONFIG_BT_HCIVHCI=y
CONFIG_BT_MRVL=y
CONFIG_BT_MRVL_SDIO=y
CONFIG_BT_ATH3K=y
CONFIG_BT_MTKSDIO=y
CONFIG_BT_MTKUART=y
# CONFIG_BT_VIRTIO is not set
# CONFIG_BT_NXPUART is not set
# CONFIG_BT_INTEL_PCIE is not set
# end of Bluetooth device drivers

CONFIG_AF_RXRPC=y
CONFIG_AF_RXRPC_IPV6=y
# CONFIG_AF_RXRPC_INJECT_LOSS is not set
# CONFIG_AF_RXRPC_INJECT_RX_DELAY is not set
# CONFIG_AF_RXRPC_DEBUG is not set
CONFIG_RXKAD=y
# CONFIG_RXGK is not set
# CONFIG_RXPERF is not set
CONFIG_AF_KCM=y
CONFIG_STREAM_PARSER=y
CONFIG_MCTP=y
CONFIG_FIB_RULES=y
CONFIG_WIRELESS=y
CONFIG_WEXT_CORE=y
CONFIG_WEXT_PROC=y
CONFIG_CFG80211=y
# CONFIG_NL80211_TESTMODE is not set
# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y
CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y
CONFIG_CFG80211_DEFAULT_PS=y
CONFIG_CFG80211_DEBUGFS=y
CONFIG_CFG80211_CRDA_SUPPORT=y
CONFIG_CFG80211_WEXT=y
CONFIG_MAC80211=y
CONFIG_MAC80211_HAS_RC=y
CONFIG_MAC80211_RC_MINSTREL=y
CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
CONFIG_MAC80211_MESH=y
CONFIG_MAC80211_LEDS=y
CONFIG_MAC80211_DEBUGFS=y
# CONFIG_MAC80211_MESSAGE_TRACING is not set
# CONFIG_MAC80211_DEBUG_MENU is not set
CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
CONFIG_RFKILL=y
CONFIG_RFKILL_LEDS=y
CONFIG_RFKILL_INPUT=y
# CONFIG_RFKILL_GPIO is not set
CONFIG_NET_9P=y
CONFIG_NET_9P_FD=y
CONFIG_NET_9P_VIRTIO=y
# CONFIG_NET_9P_USBG is not set
CONFIG_NET_9P_RDMA=y
# CONFIG_NET_9P_DEBUG is not set
CONFIG_CEPH_LIB=y
# CONFIG_CEPH_LIB_PRETTYDEBUG is not set
CONFIG_CEPH_LIB_USE_DNS_RESOLVER=y
CONFIG_NFC=y
CONFIG_NFC_DIGITAL=y
CONFIG_NFC_NCI=y
# CONFIG_NFC_NCI_SPI is not set
CONFIG_NFC_NCI_UART=y
CONFIG_NFC_HCI=y
CONFIG_NFC_SHDLC=y

#
# Near Field Communication (NFC) devices
#
# CONFIG_NFC_TRF7970A is not set
# CONFIG_NFC_MEI_PHY is not set
CONFIG_NFC_SIM=y
CONFIG_NFC_PORT100=y
CONFIG_NFC_VIRTUAL_NCI=y
CONFIG_NFC_FDP=y
# CONFIG_NFC_FDP_I2C is not set
# CONFIG_NFC_PN544_I2C is not set
CONFIG_NFC_PN533=y
CONFIG_NFC_PN533_USB=y
# CONFIG_NFC_PN533_I2C is not set
# CONFIG_NFC_PN532_UART is not set
# CONFIG_NFC_MICROREAD_I2C is not set
CONFIG_NFC_MRVL=y
CONFIG_NFC_MRVL_USB=y
# CONFIG_NFC_MRVL_UART is not set
# CONFIG_NFC_MRVL_I2C is not set
# CONFIG_NFC_ST21NFCA_I2C is not set
# CONFIG_NFC_ST_NCI_I2C is not set
# CONFIG_NFC_ST_NCI_SPI is not set
# CONFIG_NFC_NXP_NCI is not set
# CONFIG_NFC_S3FWRN5_I2C is not set
# CONFIG_NFC_S3FWRN82_UART is not set
# CONFIG_NFC_ST95HF is not set
# end of Near Field Communication (NFC) devices

CONFIG_PSAMPLE=y
CONFIG_NET_IFE=y
CONFIG_LWTUNNEL=y
CONFIG_LWTUNNEL_BPF=y
CONFIG_DST_CACHE=y
CONFIG_GRO_CELLS=y
CONFIG_SOCK_VALIDATE_XMIT=y
CONFIG_NET_SELFTESTS=y
CONFIG_NET_SOCK_MSG=y
CONFIG_NET_DEVLINK=y
CONFIG_PAGE_POOL=y
# CONFIG_PAGE_POOL_STATS is not set
CONFIG_FAILOVER=y
CONFIG_ETHTOOL_NETLINK=y

#
# Device Drivers
#
CONFIG_HAVE_PCI=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCIEPORTBUS=y
CONFIG_HOTPLUG_PCI_PCIE=y
CONFIG_PCIEAER=y
# CONFIG_PCIEAER_INJECT is not set
# CONFIG_PCIE_ECRC is not set
CONFIG_PCIEASPM=y
CONFIG_PCIEASPM_DEFAULT=y
# CONFIG_PCIEASPM_POWERSAVE is not set
# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set
# CONFIG_PCIEASPM_PERFORMANCE is not set
CONFIG_PCIE_PME=y
# CONFIG_PCIE_DPC is not set
# CONFIG_PCIE_PTM is not set
CONFIG_PCI_MSI=y
CONFIG_PCI_QUIRKS=y
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set
# CONFIG_PCI_STUB is not set
# CONFIG_PCI_PF_STUB is not set
CONFIG_PCI_ATS=y
# CONFIG_PCI_TSM is not set
# CONFIG_PCI_DOE is not set
CONFIG_PCI_ECAM=y
CONFIG_PCI_LOCKLESS_CONFIG=y
CONFIG_PCI_IOV=y
# CONFIG_PCI_NPEM is not set
CONFIG_PCI_PRI=y
CONFIG_PCI_PASID=y
# CONFIG_PCIE_TPH is not set
# CONFIG_PCI_P2PDMA is not set
CONFIG_PCI_LABEL=y
# CONFIG_PCI_DYNAMIC_OF_NODES is not set
CONFIG_VGA_ARB=y
CONFIG_VGA_ARB_MAX_GPUS=16
CONFIG_HOTPLUG_PCI=y
# CONFIG_HOTPLUG_PCI_ACPI is not set
# CONFIG_HOTPLUG_PCI_CPCI is not set
# CONFIG_HOTPLUG_PCI_OCTEONEP is not set
# CONFIG_HOTPLUG_PCI_SHPC is not set

#
# PCI controller drivers
#
CONFIG_PCI_HOST_COMMON=y
# CONFIG_PCI_FTPCI100 is not set
CONFIG_PCI_HOST_GENERIC=y
# CONFIG_VMD is not set
# CONFIG_PCIE_XILINX is not set

#
# Cadence-based PCIe controllers
#
# CONFIG_PCIE_CADENCE_PLAT_HOST is not set
# CONFIG_PCIE_CADENCE_PLAT_EP is not set
# end of Cadence-based PCIe controllers

#
# DesignWare-based PCIe controllers
#
# CONFIG_PCI_MESON is not set
# CONFIG_PCIE_INTEL_GW is not set
# CONFIG_PCIE_DW_PLAT_HOST is not set
# CONFIG_PCIE_DW_PLAT_EP is not set
# end of DesignWare-based PCIe controllers

#
# Mobiveil-based PCIe controllers
#
# end of Mobiveil-based PCIe controllers

#
# PLDA-based PCIe controllers
#
# CONFIG_PCIE_MICROCHIP_HOST is not set
# end of PLDA-based PCIe controllers
# end of PCI controller drivers

#
# PCI Endpoint
#
CONFIG_PCI_ENDPOINT=y
# CONFIG_PCI_ENDPOINT_CONFIGFS is not set
# CONFIG_PCI_ENDPOINT_MSI_DOORBELL is not set
# CONFIG_PCI_EPF_TEST is not set
# CONFIG_PCI_EPF_NTB is not set
# end of PCI Endpoint

#
# PCI switch controller drivers
#
# CONFIG_PCI_SW_SWITCHTEC is not set
# end of PCI switch controller drivers

# CONFIG_PCI_PWRCTRL_GENERIC is not set
# CONFIG_PCI_PWRCTRL_TC9563 is not set
# CONFIG_CXL_BUS is not set
CONFIG_PCCARD=y
CONFIG_PCMCIA=y
CONFIG_PCMCIA_LOAD_CIS=y
CONFIG_CARDBUS=y

#
# PC-card bridges
#
CONFIG_YENTA=y
CONFIG_YENTA_O2=y
CONFIG_YENTA_RICOH=y
CONFIG_YENTA_TI=y
CONFIG_YENTA_ENE_TUNE=y
CONFIG_YENTA_TOSHIBA=y
# CONFIG_PD6729 is not set
CONFIG_PCCARD_NONSTATIC=y
# CONFIG_RAPIDIO is not set
# CONFIG_PC104 is not set

#
# Generic Driver Options
#
CONFIG_AUXILIARY_BUS=y
CONFIG_UEVENT_HELPER=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_DEVTMPFS_SAFE is not set
CONFIG_DRIVER_DEFERRED_PROBE_TIMEOUT=10
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y

#
# Firmware loader
#
CONFIG_FW_LOADER=y
# CONFIG_FW_LOADER_DEBUG is not set
CONFIG_FW_LOADER_PAGED_BUF=y
CONFIG_FW_LOADER_SYSFS=y
CONFIG_EXTRA_FIRMWARE=""
CONFIG_FW_LOADER_USER_HELPER=y
CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
CONFIG_FW_LOADER_COMPRESS=y
# CONFIG_FW_LOADER_COMPRESS_XZ is not set
# CONFIG_FW_LOADER_COMPRESS_ZSTD is not set
CONFIG_FW_CACHE=y
# CONFIG_FW_UPLOAD is not set
# end of Firmware loader

CONFIG_WANT_DEV_COREDUMP=y
CONFIG_ALLOW_DEV_COREDUMP=y
CONFIG_DEV_COREDUMP=y
# CONFIG_DEBUG_DRIVER is not set
CONFIG_DEBUG_DEVRES=y
# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set
CONFIG_GENERIC_CPU_DEVICES=y
CONFIG_GENERIC_CPU_AUTOPROBE=y
CONFIG_GENERIC_CPU_VULNERABILITIES=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
CONFIG_DMA_SHARED_BUFFER=y
# CONFIG_DMA_FENCE_TRACE is not set
# CONFIG_FW_DEVLINK_SYNC_STATE_TIMEOUT is not set
# end of Generic Driver Options

#
# Bus devices
#
# CONFIG_MOXTET is not set
CONFIG_MHI_BUS=y
# CONFIG_MHI_BUS_DEBUG is not set
# CONFIG_MHI_BUS_PCI_GENERIC is not set
# CONFIG_MHI_BUS_EP is not set
# end of Bus devices

CONFIG_CONNECTOR=y
CONFIG_PROC_EVENTS=y

#
# Firmware Drivers
#

#
# ARM System Control and Management Interface Protocol
#
# end of ARM System Control and Management Interface Protocol

# CONFIG_EDD is not set
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
# CONFIG_DMI_SYSFS is not set
CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y
# CONFIG_ISCSI_IBFT is not set
# CONFIG_FW_CFG_SYSFS is not set
CONFIG_SYSFB=y
# CONFIG_SYSFB_SIMPLEFB is not set
CONFIG_GOOGLE_FIRMWARE=y
# CONFIG_GOOGLE_SMI is not set
# CONFIG_GOOGLE_CBMEM is not set
CONFIG_GOOGLE_COREBOOT_TABLE=y
CONFIG_GOOGLE_MEMCONSOLE=y
# CONFIG_GOOGLE_MEMCONSOLE_X86_LEGACY is not set
# CONFIG_GOOGLE_FRAMEBUFFER_COREBOOT is not set
CONFIG_GOOGLE_MEMCONSOLE_COREBOOT=y
CONFIG_GOOGLE_VPD=y

#
# Qualcomm firmware drivers
#
# end of Qualcomm firmware drivers

#
# Tegra firmware driver
#
# end of Tegra firmware driver
# end of Firmware Drivers

# CONFIG_FWCTL is not set
CONFIG_GNSS=y
# CONFIG_GNSS_MTK_SERIAL is not set
# CONFIG_GNSS_SIRF_SERIAL is not set
# CONFIG_GNSS_UBX_SERIAL is not set
CONFIG_GNSS_USB=y
CONFIG_MTD=y
# CONFIG_MTD_TESTS is not set

#
# Partition parsers
#
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_OF_PARTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
# end of Partition parsers

#
# User Modules And Translation Layers
#
CONFIG_MTD_BLKDEVS=y
CONFIG_MTD_BLOCK=y

#
# Note that in some cases UBI block is preferred. See MTD_UBI_BLOCK.
#
CONFIG_FTL=y
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set
# CONFIG_SSFDC is not set
# CONFIG_SM_FTL is not set
# CONFIG_MTD_OOPS is not set
# CONFIG_MTD_SWAP is not set
# CONFIG_MTD_PARTITIONED_MASTER is not set

#
# RAM/ROM/Flash chip drivers
#
# CONFIG_MTD_CFI is not set
# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_MAP_BANK_WIDTH_1=y
CONFIG_MTD_MAP_BANK_WIDTH_2=y
CONFIG_MTD_MAP_BANK_WIDTH_4=y
CONFIG_MTD_CFI_I1=y
CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
# end of RAM/ROM/Flash chip drivers

#
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
# CONFIG_MTD_PLATRAM is not set
# end of Mapping drivers for chip access

#
# Self-contained MTD device drivers
#
# CONFIG_MTD_PMC551 is not set
# CONFIG_MTD_DATAFLASH is not set
# CONFIG_MTD_MCHP23K256 is not set
# CONFIG_MTD_MCHP48L640 is not set
# CONFIG_MTD_SST25L is not set
CONFIG_MTD_SLRAM=y
CONFIG_MTD_PHRAM=y
CONFIG_MTD_MTDRAM=y
CONFIG_MTDRAM_TOTAL_SIZE=128
CONFIG_MTDRAM_ERASE_SIZE=4
CONFIG_MTD_BLOCK2MTD=y

#
# Disk-On-Chip Device Drivers
#
# CONFIG_MTD_DOCG3 is not set
# end of Self-contained MTD device drivers

#
# NAND
#
# CONFIG_MTD_ONENAND is not set
# CONFIG_MTD_RAW_NAND is not set
# CONFIG_MTD_SPI_NAND is not set

#
# ECC engine support
#
# CONFIG_MTD_NAND_ECC_SW_HAMMING is not set
# CONFIG_MTD_NAND_ECC_SW_BCH is not set
# CONFIG_MTD_NAND_ECC_MXIC is not set
# end of ECC engine support
# end of NAND

#
# LPDDR & LPDDR2 PCM memory drivers
#
# CONFIG_MTD_LPDDR is not set
# end of LPDDR & LPDDR2 PCM memory drivers

# CONFIG_MTD_SPI_NOR is not set
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_WL_THRESHOLD=4096
CONFIG_MTD_UBI_BEB_LIMIT=20
# CONFIG_MTD_UBI_FASTMAP is not set
# CONFIG_MTD_UBI_GLUEBI is not set
# CONFIG_MTD_UBI_BLOCK is not set
# CONFIG_MTD_UBI_FAULT_INJECTION is not set
# CONFIG_MTD_UBI_NVMEM is not set
# CONFIG_MTD_HYPERBUS is not set
CONFIG_DTC=y
CONFIG_OF=y
# CONFIG_OF_UNITTEST is not set
CONFIG_OF_FLATTREE=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_KOBJ=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_IRQ=y
CONFIG_OF_RESERVED_MEM=y
# CONFIG_OF_OVERLAY is not set
CONFIG_OF_NUMA=y
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
CONFIG_PARPORT=y
# CONFIG_PARPORT_PC is not set
# CONFIG_PARPORT_1284 is not set
CONFIG_PARPORT_NOT_PC=y
CONFIG_PNP=y
CONFIG_PNP_DEBUG_MESSAGES=y

#
# Protocols
#
CONFIG_PNPACPI=y
CONFIG_BLK_DEV=y
CONFIG_BLK_DEV_NULL_BLK=y
CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTION=y
# CONFIG_BLK_DEV_FD is not set
CONFIG_CDROM=y
# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set
CONFIG_ZRAM=y
# CONFIG_ZRAM_BACKEND_LZ4 is not set
# CONFIG_ZRAM_BACKEND_LZ4HC is not set
# CONFIG_ZRAM_BACKEND_ZSTD is not set
# CONFIG_ZRAM_BACKEND_DEFLATE is not set
# CONFIG_ZRAM_BACKEND_842 is not set
CONFIG_ZRAM_BACKEND_FORCE_LZO=y
CONFIG_ZRAM_BACKEND_LZO=y
# CONFIG_ZRAM_DEF_COMP_LZORLE is not set
CONFIG_ZRAM_DEF_COMP_LZO=y
CONFIG_ZRAM_DEF_COMP="lzo"
# CONFIG_ZRAM_WRITEBACK is not set
# CONFIG_ZRAM_TRACK_ENTRY_ACTIME is not set
# CONFIG_ZRAM_MEMORY_TRACKING is not set
# CONFIG_ZRAM_MULTI_COMP is not set
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
# CONFIG_BLK_DEV_DRBD is not set
CONFIG_BLK_DEV_NBD=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_ATA_OVER_ETH=y
CONFIG_VIRTIO_BLK=y
# CONFIG_BLK_DEV_RBD is not set
CONFIG_BLK_DEV_UBLK=y
CONFIG_BLKDEV_UBLK_LEGACY_OPCODES=y
CONFIG_BLK_DEV_RNBD=y
CONFIG_BLK_DEV_RNBD_CLIENT=y
# CONFIG_BLK_DEV_ZONED_LOOP is not set

#
# NVME Support
#
CONFIG_NVME_CORE=y
CONFIG_BLK_DEV_NVME=y
CONFIG_NVME_MULTIPATH=y
# CONFIG_NVME_VERBOSE_ERRORS is not set
# CONFIG_NVME_HWMON is not set
CONFIG_NVME_FABRICS=y
CONFIG_NVME_RDMA=y
CONFIG_NVME_FC=y
CONFIG_NVME_TCP=y
# CONFIG_NVME_TCP_TLS is not set
# CONFIG_NVME_HOST_AUTH is not set
CONFIG_NVME_TARGET=y
# CONFIG_NVME_TARGET_DEBUGFS is not set
# CONFIG_NVME_TARGET_PASSTHRU is not set
CONFIG_NVME_TARGET_LOOP=y
CONFIG_NVME_TARGET_RDMA=y
CONFIG_NVME_TARGET_FC=y
CONFIG_NVME_TARGET_FCLOOP=y
CONFIG_NVME_TARGET_TCP=y
# CONFIG_NVME_TARGET_TCP_TLS is not set
# CONFIG_NVME_TARGET_AUTH is not set
# CONFIG_NVME_TARGET_PCI_EPF is not set
# end of NVME Support

#
# Misc devices
#
# CONFIG_AD525X_DPOT is not set
# CONFIG_DUMMY_IRQ is not set
# CONFIG_IBM_ASM is not set
# CONFIG_PHANTOM is not set
# CONFIG_RPMB is not set
# CONFIG_TI_FPC202 is not set
# CONFIG_TIFM_CORE is not set
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
# CONFIG_APDS9802ALS is not set
# CONFIG_ISL29003 is not set
# CONFIG_ISL29020 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_SENSORS_BH1770 is not set
# CONFIG_HMC6352 is not set
# CONFIG_DS1682 is not set
# CONFIG_VMWARE_BALLOON is not set
# CONFIG_LATTICE_ECP3_CONFIG is not set
# CONFIG_SRAM is not set
# CONFIG_DW_XDATA_PCIE is not set
# CONFIG_PCI_ENDPOINT_TEST is not set
# CONFIG_XILINX_SDFEC is not set
CONFIG_MISC_RTSX=y
# CONFIG_HISI_HIKEY_USB is not set
# CONFIG_OPEN_DICE is not set
# CONFIG_NTSYNC is not set
# CONFIG_VCPU_STALL_DETECTOR is not set
# CONFIG_NSM is not set
# CONFIG_C2PORT is not set

#
# EEPROM support
#
# CONFIG_EEPROM_AT24 is not set
# CONFIG_EEPROM_AT25 is not set
# CONFIG_EEPROM_MAX6875 is not set
CONFIG_EEPROM_93CX6=y
# CONFIG_EEPROM_93XX46 is not set
# CONFIG_EEPROM_IDT_89HPESX is not set
# CONFIG_EEPROM_EE1004 is not set
# CONFIG_EEPROM_M24LR is not set
# end of EEPROM support

# CONFIG_CB710_CORE is not set
# CONFIG_SENSORS_LIS3_I2C is not set
# CONFIG_ALTERA_STAPL is not set
CONFIG_INTEL_MEI=y
CONFIG_INTEL_MEI_ME=y
# CONFIG_INTEL_MEI_TXE is not set
# CONFIG_INTEL_MEI_CSC is not set
# CONFIG_INTEL_MEI_VSC_HW is not set
CONFIG_VMWARE_VMCI=y
# CONFIG_GENWQE is not set
# CONFIG_BCM_VK is not set
# CONFIG_MISC_ALCOR_PCI is not set
# CONFIG_MISC_RTSX_PCI is not set
CONFIG_MISC_RTSX_USB=y
# CONFIG_UACCE is not set
# CONFIG_PVPANIC is not set
# CONFIG_GP_PCI1XXXX is not set
# CONFIG_KEBA_CP500 is not set
# CONFIG_MISC_RP1 is not set
# end of Misc devices

#
# SCSI device support
#
CONFIG_SCSI_MOD=y
CONFIG_RAID_ATTRS=y
CONFIG_SCSI_COMMON=y
CONFIG_SCSI=y
CONFIG_SCSI_DMA=y
CONFIG_SCSI_NETLINK=y
CONFIG_SCSI_PROC_FS=y

#
# SCSI support type (disk, tape, CD-ROM)
#
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_ST=y
CONFIG_BLK_DEV_SR=y
CONFIG_CHR_DEV_SG=y
CONFIG_BLK_DEV_BSG=y
# CONFIG_CHR_DEV_SCH is not set
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SCAN_ASYNC=y

#
# SCSI Transports
#
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_FC_ATTRS=y
CONFIG_SCSI_ISCSI_ATTRS=y
CONFIG_SCSI_SAS_ATTRS=y
CONFIG_SCSI_SAS_LIBSAS=y
CONFIG_SCSI_SAS_ATA=y
# CONFIG_SCSI_SAS_HOST_SMP is not set
CONFIG_SCSI_SRP_ATTRS=y
# end of SCSI Transports

CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_ISCSI_BOOT_SYSFS is not set
# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_SCSI_CXGB4_ISCSI is not set
# CONFIG_SCSI_BNX2_ISCSI is not set
# CONFIG_BE2ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
CONFIG_SCSI_HPSA=y
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_3W_SAS is not set
# CONFIG_SCSI_ACARD is not set
# CONFIG_SCSI_AACRAID is not set
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC79XX is not set
# CONFIG_SCSI_AIC94XX is not set
# CONFIG_SCSI_MVSAS is not set
# CONFIG_SCSI_MVUMI is not set
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_ARCMSR is not set
# CONFIG_SCSI_ESAS2R is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_MPT3SAS is not set
# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_MPI3MR is not set
# CONFIG_SCSI_SMARTPQI is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_MYRB is not set
# CONFIG_SCSI_MYRS is not set
# CONFIG_VMWARE_PVSCSI is not set
# CONFIG_LIBFC is not set
# CONFIG_SCSI_SNIC is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FDOMAIN_PCI is not set
# CONFIG_SCSI_ISCI is not set
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_QLA_ISCSI is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_EFCT is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_AM53C974 is not set
# CONFIG_SCSI_WD719X is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_PMCRAID is not set
# CONFIG_SCSI_PM8001 is not set
# CONFIG_SCSI_BFA_FC is not set
CONFIG_SCSI_VIRTIO=y
# CONFIG_SCSI_CHELSIO_FCOE is not set
# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
# CONFIG_SCSI_DH is not set
# end of SCSI device support

CONFIG_ATA=y
CONFIG_SATA_HOST=y
CONFIG_PATA_TIMINGS=y
CONFIG_ATA_VERBOSE_ERROR=y
CONFIG_ATA_FORCE=y
CONFIG_ATA_ACPI=y
# CONFIG_SATA_ZPODD is not set
CONFIG_SATA_PMP=y

#
# Controllers with non-SFF native interface
#
CONFIG_SATA_AHCI=y
CONFIG_SATA_MOBILE_LPM_POLICY=3
# CONFIG_SATA_AHCI_PLATFORM is not set
# CONFIG_AHCI_DWC is not set
# CONFIG_AHCI_CEVA is not set
# CONFIG_SATA_INIC162X is not set
# CONFIG_SATA_ACARD_AHCI is not set
# CONFIG_SATA_SIL24 is not set
CONFIG_ATA_SFF=y

#
# SFF controllers with custom DMA interface
#
# CONFIG_PDC_ADMA is not set
# CONFIG_SATA_QSTOR is not set
# CONFIG_SATA_SX4 is not set
CONFIG_ATA_BMDMA=y

#
# SATA SFF controllers with BMDMA
#
CONFIG_ATA_PIIX=y
# CONFIG_SATA_DWC is not set
# CONFIG_SATA_MV is not set
# CONFIG_SATA_NV is not set
# CONFIG_SATA_PROMISE is not set
# CONFIG_SATA_SIL is not set
# CONFIG_SATA_SIS is not set
# CONFIG_SATA_SVW is not set
# CONFIG_SATA_ULI is not set
# CONFIG_SATA_VIA is not set
# CONFIG_SATA_VITESSE is not set

#
# PATA SFF controllers with BMDMA
#
# CONFIG_PATA_ALI is not set
CONFIG_PATA_AMD=y
# CONFIG_PATA_ARTOP is not set
# CONFIG_PATA_ATIIXP is not set
# CONFIG_PATA_ATP867X is not set
# CONFIG_PATA_CMD64X is not set
# CONFIG_PATA_CYPRESS is not set
# CONFIG_PATA_EFAR is not set
# CONFIG_PATA_HPT366 is not set
# CONFIG_PATA_HPT37X is not set
# CONFIG_PATA_HPT3X2N is not set
# CONFIG_PATA_HPT3X3 is not set
# CONFIG_PATA_IT8213 is not set
# CONFIG_PATA_IT821X is not set
# CONFIG_PATA_JMICRON is not set
# CONFIG_PATA_MARVELL is not set
# CONFIG_PATA_NETCELL is not set
# CONFIG_PATA_NINJA32 is not set
# CONFIG_PATA_NS87415 is not set
CONFIG_PATA_OLDPIIX=y
# CONFIG_PATA_OPTIDMA is not set
# CONFIG_PATA_PDC2027X is not set
# CONFIG_PATA_PDC_OLD is not set
# CONFIG_PATA_RADISYS is not set
# CONFIG_PATA_RDC is not set
CONFIG_PATA_SCH=y
# CONFIG_PATA_SERVERWORKS is not set
# CONFIG_PATA_SIL680 is not set
# CONFIG_PATA_SIS is not set
# CONFIG_PATA_TOSHIBA is not set
# CONFIG_PATA_TRIFLEX is not set
# CONFIG_PATA_VIA is not set
# CONFIG_PATA_WINBOND is not set

#
# PIO-only SFF controllers
#
# CONFIG_PATA_CMD640_PCI is not set
# CONFIG_PATA_MPIIX is not set
# CONFIG_PATA_NS87410 is not set
# CONFIG_PATA_OPTI is not set
# CONFIG_PATA_PCMCIA is not set
# CONFIG_PATA_OF_PLATFORM is not set
# CONFIG_PATA_RZ1000 is not set

#
# Generic fallback / legacy drivers
#
# CONFIG_PATA_ACPI is not set
CONFIG_ATA_GENERIC=y
# CONFIG_PATA_LEGACY is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=y
CONFIG_MD_BITMAP=y
# CONFIG_MD_LLBITMAP is not set
CONFIG_MD_AUTODETECT=y
CONFIG_MD_BITMAP_FILE=y
# CONFIG_MD_LINEAR is not set
CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
CONFIG_MD_RAID10=y
CONFIG_MD_RAID456=y
# CONFIG_MD_CLUSTER is not set
CONFIG_BCACHE=y
# CONFIG_BCACHE_DEBUG is not set
# CONFIG_BCACHE_ASYNC_REGISTRATION is not set
CONFIG_BLK_DEV_DM_BUILTIN=y
CONFIG_BLK_DEV_DM=y
# CONFIG_DM_DEBUG is not set
CONFIG_DM_BUFIO=y
# CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING is not set
CONFIG_DM_BIO_PRISON=y
CONFIG_DM_PERSISTENT_DATA=y
# CONFIG_DM_UNSTRIPED is not set
CONFIG_DM_CRYPT=y
# CONFIG_DM_INLINECRYPT is not set
CONFIG_DM_SNAPSHOT=y
CONFIG_DM_THIN_PROVISIONING=y
CONFIG_DM_CACHE=y
CONFIG_DM_CACHE_SMQ=y
CONFIG_DM_WRITECACHE=y
# CONFIG_DM_EBS is not set
# CONFIG_DM_ERA is not set
CONFIG_DM_CLONE=y
CONFIG_DM_MIRROR=y
# CONFIG_DM_LOG_USERSPACE is not set
CONFIG_DM_RAID=y
CONFIG_DM_ZERO=y
CONFIG_DM_MULTIPATH=y
CONFIG_DM_MULTIPATH_QL=y
CONFIG_DM_MULTIPATH_ST=y
# CONFIG_DM_MULTIPATH_HST is not set
# CONFIG_DM_MULTIPATH_IOA is not set
# CONFIG_DM_DELAY is not set
# CONFIG_DM_DUST is not set
# CONFIG_DM_INIT is not set
CONFIG_DM_UEVENT=y
CONFIG_DM_FLAKEY=y
CONFIG_DM_VERITY=y
# CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG is not set
CONFIG_DM_VERITY_FEC=y
# CONFIG_DM_SWITCH is not set
# CONFIG_DM_LOG_WRITES is not set
CONFIG_DM_INTEGRITY=y
CONFIG_DM_ZONED=y
CONFIG_DM_AUDIT=y
# CONFIG_DM_VDO is not set
CONFIG_TARGET_CORE=y
# CONFIG_TCM_IBLOCK is not set
# CONFIG_TCM_FILEIO is not set
# CONFIG_TCM_PSCSI is not set
# CONFIG_LOOPBACK_TARGET is not set
# CONFIG_ISCSI_TARGET is not set
# CONFIG_SBP_TARGET is not set
# CONFIG_REMOTE_TARGET is not set
# CONFIG_FUSION is not set

#
# IEEE 1394 (FireWire) support
#
CONFIG_FIREWIRE=y
CONFIG_FIREWIRE_OHCI=y
CONFIG_FIREWIRE_SBP2=y
CONFIG_FIREWIRE_NET=y
# CONFIG_FIREWIRE_NOSY is not set
# end of IEEE 1394 (FireWire) support

# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
CONFIG_MII=y
CONFIG_NET_CORE=y
CONFIG_BONDING=y
CONFIG_DUMMY=y
CONFIG_WIREGUARD=y
# CONFIG_WIREGUARD_DEBUG is not set
# CONFIG_OVPN is not set
CONFIG_EQUALIZER=y
CONFIG_NET_FC=y
CONFIG_IFB=y
CONFIG_NET_TEAM=y
CONFIG_NET_TEAM_MODE_BROADCAST=y
CONFIG_NET_TEAM_MODE_ROUNDROBIN=y
CONFIG_NET_TEAM_MODE_RANDOM=y
CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=y
CONFIG_NET_TEAM_MODE_LOADBALANCE=y
CONFIG_MACVLAN=y
CONFIG_MACVTAP=y
CONFIG_IPVLAN_L3S=y
CONFIG_IPVLAN=y
CONFIG_IPVTAP=y
CONFIG_VXLAN=y
CONFIG_GENEVE=y
CONFIG_BAREUDP=y
CONFIG_GTP=y
# CONFIG_PFCP is not set
# CONFIG_AMT is not set
CONFIG_MACSEC=y
CONFIG_NETCONSOLE=y
# CONFIG_NETCONSOLE_DYNAMIC is not set
# CONFIG_NETCONSOLE_EXTENDED_LOG is not set
CONFIG_NETPOLL=y
CONFIG_NET_POLL_CONTROLLER=y
CONFIG_TUN=y
CONFIG_TAP=y
CONFIG_TUN_VNET_CROSS_LE=y
CONFIG_VETH=y
CONFIG_VIRTIO_NET=y
CONFIG_NLMON=y
# CONFIG_NETKIT is not set
CONFIG_NET_VRF=y
CONFIG_VSOCKMON=y
# CONFIG_MHI_NET is not set
# CONFIG_ARCNET is not set
CONFIG_ATM_DRIVERS=y
# CONFIG_ATM_SOLOS is not set

#
# Distributed Switch Architecture drivers
#
# CONFIG_B53 is not set
# CONFIG_NET_DSA_BCM_SF2 is not set
# CONFIG_NET_DSA_LOOP is not set
# CONFIG_NET_DSA_HIRSCHMANN_HELLCREEK is not set
# CONFIG_NET_DSA_LANTIQ_GSWIP is not set
# CONFIG_NET_DSA_MXL_GSW1XX is not set
# CONFIG_NET_DSA_MT7530 is not set
# CONFIG_NET_DSA_MV88E6060 is not set
# CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON is not set
# CONFIG_NET_DSA_MV88E6XXX is not set
# CONFIG_NET_DSA_MXL862 is not set
# CONFIG_NET_DSA_AR9331 is not set
# CONFIG_NET_DSA_QCA8K is not set
# CONFIG_NET_DSA_SJA1105 is not set
# CONFIG_NET_DSA_XRS700X_I2C is not set
# CONFIG_NET_DSA_XRS700X_MDIO is not set
# CONFIG_NET_DSA_REALTEK is not set
# CONFIG_NET_DSA_KS8995 is not set
# CONFIG_NET_DSA_SMSC_LAN9303_I2C is not set
# CONFIG_NET_DSA_SMSC_LAN9303_MDIO is not set
# CONFIG_NET_DSA_VITESSE_VSC73XX_SPI is not set
# CONFIG_NET_DSA_VITESSE_VSC73XX_PLATFORM is not set
# CONFIG_NET_DSA_YT921X is not set
# end of Distributed Switch Architecture drivers

CONFIG_ETHERNET=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_VENDOR_ADAPTEC is not set
# CONFIG_NET_VENDOR_AGERE is not set
# CONFIG_NET_VENDOR_ALACRITECH is not set
CONFIG_NET_VENDOR_ALIBABA=y
# CONFIG_ALIBABA_EEA is not set
# CONFIG_ALTERA_TSE is not set
CONFIG_NET_VENDOR_AMAZON=y
# CONFIG_ENA_ETHERNET is not set
# CONFIG_NET_VENDOR_AMD is not set
# CONFIG_NET_VENDOR_AQUANTIA is not set
# CONFIG_NET_VENDOR_ARC is not set
CONFIG_NET_VENDOR_ASIX=y
# CONFIG_SPI_AX88796C is not set
# CONFIG_NET_VENDOR_ATHEROS is not set
# CONFIG_CX_ECAT is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CADENCE is not set
# CONFIG_NET_VENDOR_CAVIUM is not set
# CONFIG_NET_VENDOR_CHELSIO is not set
CONFIG_NET_VENDOR_CISCO=y
# CONFIG_ENIC is not set
# CONFIG_NET_VENDOR_CORTINA is not set
CONFIG_NET_VENDOR_DAVICOM=y
# CONFIG_DM9051 is not set
# CONFIG_NET_VENDOR_DEC is not set
# CONFIG_NET_VENDOR_DLINK is not set
# CONFIG_NET_VENDOR_EMULEX is not set
CONFIG_NET_VENDOR_ENGLEDER=y
# CONFIG_TSNEP is not set
# CONFIG_NET_VENDOR_EZCHIP is not set
CONFIG_NET_VENDOR_FUNGIBLE=y
# CONFIG_FUN_ETH is not set
CONFIG_NET_VENDOR_GOOGLE=y
CONFIG_GVE=y
CONFIG_NET_VENDOR_HISILICON=y
# CONFIG_HIBMCGE is not set
# CONFIG_NET_VENDOR_HUAWEI is not set
CONFIG_NET_VENDOR_I825XX=y
CONFIG_NET_VENDOR_INTEL=y
CONFIG_E100=y
CONFIG_E1000=y
CONFIG_E1000E=y
CONFIG_E1000E_HWTS=y
# CONFIG_IGB is not set
# CONFIG_IGBVF is not set
# CONFIG_IXGBE is not set
# CONFIG_IXGBEVF is not set
# CONFIG_I40E is not set
# CONFIG_I40EVF is not set
# CONFIG_ICE is not set
# CONFIG_FM10K is not set
# CONFIG_IGC is not set
# CONFIG_IDPF is not set
# CONFIG_JME is not set
# CONFIG_NET_VENDOR_ADI is not set
CONFIG_NET_VENDOR_LITEX=y
# CONFIG_LITEX_LITEETH is not set
# CONFIG_NET_VENDOR_MARVELL is not set
CONFIG_NET_VENDOR_MELLANOX=y
# CONFIG_MLX4_EN is not set
CONFIG_MLX4_CORE=y
# CONFIG_MLX4_DEBUG is not set
# CONFIG_MLX4_CORE_GEN2 is not set
# CONFIG_MLX5_CORE is not set
# CONFIG_MLXSW_CORE is not set
# CONFIG_MLXFW is not set
CONFIG_NET_VENDOR_META=y
# CONFIG_FBNIC is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_MICROCHIP is not set
# CONFIG_NET_VENDOR_MICROSEMI is not set
CONFIG_NET_VENDOR_MICROSOFT=y
CONFIG_NET_VENDOR_MUCSE=y
# CONFIG_MGBE is not set
# CONFIG_NET_VENDOR_MYRI is not set
# CONFIG_FEALNX is not set
# CONFIG_NET_VENDOR_NI is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_NETRONOME is not set
# CONFIG_NET_VENDOR_NVIDIA is not set
# CONFIG_NET_VENDOR_OKI is not set
# CONFIG_ETHOC is not set
# CONFIG_NET_VENDOR_PENSANDO is not set
# CONFIG_NET_VENDOR_QLOGIC is not set
# CONFIG_NET_VENDOR_BROCADE is not set
# CONFIG_NET_VENDOR_QUALCOMM is not set
# CONFIG_NET_VENDOR_RDC is not set
# CONFIG_NET_VENDOR_REALTEK is not set
# CONFIG_NET_VENDOR_RENESAS is not set
# CONFIG_NET_VENDOR_ROCKER is not set
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_SILAN is not set
# CONFIG_NET_VENDOR_SIS is not set
# CONFIG_NET_VENDOR_SOLARFLARE is not set
# CONFIG_NET_VENDOR_SMSC is not set
# CONFIG_NET_VENDOR_SOCIONEXT is not set
# CONFIG_NET_VENDOR_STMICRO is not set
# CONFIG_NET_VENDOR_SUN is not set
# CONFIG_NET_VENDOR_SYNOPSYS is not set
# CONFIG_NET_VENDOR_TEHUTI is not set
# CONFIG_NET_VENDOR_TI is not set
CONFIG_NET_VENDOR_VERTEXCOM=y
# CONFIG_MSE102X is not set
# CONFIG_NET_VENDOR_VIA is not set
CONFIG_NET_VENDOR_WANGXUN=y
# CONFIG_NGBE is not set
# CONFIG_TXGBE is not set
# CONFIG_TXGBEVF is not set
# CONFIG_NGBEVF is not set
# CONFIG_NET_VENDOR_WIZNET is not set
# CONFIG_NET_VENDOR_XILINX is not set
# CONFIG_NET_VENDOR_XIRCOM is not set
CONFIG_FDDI=y
# CONFIG_DEFXX is not set
# CONFIG_SKFP is not set
CONFIG_PHYLINK=y
CONFIG_PHYLIB=y
CONFIG_SWPHY=y
CONFIG_PHY_PACKAGE=y
# CONFIG_LED_TRIGGER_PHY is not set
CONFIG_PHYLIB_LEDS=y
CONFIG_FIXED_PHY=y
# CONFIG_SFP is not set

#
# MII PHY device drivers
#
# CONFIG_AS21XXX_PHY is not set
# CONFIG_AIR_AN8801_PHY is not set
# CONFIG_AIR_EN8811H_PHY is not set
# CONFIG_AMD_PHY is not set
# CONFIG_ADIN_PHY is not set
# CONFIG_ADIN1100_PHY is not set
# CONFIG_AQUANTIA_PHY is not set
CONFIG_AX88796B_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_BCM54140_PHY is not set
# CONFIG_BCM7XXX_PHY is not set
# CONFIG_BCM84881_PHY is not set
# CONFIG_BCM87XX_PHY is not set
# CONFIG_CICADA_PHY is not set
# CONFIG_CORTINA_PHY is not set
# CONFIG_DAVICOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_LXT_PHY is not set
# CONFIG_INTEL_XWAY_PHY is not set
# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_MARVELL_PHY is not set
# CONFIG_MARVELL_10G_PHY is not set
# CONFIG_MARVELL_88Q2XXX_PHY is not set
# CONFIG_MARVELL_88X2222_PHY is not set
# CONFIG_MAXLINEAR_GPHY is not set
# CONFIG_MAXLINEAR_86110_PHY is not set
# CONFIG_MEDIATEK_GE_PHY is not set
# CONFIG_MICREL_PHY is not set
# CONFIG_MICROCHIP_T1S_PHY is not set
CONFIG_MICROCHIP_PHY=y
# CONFIG_MICROCHIP_T1_PHY is not set
# CONFIG_MICROSEMI_PHY is not set
# CONFIG_MOTORCOMM_PHY is not set
# CONFIG_NATIONAL_PHY is not set
# CONFIG_NXP_CBTX_PHY is not set
# CONFIG_NXP_C45_TJA11XX_PHY is not set
# CONFIG_NXP_TJA11XX_PHY is not set
# CONFIG_NCN26000_PHY is not set
# CONFIG_AT803X_PHY is not set
# CONFIG_QCA83XX_PHY is not set
# CONFIG_QCA808X_PHY is not set
# CONFIG_QCA807X_PHY is not set
# CONFIG_QSEMI_PHY is not set
CONFIG_REALTEK_PHY=y
# CONFIG_REALTEK_PHY_HWMON is not set
# CONFIG_RENESAS_PHY is not set
# CONFIG_ROCKCHIP_PHY is not set
CONFIG_SMSC_PHY=y
# CONFIG_STE10XP is not set
# CONFIG_TERANETICS_PHY is not set
# CONFIG_DP83822_PHY is not set
# CONFIG_DP83TC811_PHY is not set
# CONFIG_DP83848_PHY is not set
# CONFIG_DP83867_PHY is not set
# CONFIG_DP83869_PHY is not set
# CONFIG_DP83TD510_PHY is not set
# CONFIG_DP83TG720_PHY is not set
# CONFIG_VITESSE_PHY is not set
# CONFIG_XILINX_GMII2RGMII is not set
# CONFIG_PSE_CONTROLLER is not set
CONFIG_CAN_DEV=y
CONFIG_CAN_VCAN=y
CONFIG_CAN_VXCAN=y
CONFIG_CAN_NETLINK=y
CONFIG_CAN_CALC_BITTIMING=y
CONFIG_CAN_RX_OFFLOAD=y
# CONFIG_CAN_CAN327 is not set
# CONFIG_CAN_DUMMY is not set
# CONFIG_CAN_FLEXCAN is not set
# CONFIG_CAN_GRCAN is not set
# CONFIG_CAN_KVASER_PCIEFD is not set
CONFIG_CAN_SLCAN=y
# CONFIG_CAN_VIRTIO_CAN is not set
# CONFIG_CAN_C_CAN is not set
# CONFIG_CAN_CC770 is not set
# CONFIG_CAN_CTUCANFD_PCI is not set
# CONFIG_CAN_CTUCANFD_PLATFORM is not set
# CONFIG_CAN_ESD_402_PCI is not set
CONFIG_CAN_IFI_CANFD=y
# CONFIG_CAN_M_CAN is not set
# CONFIG_CAN_PEAK_PCIEFD is not set
# CONFIG_CAN_SJA1000 is not set
# CONFIG_CAN_SOFTING is not set

#
# CAN SPI interfaces
#
# CONFIG_CAN_HI311X is not set
# CONFIG_CAN_MCP251X is not set
# CONFIG_CAN_MCP251XFD is not set
# end of CAN SPI interfaces

#
# CAN USB interfaces
#
CONFIG_CAN_8DEV_USB=y
CONFIG_CAN_EMS_USB=y
CONFIG_CAN_ESD_USB=y
CONFIG_CAN_ETAS_ES58X=y
CONFIG_CAN_F81604=y
CONFIG_CAN_GS_USB=y
CONFIG_CAN_KVASER_USB=y
CONFIG_CAN_MCBA_USB=y
CONFIG_CAN_PEAK_USB=y
CONFIG_CAN_UCAN=y
# end of CAN USB interfaces

# CONFIG_CAN_DEBUG_DEVICES is not set

#
# MCTP Device Drivers
#
# CONFIG_MCTP_SERIAL is not set
# CONFIG_MCTP_TRANSPORT_I2C is not set
# CONFIG_MCTP_TRANSPORT_USB is not set
# end of MCTP Device Drivers

CONFIG_FWNODE_MDIO=y
CONFIG_OF_MDIO=y
CONFIG_ACPI_MDIO=y
# CONFIG_MDIO_BITBANG is not set
# CONFIG_MDIO_BCM_UNIMAC is not set
# CONFIG_MDIO_HISI_FEMAC is not set
CONFIG_MDIO_MVUSB=y
# CONFIG_MDIO_MSCC_MIIM is not set
# CONFIG_MDIO_OCTEON is not set
# CONFIG_MDIO_IPQ4019 is not set
# CONFIG_MDIO_IPQ8064 is not set
# CONFIG_MDIO_THUNDER is not set

#
# MDIO Multiplexers
#
# CONFIG_MDIO_BUS_MUX_GPIO is not set
# CONFIG_MDIO_BUS_MUX_MULTIPLEXER is not set
# CONFIG_MDIO_BUS_MUX_MMIOREG is not set

#
# PCS device drivers
#
# CONFIG_PCS_XPCS is not set
# end of PCS device drivers

# CONFIG_PLIP is not set
CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_FILTER=y
CONFIG_PPP_MPPE=y
CONFIG_PPP_MULTILINK=y
CONFIG_PPPOATM=y
CONFIG_PPPOX=y
CONFIG_PPPOE=y
CONFIG_PPPOE_HASH_BITS_1=y
# CONFIG_PPPOE_HASH_BITS_2 is not set
# CONFIG_PPPOE_HASH_BITS_4 is not set
# CONFIG_PPPOE_HASH_BITS_8 is not set
CONFIG_PPPOE_HASH_BITS=1
CONFIG_PPTP=y
CONFIG_PPPOL2TP=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
CONFIG_SLIP=y
CONFIG_SLHC=y
CONFIG_SLIP_COMPRESSED=y
CONFIG_SLIP_SMART=y
CONFIG_SLIP_MODE_SLIP6=y
CONFIG_USB_NET_DRIVERS=y
CONFIG_USB_CATC=y
CONFIG_USB_KAWETH=y
CONFIG_USB_PEGASUS=y
CONFIG_USB_RTL8150=y
CONFIG_USB_RTL8152=y
CONFIG_USB_LAN78XX=y
CONFIG_USB_USBNET=y
CONFIG_USB_NET_AX8817X=y
CONFIG_USB_NET_AX88179_178A=y
CONFIG_USB_NET_CDCETHER=y
CONFIG_USB_NET_CDC_EEM=y
CONFIG_USB_NET_CDC_NCM=y
CONFIG_USB_NET_HUAWEI_CDC_NCM=y
CONFIG_USB_NET_CDC_MBIM=y
CONFIG_USB_NET_DM9601=y
CONFIG_USB_NET_SR9700=y
CONFIG_USB_NET_SR9800=y
CONFIG_USB_NET_SMSC75XX=y
CONFIG_USB_NET_SMSC95XX=y
CONFIG_USB_NET_GL620A=y
CONFIG_USB_NET_NET1080=y
CONFIG_USB_NET_PLUSB=y
CONFIG_USB_NET_MCS7830=y
CONFIG_USB_NET_RNDIS_HOST=y
CONFIG_USB_NET_CDC_SUBSET_ENABLE=y
CONFIG_USB_NET_CDC_SUBSET=y
CONFIG_USB_ALI_M5632=y
CONFIG_USB_AN2720=y
CONFIG_USB_BELKIN=y
CONFIG_USB_ARMLINUX=y
CONFIG_USB_EPSON2888=y
CONFIG_USB_KC2190=y
CONFIG_USB_NET_ZAURUS=y
CONFIG_USB_NET_CX82310_ETH=y
CONFIG_USB_NET_KALMIA=y
CONFIG_USB_NET_QMI_WWAN=y
CONFIG_USB_HSO=y
CONFIG_USB_NET_INT51X1=y
CONFIG_USB_CDC_PHONET=y
CONFIG_USB_IPHETH=y
CONFIG_USB_SIERRA_NET=y
CONFIG_USB_VL600=y
CONFIG_USB_NET_CH9200=y
CONFIG_USB_NET_AQC111=y
CONFIG_USB_RTL8153_ECM=y
CONFIG_WLAN=y
CONFIG_WLAN_VENDOR_ADMTEK=y
# CONFIG_ADM8211 is not set
CONFIG_ATH_COMMON=y
CONFIG_WLAN_VENDOR_ATH=y
# CONFIG_ATH_DEBUG is not set
# CONFIG_ATH5K is not set
# CONFIG_ATH5K_PCI is not set
CONFIG_ATH9K_HW=y
CONFIG_ATH9K_COMMON=y
CONFIG_ATH9K_COMMON_DEBUG=y
CONFIG_ATH9K_BTCOEX_SUPPORT=y
CONFIG_ATH9K=y
CONFIG_ATH9K_PCI=y
CONFIG_ATH9K_AHB=y
CONFIG_ATH9K_DEBUGFS=y
# CONFIG_ATH9K_STATION_STATISTICS is not set
CONFIG_ATH9K_DYNACK=y
# CONFIG_ATH9K_WOW is not set
CONFIG_ATH9K_RFKILL=y
CONFIG_ATH9K_CHANNEL_CONTEXT=y
CONFIG_ATH9K_PCOEM=y
# CONFIG_ATH9K_PCI_NO_EEPROM is not set
CONFIG_ATH9K_HTC=y
CONFIG_ATH9K_HTC_DEBUGFS=y
# CONFIG_ATH9K_HWRNG is not set
CONFIG_ATH9K_COMMON_SPECTRAL=y
CONFIG_CARL9170=y
CONFIG_CARL9170_LEDS=y
# CONFIG_CARL9170_DEBUGFS is not set
CONFIG_CARL9170_WPC=y
CONFIG_CARL9170_HWRNG=y
CONFIG_ATH6KL=y
# CONFIG_ATH6KL_SDIO is not set
CONFIG_ATH6KL_USB=y
# CONFIG_ATH6KL_DEBUG is not set
# CONFIG_ATH6KL_TRACING is not set
CONFIG_AR5523=y
# CONFIG_WIL6210 is not set
CONFIG_ATH10K=y
CONFIG_ATH10K_CE=y
CONFIG_ATH10K_PCI=y
# CONFIG_ATH10K_AHB is not set
# CONFIG_ATH10K_SDIO is not set
CONFIG_ATH10K_USB=y
# CONFIG_ATH10K_DEBUG is not set
# CONFIG_ATH10K_DEBUGFS is not set
CONFIG_ATH10K_LEDS=y
# CONFIG_ATH10K_TRACING is not set
# CONFIG_WCN36XX is not set
CONFIG_ATH11K=y
# CONFIG_ATH11K_PCI is not set
# CONFIG_ATH11K_DEBUG is not set
# CONFIG_ATH11K_DEBUGFS is not set
# CONFIG_ATH11K_TRACING is not set
# CONFIG_ATH12K is not set
# CONFIG_WLAN_VENDOR_ATMEL is not set
# CONFIG_WLAN_VENDOR_BROADCOM is not set
# CONFIG_WLAN_VENDOR_INTEL is not set
# CONFIG_WLAN_VENDOR_INTERSIL is not set
# CONFIG_WLAN_VENDOR_MARVELL is not set
# CONFIG_WLAN_VENDOR_MEDIATEK is not set
# CONFIG_WLAN_VENDOR_MICROCHIP is not set
CONFIG_WLAN_VENDOR_PURELIFI=y
CONFIG_PLFXLC=y
# CONFIG_WLAN_VENDOR_RALINK is not set
# CONFIG_WLAN_VENDOR_REALTEK is not set
# CONFIG_WLAN_VENDOR_RSI is not set
CONFIG_WLAN_VENDOR_SILABS=y
# CONFIG_WFX is not set
# CONFIG_WLAN_VENDOR_ST is not set
# CONFIG_WLAN_VENDOR_TI is not set
# CONFIG_WLAN_VENDOR_ZYDAS is not set
# CONFIG_WLAN_VENDOR_QUANTENNA is not set
CONFIG_MAC80211_HWSIM=y
CONFIG_VIRT_WIFI=y
CONFIG_WAN=y
CONFIG_HDLC=y
CONFIG_HDLC_RAW=y
CONFIG_HDLC_RAW_ETH=y
CONFIG_HDLC_CISCO=y
CONFIG_HDLC_FR=y
CONFIG_HDLC_PPP=y
CONFIG_HDLC_X25=y
# CONFIG_FRAMER is not set
# CONFIG_PCI200SYN is not set
# CONFIG_WANXL is not set
# CONFIG_PC300TOO is not set
# CONFIG_FARSYNC is not set
CONFIG_LAPBETHER=y
CONFIG_IEEE802154_DRIVERS=y
# CONFIG_IEEE802154_FAKELB is not set
# CONFIG_IEEE802154_AT86RF230 is not set
# CONFIG_IEEE802154_MRF24J40 is not set
# CONFIG_IEEE802154_CC2520 is not set
CONFIG_IEEE802154_ATUSB=y
# CONFIG_IEEE802154_ADF7242 is not set
# CONFIG_IEEE802154_CA8210 is not set
# CONFIG_IEEE802154_MCR20A is not set
CONFIG_IEEE802154_HWSIM=y

#
# Wireless WAN
#
CONFIG_WWAN=y
# CONFIG_WWAN_DEBUGFS is not set
# CONFIG_WWAN_HWSIM is not set
CONFIG_MHI_WWAN_CTRL=y
# CONFIG_MHI_WWAN_MBIM is not set
# CONFIG_IOSM is not set
# CONFIG_MTK_T7XX is not set
# end of Wireless WAN

CONFIG_VMXNET3=y
# CONFIG_FUJITSU_ES is not set
CONFIG_USB4_NET=y
CONFIG_NETDEVSIM=y
CONFIG_NET_FAILOVER=y

#
# Input device support
#
CONFIG_INPUT=y
CONFIG_INPUT_LEDS=y
CONFIG_INPUT_FF_MEMLESS=y
CONFIG_INPUT_SPARSEKMAP=y
# CONFIG_INPUT_MATRIXKMAP is not set
CONFIG_INPUT_VIVALDIFMAP=y

#
# Userland interfaces
#
CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_MOUSEDEV_PSAUX=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
CONFIG_INPUT_JOYDEV=y
CONFIG_INPUT_EVDEV=y

#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
# CONFIG_KEYBOARD_ADC is not set
# CONFIG_KEYBOARD_ADP5588 is not set
CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_QT1050 is not set
# CONFIG_KEYBOARD_QT1070 is not set
# CONFIG_KEYBOARD_QT2160 is not set
# CONFIG_KEYBOARD_DLINK_DIR685 is not set
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_GPIO is not set
# CONFIG_KEYBOARD_GPIO_POLLED is not set
# CONFIG_KEYBOARD_TCA8418 is not set
# CONFIG_KEYBOARD_MATRIX is not set
# CONFIG_KEYBOARD_CHARLIEPLEX is not set
# CONFIG_KEYBOARD_LM8323 is not set
# CONFIG_KEYBOARD_LM8333 is not set
# CONFIG_KEYBOARD_MAX7359 is not set
# CONFIG_KEYBOARD_MPR121 is not set
# CONFIG_KEYBOARD_NEWTON is not set
# CONFIG_KEYBOARD_OPENCORES is not set
# CONFIG_KEYBOARD_PINEPHONE is not set
# CONFIG_KEYBOARD_SAMSUNG is not set
# CONFIG_KEYBOARD_STOWAWAY is not set
# CONFIG_KEYBOARD_SUNKBD is not set
# CONFIG_KEYBOARD_OMAP4 is not set
# CONFIG_KEYBOARD_TM2_TOUCHKEY is not set
# CONFIG_KEYBOARD_TWL4030 is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_CAP11XX is not set
# CONFIG_KEYBOARD_BCM is not set
# CONFIG_KEYBOARD_CYPRESS_SF is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_BYD=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS=y
CONFIG_MOUSE_PS2_CYPRESS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_SENTELIC is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
CONFIG_MOUSE_PS2_FOCALTECH=y
# CONFIG_MOUSE_PS2_VMMOUSE is not set
CONFIG_MOUSE_PS2_SMBUS=y
# CONFIG_MOUSE_SERIAL is not set
CONFIG_MOUSE_APPLETOUCH=y
CONFIG_MOUSE_BCM5974=y
# CONFIG_MOUSE_CYAPA is not set
# CONFIG_MOUSE_ELAN_I2C is not set
# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_MOUSE_GPIO is not set
# CONFIG_MOUSE_SYNAPTICS_I2C is not set
CONFIG_MOUSE_SYNAPTICS_USB=y
CONFIG_INPUT_JOYSTICK=y
# CONFIG_JOYSTICK_ANALOG is not set
# CONFIG_JOYSTICK_A3D is not set
# CONFIG_JOYSTICK_ADC is not set
# CONFIG_JOYSTICK_ADI is not set
# CONFIG_JOYSTICK_COBRA is not set
# CONFIG_JOYSTICK_GF2K is not set
# CONFIG_JOYSTICK_GRIP is not set
# CONFIG_JOYSTICK_GRIP_MP is not set
# CONFIG_JOYSTICK_GUILLEMOT is not set
# CONFIG_JOYSTICK_INTERACT is not set
# CONFIG_JOYSTICK_SIDEWINDER is not set
# CONFIG_JOYSTICK_TMDC is not set
CONFIG_JOYSTICK_IFORCE=y
CONFIG_JOYSTICK_IFORCE_USB=y
# CONFIG_JOYSTICK_IFORCE_232 is not set
# CONFIG_JOYSTICK_WARRIOR is not set
# CONFIG_JOYSTICK_MAGELLAN is not set
# CONFIG_JOYSTICK_SPACEORB is not set
# CONFIG_JOYSTICK_SPACEBALL is not set
# CONFIG_JOYSTICK_STINGER is not set
# CONFIG_JOYSTICK_TWIDJOY is not set
# CONFIG_JOYSTICK_ZHENHUA is not set
# CONFIG_JOYSTICK_DB9 is not set
# CONFIG_JOYSTICK_GAMECON is not set
# CONFIG_JOYSTICK_TURBOGRAFX is not set
# CONFIG_JOYSTICK_AS5011 is not set
# CONFIG_JOYSTICK_JOYDUMP is not set
CONFIG_JOYSTICK_XPAD=y
CONFIG_JOYSTICK_XPAD_FF=y
CONFIG_JOYSTICK_XPAD_LEDS=y
# CONFIG_JOYSTICK_WALKERA0701 is not set
# CONFIG_JOYSTICK_PSXPAD_SPI is not set
CONFIG_JOYSTICK_PXRC=y
# CONFIG_JOYSTICK_QWIIC is not set
# CONFIG_JOYSTICK_FSIA6B is not set
# CONFIG_JOYSTICK_SENSEHAT is not set
# CONFIG_JOYSTICK_SEESAW is not set
CONFIG_INPUT_TABLET=y
CONFIG_TABLET_USB_ACECAD=y
CONFIG_TABLET_USB_AIPTEK=y
CONFIG_TABLET_USB_HANWANG=y
CONFIG_TABLET_USB_KBTAB=y
CONFIG_TABLET_USB_PEGASUS=y
# CONFIG_TABLET_SERIAL_WACOM4 is not set
CONFIG_INPUT_TOUCHSCREEN=y
# CONFIG_TOUCHSCREEN_ADS7846 is not set
# CONFIG_TOUCHSCREEN_AD7877 is not set
# CONFIG_TOUCHSCREEN_AD7879 is not set
# CONFIG_TOUCHSCREEN_ADC is not set
# CONFIG_TOUCHSCREEN_AR1021_I2C is not set
# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set
# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
# CONFIG_TOUCHSCREEN_BU21013 is not set
# CONFIG_TOUCHSCREEN_BU21029 is not set
# CONFIG_TOUCHSCREEN_CHIPONE_ICN8318 is not set
# CONFIG_TOUCHSCREEN_CHIPONE_ICN8505 is not set
# CONFIG_TOUCHSCREEN_CY8CTMA140 is not set
# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set
# CONFIG_TOUCHSCREEN_CYTTSP5 is not set
# CONFIG_TOUCHSCREEN_DYNAPRO is not set
# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
# CONFIG_TOUCHSCREEN_EETI is not set
# CONFIG_TOUCHSCREEN_EGALAX is not set
# CONFIG_TOUCHSCREEN_EGALAX_SERIAL is not set
# CONFIG_TOUCHSCREEN_EXC3000 is not set
# CONFIG_TOUCHSCREEN_FUJITSU is not set
# CONFIG_TOUCHSCREEN_GOODIX is not set
# CONFIG_TOUCHSCREEN_GOODIX_BERLIN_I2C is not set
# CONFIG_TOUCHSCREEN_GOODIX_BERLIN_SPI is not set
# CONFIG_TOUCHSCREEN_HIDEEP is not set
# CONFIG_TOUCHSCREEN_HIMAX_HX852X is not set
# CONFIG_TOUCHSCREEN_HYCON_HY46XX is not set
# CONFIG_TOUCHSCREEN_HYNITRON_CSTXXX is not set
# CONFIG_TOUCHSCREEN_HYNITRON_CST816X is not set
# CONFIG_TOUCHSCREEN_ILI210X is not set
# CONFIG_TOUCHSCREEN_ILITEK is not set
# CONFIG_TOUCHSCREEN_S6SY761 is not set
# CONFIG_TOUCHSCREEN_GUNZE is not set
# CONFIG_TOUCHSCREEN_EKTF2127 is not set
# CONFIG_TOUCHSCREEN_ELAN is not set
# CONFIG_TOUCHSCREEN_ELO is not set
# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
# CONFIG_TOUCHSCREEN_WACOM_I2C is not set
# CONFIG_TOUCHSCREEN_WACOM_W9000 is not set
# CONFIG_TOUCHSCREEN_MAX11801 is not set
# CONFIG_TOUCHSCREEN_MMS114 is not set
# CONFIG_TOUCHSCREEN_MELFAS_MIP4 is not set
# CONFIG_TOUCHSCREEN_MSG2638 is not set
# CONFIG_TOUCHSCREEN_MTOUCH is not set
# CONFIG_TOUCHSCREEN_NOVATEK_NVT_TS is not set
# CONFIG_TOUCHSCREEN_IMAGIS is not set
# CONFIG_TOUCHSCREEN_IMX6UL_TSC is not set
# CONFIG_TOUCHSCREEN_INEXIO is not set
# CONFIG_TOUCHSCREEN_PENMOUNT is not set
# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set
# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
# CONFIG_TOUCHSCREEN_PIXCIR is not set
# CONFIG_TOUCHSCREEN_WDT87XX_I2C is not set
CONFIG_TOUCHSCREEN_USB_COMPOSITE=y
CONFIG_TOUCHSCREEN_USB_EGALAX=y
CONFIG_TOUCHSCREEN_USB_PANJIT=y
CONFIG_TOUCHSCREEN_USB_3M=y
CONFIG_TOUCHSCREEN_USB_ITM=y
CONFIG_TOUCHSCREEN_USB_ETURBO=y
CONFIG_TOUCHSCREEN_USB_GUNZE=y
CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y
CONFIG_TOUCHSCREEN_USB_IRTOUCH=y
CONFIG_TOUCHSCREEN_USB_IDEALTEK=y
CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y
CONFIG_TOUCHSCREEN_USB_GOTOP=y
CONFIG_TOUCHSCREEN_USB_JASTEC=y
CONFIG_TOUCHSCREEN_USB_ELO=y
CONFIG_TOUCHSCREEN_USB_E2I=y
CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y
CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y
CONFIG_TOUCHSCREEN_USB_NEXIO=y
CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y
# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
# CONFIG_TOUCHSCREEN_TSC_SERIO is not set
# CONFIG_TOUCHSCREEN_TSC2004 is not set
# CONFIG_TOUCHSCREEN_TSC2005 is not set
# CONFIG_TOUCHSCREEN_TSC2007 is not set
# CONFIG_TOUCHSCREEN_RM_TS is not set
# CONFIG_TOUCHSCREEN_SILEAD is not set
# CONFIG_TOUCHSCREEN_SIS_I2C is not set
# CONFIG_TOUCHSCREEN_ST1232 is not set
# CONFIG_TOUCHSCREEN_STMFTS is not set
CONFIG_TOUCHSCREEN_SUR40=y
# CONFIG_TOUCHSCREEN_SURFACE3_SPI is not set
# CONFIG_TOUCHSCREEN_SX8654 is not set
# CONFIG_TOUCHSCREEN_TPS6507X is not set
# CONFIG_TOUCHSCREEN_ZET6223 is not set
# CONFIG_TOUCHSCREEN_ZFORCE is not set
# CONFIG_TOUCHSCREEN_COLIBRI_VF50 is not set
# CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set
# CONFIG_TOUCHSCREEN_IQS5XX is not set
# CONFIG_TOUCHSCREEN_IQS7211 is not set
# CONFIG_TOUCHSCREEN_ZINITIX is not set
# CONFIG_TOUCHSCREEN_HIMAX_HX83112B is not set
CONFIG_INPUT_MISC=y
# CONFIG_INPUT_AD714X is not set
# CONFIG_INPUT_ATMEL_CAPTOUCH is not set
# CONFIG_INPUT_AW86927 is not set
# CONFIG_INPUT_BMA150 is not set
# CONFIG_INPUT_E3X0_BUTTON is not set
# CONFIG_INPUT_PCSPKR is not set
# CONFIG_INPUT_MMA8450 is not set
# CONFIG_INPUT_APANEL is not set
# CONFIG_INPUT_GPIO_BEEPER is not set
# CONFIG_INPUT_GPIO_DECODER is not set
# CONFIG_INPUT_GPIO_VIBRA is not set
# CONFIG_INPUT_ATLAS_BTNS is not set
CONFIG_INPUT_ATI_REMOTE2=y
CONFIG_INPUT_KEYSPAN_REMOTE=y
# CONFIG_INPUT_KXTJ9 is not set
CONFIG_INPUT_POWERMATE=y
CONFIG_INPUT_YEALINK=y
CONFIG_INPUT_CM109=y
# CONFIG_INPUT_REGULATOR_HAPTIC is not set
# CONFIG_INPUT_RETU_PWRBUTTON is not set
# CONFIG_INPUT_TWL4030_PWRBUTTON is not set
# CONFIG_INPUT_TWL4030_VIBRA is not set
CONFIG_INPUT_UINPUT=y
# CONFIG_INPUT_PCF8574 is not set
# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
# CONFIG_INPUT_DA7280_HAPTICS is not set
# CONFIG_INPUT_ADXL34X is not set
# CONFIG_INPUT_IBM_PANEL is not set
CONFIG_INPUT_IMS_PCU=y
# CONFIG_INPUT_IQS269A is not set
# CONFIG_INPUT_IQS626A is not set
# CONFIG_INPUT_IQS7222 is not set
# CONFIG_INPUT_CMA3000 is not set
# CONFIG_INPUT_IDEAPAD_SLIDEBAR is not set
# CONFIG_INPUT_DRV260X_HAPTICS is not set
# CONFIG_INPUT_DRV2665_HAPTICS is not set
# CONFIG_INPUT_DRV2667_HAPTICS is not set
CONFIG_RMI4_CORE=y
# CONFIG_RMI4_I2C is not set
# CONFIG_RMI4_SPI is not set
# CONFIG_RMI4_SMB is not set
CONFIG_RMI4_F03=y
CONFIG_RMI4_F03_SERIO=y
CONFIG_RMI4_2D_SENSOR=y
CONFIG_RMI4_F11=y
CONFIG_RMI4_F12=y
# CONFIG_RMI4_F1A is not set
# CONFIG_RMI4_F21 is not set
CONFIG_RMI4_F30=y
# CONFIG_RMI4_F34 is not set
CONFIG_RMI4_F3A=y
# CONFIG_RMI4_F54 is not set
# CONFIG_RMI4_F55 is not set

#
# Hardware I/O ports
#
CONFIG_SERIO=y
CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
CONFIG_SERIO_I8042=y
CONFIG_SERIO_SERPORT=y
# CONFIG_SERIO_PARKBD is not set
# CONFIG_SERIO_PCIPS2 is not set
CONFIG_SERIO_LIBPS2=y
# CONFIG_SERIO_RAW is not set
# CONFIG_SERIO_ALTERA_PS2 is not set
# CONFIG_SERIO_PS2MULT is not set
# CONFIG_SERIO_ARC_PS2 is not set
# CONFIG_SERIO_APBPS2 is not set
# CONFIG_SERIO_GPIO_PS2 is not set
CONFIG_USERIO=y
# CONFIG_GAMEPORT is not set
# end of Hardware I/O ports
# end of Input device support

#
# Character devices
#
CONFIG_TTY=y
CONFIG_VT=y
CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_VT_CONSOLE_SLEEP=y
CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
CONFIG_LEGACY_TIOCSTI=y
CONFIG_LDISC_AUTOLOAD=y

#
# Serial drivers
#
CONFIG_SERIAL_EARLYCON=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_PNP=y
# CONFIG_SERIAL_8250_16550A_VARIANTS is not set
# CONFIG_SERIAL_8250_FINTEK is not set
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_DMA=y
CONFIG_SERIAL_8250_PCILIB=y
CONFIG_SERIAL_8250_PCI=y
# CONFIG_SERIAL_8250_EXAR is not set
# CONFIG_SERIAL_8250_CS is not set
CONFIG_SERIAL_8250_NR_UARTS=32
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_8250_DETECT_IRQ=y
CONFIG_SERIAL_8250_RSA=y
CONFIG_SERIAL_8250_MANY_PORTS=y
# CONFIG_SERIAL_8250_PCI1XXXX is not set
# CONFIG_SERIAL_8250_DW is not set
# CONFIG_SERIAL_8250_RT288X is not set
CONFIG_SERIAL_8250_LPSS=y
CONFIG_SERIAL_8250_MID=y
CONFIG_SERIAL_8250_PERICOM=y
# CONFIG_SERIAL_8250_NI is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_SERIAL_8250_DWLIB=y

#
# Non-8250 serial port support
#
# CONFIG_SERIAL_MAX3100 is not set
# CONFIG_SERIAL_MAX310X is not set
# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_SIFIVE is not set
# CONFIG_SERIAL_LANTIQ is not set
# CONFIG_SERIAL_SCCNXP is not set
# CONFIG_SERIAL_SC16IS7XX is not set
# CONFIG_SERIAL_ALTERA_JTAGUART is not set
# CONFIG_SERIAL_ALTERA_UART is not set
# CONFIG_SERIAL_XILINX_PS_UART is not set
# CONFIG_SERIAL_ARC is not set
# CONFIG_SERIAL_RP2 is not set
# CONFIG_SERIAL_FSL_LPUART is not set
# CONFIG_SERIAL_FSL_LINFLEXUART is not set
# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
# CONFIG_SERIAL_SPRD is not set
# end of Serial drivers

CONFIG_SERIAL_MCTRL_GPIO=y
CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_MOXA_INTELLIO is not set
# CONFIG_MOXA_SMARTIO is not set
CONFIG_N_HDLC=y
# CONFIG_IPWIRELESS is not set
CONFIG_N_GSM=y
CONFIG_NOZOMI=y
CONFIG_NULL_TTY=y
CONFIG_HVC_DRIVER=y
CONFIG_SERIAL_DEV_BUS=y
CONFIG_SERIAL_DEV_CTRL_TTYPORT=y
CONFIG_TTY_PRINTK=y
CONFIG_TTY_PRINTK_LEVEL=6
# CONFIG_PRINTER is not set
# CONFIG_PPDEV is not set
CONFIG_VIRTIO_CONSOLE=y
# CONFIG_IPMI_HANDLER is not set
# CONFIG_SSIF_IPMI_BMC is not set
# CONFIG_IPMB_DEVICE_INTERFACE is not set
CONFIG_HW_RANDOM=y
# CONFIG_HW_RANDOM_TIMERIOMEM is not set
# CONFIG_HW_RANDOM_INTEL is not set
# CONFIG_HW_RANDOM_AMD is not set
# CONFIG_HW_RANDOM_BA431 is not set
# CONFIG_HW_RANDOM_VIA is not set
CONFIG_HW_RANDOM_VIRTIO=y
# CONFIG_HW_RANDOM_CCTRNG is not set
# CONFIG_HW_RANDOM_XIPHERA is not set
# CONFIG_DEVMEM is not set
CONFIG_NVRAM=y
# CONFIG_DEVPORT is not set
CONFIG_HPET=y
CONFIG_HPET_MMAP=y
CONFIG_HPET_MMAP_DEFAULT=y
# CONFIG_HANGCHECK_TIMER is not set
CONFIG_TCG_TPM=y
# CONFIG_TCG_TPM2_HMAC is not set
# CONFIG_HW_RANDOM_TPM is not set
CONFIG_TCG_TIS_CORE=y
CONFIG_TCG_TIS=y
# CONFIG_TCG_TIS_SPI is not set
# CONFIG_TCG_TIS_I2C is not set
# CONFIG_TCG_TIS_I2C_CR50 is not set
# CONFIG_TCG_TIS_I2C_ATMEL is not set
# CONFIG_TCG_TIS_I2C_INFINEON is not set
# CONFIG_TCG_TIS_I2C_NUVOTON is not set
# CONFIG_TCG_NSC is not set
# CONFIG_TCG_ATMEL is not set
# CONFIG_TCG_INFINEON is not set
CONFIG_TCG_CRB=y
# CONFIG_TCG_VTPM_PROXY is not set
# CONFIG_TCG_TIS_ST33ZP24_I2C is not set
# CONFIG_TCG_TIS_ST33ZP24_SPI is not set
# CONFIG_TELCLOCK is not set
CONFIG_XILLYBUS_CLASS=y
# CONFIG_XILLYBUS is not set
CONFIG_XILLYUSB=y
# end of Character devices

#
# I2C support
#
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MUX=y

#
# Multiplexer I2C Chip support
#
# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set
# CONFIG_I2C_MUX_GPIO is not set
# CONFIG_I2C_MUX_GPMUX is not set
# CONFIG_I2C_MUX_LTC4306 is not set
# CONFIG_I2C_MUX_PCA9541 is not set
# CONFIG_I2C_MUX_PCA954x is not set
CONFIG_I2C_MUX_REG=y
# CONFIG_I2C_MUX_MLXCPLD is not set
# end of Multiplexer I2C Chip support

CONFIG_I2C_HELPER_AUTO=y
CONFIG_I2C_SMBUS=y
CONFIG_I2C_ALGOBIT=y

#
# I2C Hardware Bus support
#

#
# PC SMBus host controller drivers
#
# CONFIG_I2C_ALI1535 is not set
# CONFIG_I2C_ALI1563 is not set
# CONFIG_I2C_ALI15X3 is not set
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_AMD_MP2 is not set
CONFIG_I2C_I801=y
# CONFIG_I2C_ISCH is not set
# CONFIG_I2C_ISMT is not set
# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_CHT_WC is not set
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_NVIDIA_GPU is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_ZHAOXIN is not set

#
# ACPI drivers
#
# CONFIG_I2C_SCMI is not set

#
# I2C system bus drivers (mostly embedded / system-on-chip)
#
# CONFIG_I2C_CBUS_GPIO is not set
CONFIG_I2C_DESIGNWARE_CORE=y
CONFIG_I2C_DESIGNWARE_PLATFORM=y
# CONFIG_I2C_DESIGNWARE_BAYTRAIL is not set
# CONFIG_I2C_DESIGNWARE_PCI is not set
# CONFIG_I2C_EMEV2 is not set
# CONFIG_I2C_GPIO is not set
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_PCA_PLATFORM is not set
# CONFIG_I2C_RK3X is not set
# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_XILINX is not set

#
# External I2C/SMBus adapter drivers
#
CONFIG_I2C_DIOLAN_U2C=y
CONFIG_I2C_DLN2=y
CONFIG_I2C_LJCA=y
CONFIG_I2C_CP2615=y
# CONFIG_I2C_PARPORT is not set
# CONFIG_I2C_PCI1XXXX is not set
CONFIG_I2C_ROBOTFUZZ_OSIF=y
# CONFIG_I2C_TAOS_EVM is not set
CONFIG_I2C_TINY_USB=y
CONFIG_I2C_VIPERBOARD=y

#
# Other I2C/SMBus bus drivers
#
# CONFIG_I2C_MLXCPLD is not set
# CONFIG_I2C_VIRTIO is not set
# end of I2C Hardware Bus support

# CONFIG_I2C_STUB is not set
CONFIG_I2C_SLAVE=y
CONFIG_I2C_SLAVE_EEPROM=y
# CONFIG_I2C_SLAVE_TESTUNIT is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# end of I2C support

# CONFIG_I3C is not set
CONFIG_I3C_OR_I2C=y
CONFIG_SPI=y
# CONFIG_SPI_DEBUG is not set
CONFIG_SPI_MASTER=y
# CONFIG_SPI_MEM is not set

#
# SPI Master Controller Drivers
#
# CONFIG_SPI_ALTERA is not set
# CONFIG_SPI_AXI_SPI_ENGINE is not set
# CONFIG_SPI_BITBANG is not set
# CONFIG_SPI_BUTTERFLY is not set
# CONFIG_SPI_CADENCE is not set
# CONFIG_SPI_CADENCE_QUADSPI is not set
# CONFIG_SPI_CH341 is not set
# CONFIG_SPI_DESIGNWARE is not set
CONFIG_SPI_DLN2=y
# CONFIG_SPI_GPIO is not set
# CONFIG_SPI_LM70_LLP is not set
# CONFIG_SPI_FSL_SPI is not set
CONFIG_SPI_LJCA=y
# CONFIG_SPI_MICROCHIP_CORE_QSPI is not set
# CONFIG_SPI_MICROCHIP_CORE_SPI is not set
# CONFIG_SPI_LANTIQ_SSC is not set
# CONFIG_SPI_OC_TINY is not set
# CONFIG_SPI_PCI1XXXX is not set
# CONFIG_SPI_PXA2XX is not set
# CONFIG_SPI_SC18IS602 is not set
# CONFIG_SPI_SIFIVE is not set
# CONFIG_SPI_MXIC is not set
# CONFIG_SPI_VIRTIO is not set
# CONFIG_SPI_XCOMM is not set
# CONFIG_SPI_XILINX is not set

#
# SPI Multiplexer support
#
# CONFIG_SPI_MUX is not set

#
# SPI Protocol Masters
#
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_LOOPBACK_TEST is not set
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_SPI_SLAVE is not set
CONFIG_SPI_DYNAMIC=y
# CONFIG_SPMI is not set
# CONFIG_HSI is not set
CONFIG_PPS=y
# CONFIG_PPS_DEBUG is not set

#
# PPS clients support
#
# CONFIG_PPS_CLIENT_KTIMER is not set
# CONFIG_PPS_CLIENT_LDISC is not set
# CONFIG_PPS_CLIENT_PARPORT is not set
# CONFIG_PPS_CLIENT_GPIO is not set
# CONFIG_PPS_GENERATOR is not set

#
# PTP clock support
#
CONFIG_PTP_1588_CLOCK=y
CONFIG_PTP_1588_CLOCK_OPTIONAL=y

#
# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
#
CONFIG_PTP_1588_CLOCK_KVM=y
CONFIG_PTP_1588_CLOCK_VMCLOCK=y
# CONFIG_PTP_1588_CLOCK_IDT82P33 is not set
# CONFIG_PTP_1588_CLOCK_IDTCM is not set
# CONFIG_PTP_1588_CLOCK_FC3W is not set
# CONFIG_PTP_1588_CLOCK_MOCK is not set
# CONFIG_PTP_1588_CLOCK_VMW is not set
# CONFIG_PTP_1588_CLOCK_OCP is not set
# CONFIG_PTP_NETC_V4_TIMER is not set
# end of PTP clock support

#
# DPLL device support
#
# CONFIG_ZL3073X_I2C is not set
# CONFIG_ZL3073X_SPI is not set
# end of DPLL device support

# CONFIG_PINCTRL is not set
CONFIG_GPIOLIB_LEGACY=y
CONFIG_GPIOLIB=y
CONFIG_GPIOLIB_FASTPATH_LIMIT=512
CONFIG_OF_GPIO=y
CONFIG_GPIO_ACPI=y
CONFIG_GPIOLIB_IRQCHIP=y
# CONFIG_DEBUG_GPIO is not set
# CONFIG_GPIO_SYSFS is not set
# CONFIG_GPIO_CDEV is not set

#
# Memory mapped GPIO drivers
#
# CONFIG_GPIO_74XX_MMIO is not set
# CONFIG_GPIO_ALTERA is not set
# CONFIG_GPIO_AMDPT is not set
# CONFIG_GPIO_BY_PINCTRL is not set
# CONFIG_GPIO_CADENCE is not set
# CONFIG_GPIO_DWAPB is not set
# CONFIG_GPIO_FTGPIO010 is not set
# CONFIG_GPIO_GENERIC_PLATFORM is not set
# CONFIG_GPIO_GRANITERAPIDS is not set
# CONFIG_GPIO_GRGPIO is not set
# CONFIG_GPIO_HLWD is not set
# CONFIG_GPIO_ICH is not set
# CONFIG_GPIO_LOGICVC is not set
# CONFIG_GPIO_MB86S7X is not set
# CONFIG_GPIO_POLARFIRE_SOC is not set
# CONFIG_GPIO_SIFIVE is not set
# CONFIG_GPIO_SYSCON is not set
# CONFIG_GPIO_WAVESHARE_DSI_TOUCH is not set
# CONFIG_GPIO_XILINX is not set
# CONFIG_GPIO_AMD_FCH is not set
# end of Memory mapped GPIO drivers

#
# Port-mapped I/O GPIO drivers
#
# CONFIG_GPIO_VX855 is not set
# CONFIG_GPIO_F7188X is not set
# CONFIG_GPIO_IT87 is not set
# CONFIG_GPIO_NOVALAKE is not set
# CONFIG_GPIO_SCH311X is not set
# CONFIG_GPIO_WINBOND is not set
# CONFIG_GPIO_WS16C48 is not set
# end of Port-mapped I/O GPIO drivers

#
# I2C GPIO expanders
#
# CONFIG_GPIO_ADNP is not set
# CONFIG_GPIO_FXL6408 is not set
# CONFIG_GPIO_DS4520 is not set
# CONFIG_GPIO_GW_PLD is not set
# CONFIG_GPIO_MAX7300 is not set
# CONFIG_GPIO_MAX732X is not set
# CONFIG_GPIO_PCA953X is not set
# CONFIG_GPIO_PCA9570 is not set
# CONFIG_GPIO_PCF857X is not set
# CONFIG_GPIO_TPIC2810 is not set
# end of I2C GPIO expanders

#
# MFD GPIO expanders
#
CONFIG_GPIO_DLN2=y
CONFIG_GPIO_LJCA=y
# CONFIG_GPIO_TWL4030 is not set
# CONFIG_GPIO_WHISKEY_COVE is not set
# end of MFD GPIO expanders

#
# Auxiliary Bus GPIO drivers
#
# end of Auxiliary Bus GPIO drivers

#
# PCI GPIO expanders
#
# CONFIG_GPIO_AMD8111 is not set
# CONFIG_GPIO_BT8XX is not set
# CONFIG_GPIO_ML_IOH is not set
# CONFIG_GPIO_PCI_IDIO_16 is not set
# CONFIG_GPIO_PCIE_IDIO_24 is not set
# CONFIG_GPIO_RDC321X is not set
# CONFIG_GPIO_SODAVILLE is not set
# end of PCI GPIO expanders

#
# SPI GPIO expanders
#
# CONFIG_GPIO_74X164 is not set
# CONFIG_GPIO_MAX3191X is not set
# CONFIG_GPIO_MAX7301 is not set
# CONFIG_GPIO_MC33880 is not set
# CONFIG_GPIO_PISOSR is not set
# CONFIG_GPIO_XRA1403 is not set
# end of SPI GPIO expanders

#
# USB GPIO expanders
#
CONFIG_GPIO_VIPERBOARD=y
# CONFIG_GPIO_MPSSE is not set
# end of USB GPIO expanders

#
# Virtual GPIO drivers
#
# CONFIG_GPIO_AGGREGATOR is not set
# CONFIG_GPIO_LATCH is not set
# CONFIG_GPIO_LINE_MUX is not set
# CONFIG_GPIO_MOCKUP is not set
# CONFIG_GPIO_VIRTIO is not set
# CONFIG_GPIO_SIM is not set
# end of Virtual GPIO drivers

#
# GPIO Debugging utilities
#
# CONFIG_GPIO_SLOPPY_LOGIC_ANALYZER is not set
# CONFIG_GPIO_VIRTUSER is not set
# end of GPIO Debugging utilities

# CONFIG_W1 is not set
# CONFIG_POWER_RESET is not set
# CONFIG_POWER_SEQUENCING is not set
CONFIG_POWER_SUPPLY=y
# CONFIG_POWER_SUPPLY_DEBUG is not set
CONFIG_POWER_SUPPLY_HWMON=y
# CONFIG_GENERIC_ADC_BATTERY is not set
# CONFIG_IP5XXX_POWER is not set
# CONFIG_TEST_POWER is not set
# CONFIG_CHARGER_ADP5061 is not set
# CONFIG_BATTERY_CHAGALL is not set
# CONFIG_BATTERY_CW2015 is not set
# CONFIG_BATTERY_DS2780 is not set
# CONFIG_BATTERY_DS2781 is not set
# CONFIG_BATTERY_DS2782 is not set
# CONFIG_BATTERY_SAMSUNG_SDI is not set
# CONFIG_BATTERY_S2MU005 is not set
# CONFIG_BATTERY_SBS is not set
# CONFIG_CHARGER_SBS is not set
# CONFIG_MANAGER_SBS is not set
# CONFIG_BATTERY_BQ27XXX is not set
# CONFIG_BATTERY_MAX17040 is not set
# CONFIG_BATTERY_MAX17042 is not set
# CONFIG_BATTERY_MAX1720X is not set
CONFIG_CHARGER_ISP1704=y
# CONFIG_CHARGER_MAX8903 is not set
# CONFIG_CHARGER_TWL4030 is not set
# CONFIG_CHARGER_TWL6030 is not set
# CONFIG_CHARGER_LP8727 is not set
# CONFIG_CHARGER_GPIO is not set
# CONFIG_CHARGER_MANAGER is not set
# CONFIG_CHARGER_LT3651 is not set
# CONFIG_CHARGER_LTC4162L is not set
# CONFIG_CHARGER_DETECTOR_MAX14656 is not set
# CONFIG_CHARGER_MAX77976 is not set
# CONFIG_CHARGER_MAX8971 is not set
# CONFIG_CHARGER_MT6360 is not set
# CONFIG_CHARGER_MT6370 is not set
# CONFIG_CHARGER_BQ2415X is not set
CONFIG_CHARGER_BQ24190=y
# CONFIG_CHARGER_BQ24257 is not set
# CONFIG_CHARGER_BQ24735 is not set
# CONFIG_CHARGER_BQ2515X is not set
# CONFIG_CHARGER_BQ25890 is not set
# CONFIG_CHARGER_BQ25980 is not set
# CONFIG_CHARGER_BQ256XX is not set
# CONFIG_CHARGER_SMB347 is not set
# CONFIG_BATTERY_GAUGE_LTC2941 is not set
# CONFIG_BATTERY_GOLDFISH is not set
# CONFIG_BATTERY_RT5033 is not set
# CONFIG_CHARGER_RT9455 is not set
# CONFIG_CHARGER_RT9467 is not set
# CONFIG_CHARGER_RT9471 is not set
# CONFIG_CHARGER_RT9756 is not set
# CONFIG_FUEL_GAUGE_STC3117 is not set
# CONFIG_CHARGER_UCS1002 is not set
# CONFIG_CHARGER_BD99954 is not set
# CONFIG_BATTERY_SURFACE is not set
# CONFIG_CHARGER_SURFACE is not set
# CONFIG_BATTERY_UG3105 is not set
# CONFIG_BATTERY_CHARGER_SURFACE_RT is not set
# CONFIG_FUEL_GAUGE_MM8013 is not set
CONFIG_HWMON=y
# CONFIG_HWMON_DEBUG_CHIP is not set

#
# Native drivers
#
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_ABITUGURU3 is not set
# CONFIG_SENSORS_AD7314 is not set
# CONFIG_SENSORS_AD7414 is not set
# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM1177 is not set
# CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ADT7310 is not set
# CONFIG_SENSORS_ADT7410 is not set
# CONFIG_SENSORS_ADT7411 is not set
# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_AHT10 is not set
CONFIG_SENSORS_AQUACOMPUTER_D5NEXT=y
# CONFIG_SENSORS_AS370 is not set
# CONFIG_SENSORS_ASC7621 is not set
# CONFIG_SENSORS_ASUS_ROG_RYUJIN is not set
# CONFIG_SENSORS_AXI_FAN_CONTROL is not set
# CONFIG_SENSORS_K8TEMP is not set
# CONFIG_SENSORS_K10TEMP is not set
# CONFIG_SENSORS_FAM15H_POWER is not set
# CONFIG_SENSORS_APPLESMC is not set
# CONFIG_SENSORS_ARCTIC_FAN_CONTROLLER is not set
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_CHIPCAP2 is not set
CONFIG_SENSORS_CORSAIR_CPRO=y
CONFIG_SENSORS_CORSAIR_PSU=y
# CONFIG_SENSORS_DRIVETEMP is not set
# CONFIG_SENSORS_DS620 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_DELL_SMM is not set
# CONFIG_SENSORS_I5K_AMB is not set
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_F71882FG is not set
# CONFIG_SENSORS_F75375S is not set
# CONFIG_SENSORS_FSCHMD is not set
# CONFIG_SENSORS_FTSTEUTATES is not set
CONFIG_SENSORS_GIGABYTE_WATERFORCE=y
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_GPD is not set
# CONFIG_SENSORS_G760A is not set
# CONFIG_SENSORS_G762 is not set
# CONFIG_SENSORS_GPIO_FAN is not set
# CONFIG_SENSORS_HIH6130 is not set
# CONFIG_SENSORS_HS3001 is not set
# CONFIG_SENSORS_HTU31 is not set
# CONFIG_SENSORS_IIO_HWMON is not set
# CONFIG_SENSORS_I5500 is not set
# CONFIG_SENSORS_CORETEMP is not set
# CONFIG_SENSORS_ISL28022 is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_JC42 is not set
CONFIG_SENSORS_POWERZ=y
# CONFIG_SENSORS_POWR1220 is not set
# CONFIG_SENSORS_PROM21_XHCI is not set
# CONFIG_SENSORS_LATTEPANDA_SIGMA_EC is not set
# CONFIG_SENSORS_LENOVO_EC is not set
# CONFIG_SENSORS_LINEAGE is not set
# CONFIG_SENSORS_LTC2945 is not set
# CONFIG_SENSORS_LTC2947_I2C is not set
# CONFIG_SENSORS_LTC2947_SPI is not set
# CONFIG_SENSORS_LTC2990 is not set
# CONFIG_SENSORS_LTC2991 is not set
# CONFIG_SENSORS_LTC2992 is not set
# CONFIG_SENSORS_LTC4151 is not set
# CONFIG_SENSORS_LTC4215 is not set
# CONFIG_SENSORS_LTC4222 is not set
# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_LTC4260 is not set
# CONFIG_SENSORS_LTC4261 is not set
# CONFIG_SENSORS_LTC4282 is not set
# CONFIG_SENSORS_LTC4283 is not set
# CONFIG_SENSORS_MAX1111 is not set
# CONFIG_SENSORS_MAX127 is not set
# CONFIG_SENSORS_MAX16065 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX1668 is not set
# CONFIG_SENSORS_MAX197 is not set
# CONFIG_SENSORS_MAX31722 is not set
# CONFIG_SENSORS_MAX31730 is not set
# CONFIG_SENSORS_MAX31760 is not set
# CONFIG_MAX31827 is not set
# CONFIG_SENSORS_MAX6620 is not set
# CONFIG_SENSORS_MAX6621 is not set
# CONFIG_SENSORS_MAX6639 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_MAX6697 is not set
# CONFIG_SENSORS_MAX31790 is not set
# CONFIG_SENSORS_MC34VR500 is not set
# CONFIG_SENSORS_MCP3021 is not set
# CONFIG_SENSORS_MCP9982 is not set
# CONFIG_SENSORS_TC654 is not set
# CONFIG_SENSORS_TPS23861 is not set
# CONFIG_SENSORS_MR75203 is not set
# CONFIG_SENSORS_ADCXX is not set
# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM70 is not set
# CONFIG_SENSORS_LM73 is not set
# CONFIG_SENSORS_LM75 is not set
# CONFIG_SENSORS_LM77 is not set
# CONFIG_SENSORS_LM78 is not set
# CONFIG_SENSORS_LM80 is not set
# CONFIG_SENSORS_LM83 is not set
# CONFIG_SENSORS_LM85 is not set
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
# CONFIG_SENSORS_LM95234 is not set
# CONFIG_SENSORS_LM95241 is not set
# CONFIG_SENSORS_LM95245 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_NTC_THERMISTOR is not set
# CONFIG_SENSORS_NCT6683 is not set
# CONFIG_SENSORS_NCT6775 is not set
# CONFIG_SENSORS_NCT6775_I2C is not set
# CONFIG_SENSORS_NCT7363 is not set
# CONFIG_SENSORS_NCT7802 is not set
# CONFIG_SENSORS_NCT7904 is not set
# CONFIG_SENSORS_NPCM7XX is not set
CONFIG_SENSORS_NZXT_KRAKEN2=y
# CONFIG_SENSORS_NZXT_KRAKEN3 is not set
CONFIG_SENSORS_NZXT_SMART2=y
# CONFIG_SENSORS_OCC_P8_I2C is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_PMBUS is not set
# CONFIG_SENSORS_PT5161L is not set
# CONFIG_SENSORS_SBTSI is not set
# CONFIG_SENSORS_SHT15 is not set
# CONFIG_SENSORS_SHT21 is not set
# CONFIG_SENSORS_SHT3x is not set
# CONFIG_SENSORS_SHT4x is not set
# CONFIG_SENSORS_SHTC1 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_DME1737 is not set
# CONFIG_SENSORS_EMC1403 is not set
# CONFIG_SENSORS_EMC1812 is not set
# CONFIG_SENSORS_EMC2103 is not set
# CONFIG_SENSORS_EMC2305 is not set
# CONFIG_SENSORS_EMC6W201 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_SCH5627 is not set
# CONFIG_SENSORS_SCH5636 is not set
# CONFIG_SENSORS_STTS751 is not set
# CONFIG_SENSORS_SURFACE_FAN is not set
# CONFIG_SENSORS_SURFACE_TEMP is not set
# CONFIG_SENSORS_ADC128D818 is not set
# CONFIG_SENSORS_ADS7828 is not set
# CONFIG_SENSORS_ADS7871 is not set
# CONFIG_SENSORS_AMC6821 is not set
# CONFIG_SENSORS_INA209 is not set
# CONFIG_SENSORS_INA2XX is not set
# CONFIG_SENSORS_INA238 is not set
# CONFIG_SENSORS_INA3221 is not set
# CONFIG_SENSORS_SPD5118 is not set
# CONFIG_SENSORS_TC74 is not set
# CONFIG_SENSORS_THMC50 is not set
# CONFIG_SENSORS_TMP102 is not set
# CONFIG_SENSORS_TMP103 is not set
# CONFIG_SENSORS_TMP108 is not set
# CONFIG_SENSORS_TMP401 is not set
# CONFIG_SENSORS_TMP421 is not set
# CONFIG_SENSORS_TMP464 is not set
# CONFIG_SENSORS_TMP513 is not set
# CONFIG_SENSORS_TSC1641 is not set
# CONFIG_SENSORS_VIA_CPUTEMP is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_VT1211 is not set
# CONFIG_SENSORS_VT8231 is not set
# CONFIG_SENSORS_W83773G is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83791D is not set
# CONFIG_SENSORS_W83792D is not set
# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83795 is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83L786NG is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_SENSORS_XGENE is not set
# CONFIG_SENSORS_YOGAFAN is not set

#
# ACPI drivers
#
# CONFIG_SENSORS_ACPI_POWER is not set
# CONFIG_SENSORS_ATK0110 is not set
# CONFIG_SENSORS_ASUS_WMI is not set
# CONFIG_SENSORS_ASUS_EC is not set
# CONFIG_SENSORS_HP_WMI is not set
CONFIG_THERMAL=y
CONFIG_THERMAL_NETLINK=y
# CONFIG_THERMAL_STATISTICS is not set
# CONFIG_THERMAL_DEBUGFS is not set
# CONFIG_THERMAL_CORE_TESTING is not set
CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
CONFIG_THERMAL_HWMON=y
# CONFIG_THERMAL_OF is not set
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
# CONFIG_THERMAL_GOV_FAIR_SHARE is not set
CONFIG_THERMAL_GOV_STEP_WISE=y
# CONFIG_THERMAL_GOV_BANG_BANG is not set
# CONFIG_THERMAL_GOV_USER_SPACE is not set
# CONFIG_PCIE_THERMAL is not set
# CONFIG_THERMAL_EMULATION is not set
# CONFIG_THERMAL_MMIO is not set

#
# Intel thermal drivers
#
# CONFIG_INTEL_POWERCLAMP is not set
CONFIG_X86_THERMAL_VECTOR=y
# CONFIG_X86_PKG_TEMP_THERMAL is not set
# CONFIG_INTEL_SOC_DTS_THERMAL is not set

#
# ACPI INT340X thermal drivers
#
# CONFIG_INT340X_THERMAL is not set
# end of ACPI INT340X thermal drivers

# CONFIG_INTEL_BXT_PMIC_THERMAL is not set
# CONFIG_INTEL_PCH_THERMAL is not set
# CONFIG_INTEL_TCC_COOLING is not set
# CONFIG_INTEL_HFI_THERMAL is not set
# end of Intel thermal drivers

# CONFIG_GENERIC_ADC_THERMAL is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_CORE is not set
# CONFIG_WATCHDOG_NOWAYOUT is not set
CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y
CONFIG_WATCHDOG_OPEN_TIMEOUT=0
# CONFIG_WATCHDOG_SYSFS is not set
# CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT is not set

#
# Watchdog Pretimeout Governors
#

#
# Watchdog Device Drivers
#
# CONFIG_SOFT_WATCHDOG is not set
# CONFIG_GPIO_WATCHDOG is not set
# CONFIG_LENOVO_SE10_WDT is not set
# CONFIG_LENOVO_SE30_WDT is not set
# CONFIG_WDAT_WDT is not set
# CONFIG_XILINX_WATCHDOG is not set
# CONFIG_ZIIRAVE_WATCHDOG is not set
# CONFIG_CADENCE_WATCHDOG is not set
# CONFIG_DW_WATCHDOG is not set
# CONFIG_TWL4030_WATCHDOG is not set
# CONFIG_MAX63XX_WATCHDOG is not set
# CONFIG_RETU_WATCHDOG is not set
# CONFIG_ACQUIRE_WDT is not set
# CONFIG_ADVANTECH_WDT is not set
# CONFIG_ADVANTECH_EC_WDT is not set
# CONFIG_ALIM1535_WDT is not set
# CONFIG_ALIM7101_WDT is not set
# CONFIG_EBC_C384_WDT is not set
# CONFIG_EXAR_WDT is not set
# CONFIG_F71808E_WDT is not set
# CONFIG_SP5100_TCO is not set
# CONFIG_SBC_FITPC2_WATCHDOG is not set
# CONFIG_EUROTECH_WDT is not set
# CONFIG_IB700_WDT is not set
# CONFIG_IBMASR is not set
# CONFIG_WAFER_WDT is not set
# CONFIG_I6300ESB_WDT is not set
# CONFIG_IE6XX_WDT is not set
# CONFIG_INTEL_OC_WATCHDOG is not set
# CONFIG_ITCO_WDT is not set
# CONFIG_IT8712F_WDT is not set
# CONFIG_IT87_WDT is not set
# CONFIG_HP_WATCHDOG is not set
# CONFIG_SC1200_WDT is not set
# CONFIG_PC87413_WDT is not set
# CONFIG_NV_TCO is not set
# CONFIG_60XX_WDT is not set
# CONFIG_SMSC_SCH311X_WDT is not set
# CONFIG_SMSC37B787_WDT is not set
# CONFIG_TQMX86_WDT is not set
# CONFIG_VIA_WDT is not set
# CONFIG_W83627HF_WDT is not set
# CONFIG_W83877F_WDT is not set
# CONFIG_W83977F_WDT is not set
# CONFIG_SBC_EPX_C3_WATCHDOG is not set
# CONFIG_INTEL_MEI_WDT is not set
# CONFIG_NI903X_WDT is not set
# CONFIG_NIC7018_WDT is not set
# CONFIG_MEN_A21_WDT is not set

#
# PCI-based Watchdog Cards
#
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set

#
# USB-based Watchdog Cards
#
CONFIG_USBPCWATCHDOG=y
CONFIG_SSB_POSSIBLE=y
CONFIG_SSB=y
CONFIG_SSB_PCIHOST_POSSIBLE=y
# CONFIG_SSB_PCIHOST is not set
CONFIG_SSB_PCMCIAHOST_POSSIBLE=y
# CONFIG_SSB_PCMCIAHOST is not set
CONFIG_SSB_SDIOHOST_POSSIBLE=y
# CONFIG_SSB_SDIOHOST is not set
# CONFIG_SSB_DRIVER_GPIO is not set
CONFIG_BCMA_POSSIBLE=y
CONFIG_BCMA=y
CONFIG_BCMA_HOST_PCI_POSSIBLE=y
# CONFIG_BCMA_HOST_PCI is not set
# CONFIG_BCMA_HOST_SOC is not set
# CONFIG_BCMA_DRIVER_PCI is not set
# CONFIG_BCMA_DRIVER_GMAC_CMN is not set
# CONFIG_BCMA_DRIVER_GPIO is not set
# CONFIG_BCMA_DEBUG is not set

#
# Multifunction device drivers
#
CONFIG_MFD_CORE=y
# CONFIG_MFD_ADP5585 is not set
# CONFIG_MFD_ACT8945A is not set
# CONFIG_MFD_AS3711 is not set
# CONFIG_MFD_SMPRO is not set
# CONFIG_MFD_AS3722 is not set
# CONFIG_PMIC_ADP5520 is not set
# CONFIG_MFD_AAT2870_CORE is not set
# CONFIG_MFD_ATMEL_FLEXCOM is not set
# CONFIG_MFD_ATMEL_HLCDC is not set
# CONFIG_MFD_BCM590XX is not set
# CONFIG_MFD_BD9571MWV is not set
# CONFIG_MFD_AXP20X_I2C is not set
# CONFIG_MFD_CGBC is not set
# CONFIG_MFD_CS40L50_I2C is not set
# CONFIG_MFD_CS40L50_SPI is not set
# CONFIG_MFD_CS42L43_I2C is not set
# CONFIG_MFD_CS42L43_SDW is not set
# CONFIG_MFD_LOCHNAGAR is not set
# CONFIG_MFD_MADERA is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_DA9052_SPI is not set
# CONFIG_MFD_DA9052_I2C is not set
# CONFIG_MFD_DA9055 is not set
# CONFIG_MFD_DA9062 is not set
# CONFIG_MFD_DA9063 is not set
# CONFIG_MFD_DA9150 is not set
CONFIG_MFD_DLN2=y
# CONFIG_MFD_GATEWORKS_GSC is not set
# CONFIG_MFD_MC13XXX_SPI is not set
# CONFIG_MFD_MC13XXX_I2C is not set
# CONFIG_MFD_MP2629 is not set
# CONFIG_MFD_PF1550 is not set
# CONFIG_MFD_HI6421_PMIC is not set
# CONFIG_MFD_INTEL_QUARK_I2C_GPIO is not set
CONFIG_LPC_ICH=y
# CONFIG_LPC_SCH is not set
# CONFIG_INTEL_SOC_PMIC is not set
CONFIG_INTEL_SOC_PMIC_BXTWC=y
CONFIG_INTEL_SOC_PMIC_CHTWC=y
# CONFIG_INTEL_SOC_PMIC_CHTDC_TI is not set
# CONFIG_MFD_INTEL_LPSS_ACPI is not set
# CONFIG_MFD_INTEL_LPSS_PCI is not set
CONFIG_MFD_INTEL_PMC_BXT=y
# CONFIG_MFD_IQS62X is not set
# CONFIG_MFD_JANZ_CMODIO is not set
# CONFIG_MFD_KEMPLD is not set
# CONFIG_MFD_88PM800 is not set
# CONFIG_MFD_88PM805 is not set
# CONFIG_MFD_88PM860X is not set
# CONFIG_MFD_88PM886_PMIC is not set
# CONFIG_MFD_MAX5970 is not set
# CONFIG_MFD_MAX14577 is not set
# CONFIG_MFD_MAX77541 is not set
# CONFIG_MFD_MAX77620 is not set
# CONFIG_MFD_MAX77650 is not set
# CONFIG_MFD_MAX77686 is not set
# CONFIG_MFD_MAX77693 is not set
# CONFIG_MFD_MAX77705 is not set
# CONFIG_MFD_MAX77714 is not set
# CONFIG_MFD_MAX77759 is not set
# CONFIG_MFD_MAX77843 is not set
# CONFIG_MFD_MAX8907 is not set
# CONFIG_MFD_MAX8925 is not set
# CONFIG_MFD_MAX8997 is not set
# CONFIG_MFD_MAX8998 is not set
CONFIG_MFD_MT6360=y
CONFIG_MFD_MT6370=y
# CONFIG_MFD_MT6397 is not set
# CONFIG_MFD_MENF21BMC is not set
# CONFIG_MFD_NCT6694 is not set
# CONFIG_MFD_OCELOT is not set
# CONFIG_MFD_CPCAP is not set
CONFIG_MFD_VIPERBOARD=y
# CONFIG_MFD_NTXEC is not set
CONFIG_MFD_RETU=y
# CONFIG_MFD_SY7636A is not set
# CONFIG_MFD_RDC321X is not set
# CONFIG_MFD_RT4831 is not set
# CONFIG_MFD_RT5033 is not set
# CONFIG_MFD_RT5120 is not set
# CONFIG_MFD_RC5T583 is not set
# CONFIG_MFD_RK8XX_I2C is not set
# CONFIG_MFD_RK8XX_SPI is not set
# CONFIG_MFD_RN5T618 is not set
# CONFIG_MFD_SEC_I2C is not set
# CONFIG_MFD_SI476X_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_MFD_SKY81452 is not set
# CONFIG_MFD_STMPE is not set
CONFIG_MFD_SYSCON=y
# CONFIG_MFD_LP3943 is not set
# CONFIG_MFD_LP8788 is not set
# CONFIG_MFD_TI_LMU is not set
# CONFIG_MFD_BQ257XX is not set
# CONFIG_MFD_PALMAS is not set
# CONFIG_TPS6105X is not set
# CONFIG_TPS65010 is not set
# CONFIG_TPS6507X is not set
# CONFIG_MFD_TPS65086 is not set
# CONFIG_MFD_TPS65090 is not set
# CONFIG_MFD_TPS65217 is not set
# CONFIG_MFD_TI_LP873X is not set
# CONFIG_MFD_TI_LP87565 is not set
# CONFIG_MFD_TPS65218 is not set
# CONFIG_MFD_TPS65219 is not set
# CONFIG_MFD_TPS6586X is not set
# CONFIG_MFD_TPS65910 is not set
# CONFIG_MFD_TPS65912_I2C is not set
# CONFIG_MFD_TPS65912_SPI is not set
# CONFIG_MFD_TPS6594_I2C is not set
# CONFIG_MFD_TPS6594_SPI is not set
CONFIG_TWL4030_CORE=y
# CONFIG_MFD_TWL4030_AUDIO is not set
# CONFIG_TWL6040_CORE is not set
# CONFIG_MFD_LM3533 is not set
# CONFIG_MFD_TC3589X is not set
# CONFIG_MFD_TQMX86 is not set
# CONFIG_MFD_VX855 is not set
# CONFIG_MFD_ARIZONA_I2C is not set
# CONFIG_MFD_ARIZONA_SPI is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM831X_I2C is not set
# CONFIG_MFD_WM831X_SPI is not set
# CONFIG_MFD_WM8350_I2C is not set
# CONFIG_MFD_WM8994 is not set
# CONFIG_MFD_ROHM_BD718XX is not set
# CONFIG_MFD_ROHM_BD71828 is not set
# CONFIG_MFD_ROHM_BD957XMUF is not set
# CONFIG_MFD_ROHM_BD96801 is not set
# CONFIG_MFD_STPMIC1 is not set
# CONFIG_MFD_STMFX is not set
# CONFIG_MFD_ATC260X_I2C is not set
# CONFIG_MFD_QCOM_PM8008 is not set
# CONFIG_RAVE_SP_CORE is not set
# CONFIG_MFD_INTEL_M10_BMC_SPI is not set
# CONFIG_MFD_QNAP_MCU is not set
# CONFIG_MFD_RSMU_I2C is not set
# CONFIG_MFD_RSMU_SPI is not set
# CONFIG_MFD_UPBOARD_FPGA is not set
# CONFIG_MFD_MAX7360 is not set
# end of Multifunction device drivers

CONFIG_REGULATOR=y
# CONFIG_REGULATOR_DEBUG is not set
CONFIG_REGULATOR_FIXED_VOLTAGE=y
# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
# CONFIG_REGULATOR_NETLINK_EVENTS is not set
# CONFIG_REGULATOR_88PG86X is not set
# CONFIG_REGULATOR_ACT8865 is not set
# CONFIG_REGULATOR_AD5398 is not set
# CONFIG_REGULATOR_ADP5055 is not set
# CONFIG_REGULATOR_AW37503 is not set
# CONFIG_REGULATOR_DA9121 is not set
# CONFIG_REGULATOR_DA9210 is not set
# CONFIG_REGULATOR_DA9211 is not set
# CONFIG_REGULATOR_FAN53555 is not set
# CONFIG_REGULATOR_FAN53880 is not set
# CONFIG_REGULATOR_GPIO is not set
# CONFIG_REGULATOR_ISL9305 is not set
# CONFIG_REGULATOR_ISL6271A is not set
# CONFIG_REGULATOR_FP9931 is not set
# CONFIG_REGULATOR_LP3971 is not set
# CONFIG_REGULATOR_LP3972 is not set
# CONFIG_REGULATOR_LP872X is not set
# CONFIG_REGULATOR_LP8755 is not set
# CONFIG_REGULATOR_LTC3589 is not set
# CONFIG_REGULATOR_LTC3676 is not set
# CONFIG_REGULATOR_MAX1586 is not set
# CONFIG_REGULATOR_MAX77503 is not set
# CONFIG_REGULATOR_MAX77675 is not set
# CONFIG_REGULATOR_MAX77857 is not set
# CONFIG_REGULATOR_MAX8649 is not set
# CONFIG_REGULATOR_MAX8660 is not set
# CONFIG_REGULATOR_MAX8893 is not set
# CONFIG_REGULATOR_MAX8952 is not set
# CONFIG_REGULATOR_MAX20086 is not set
# CONFIG_REGULATOR_MAX20411 is not set
# CONFIG_REGULATOR_MAX77826 is not set
# CONFIG_REGULATOR_MAX77838 is not set
# CONFIG_REGULATOR_MCP16502 is not set
# CONFIG_REGULATOR_MP5416 is not set
# CONFIG_REGULATOR_MP8859 is not set
# CONFIG_REGULATOR_MP886X is not set
# CONFIG_REGULATOR_MPQ7920 is not set
# CONFIG_REGULATOR_MT6311 is not set
# CONFIG_REGULATOR_MT6360 is not set
# CONFIG_REGULATOR_MT6370 is not set
# CONFIG_REGULATOR_PCA9450 is not set
# CONFIG_REGULATOR_PF9453 is not set
# CONFIG_REGULATOR_PF0900 is not set
# CONFIG_REGULATOR_PF530X is not set
# CONFIG_REGULATOR_PF8X00 is not set
# CONFIG_REGULATOR_PFUZE100 is not set
# CONFIG_REGULATOR_PV88060 is not set
# CONFIG_REGULATOR_PV88080 is not set
# CONFIG_REGULATOR_PV88090 is not set
# CONFIG_REGULATOR_RAA215300 is not set
# CONFIG_REGULATOR_RT4801 is not set
# CONFIG_REGULATOR_RT4803 is not set
# CONFIG_REGULATOR_RT5133 is not set
# CONFIG_REGULATOR_RT5190A is not set
# CONFIG_REGULATOR_RT5739 is not set
# CONFIG_REGULATOR_RT5759 is not set
# CONFIG_REGULATOR_RT6160 is not set
# CONFIG_REGULATOR_RT6190 is not set
# CONFIG_REGULATOR_RT6245 is not set
# CONFIG_REGULATOR_RT8092 is not set
# CONFIG_REGULATOR_RTQ2134 is not set
# CONFIG_REGULATOR_RTMV20 is not set
# CONFIG_REGULATOR_RTQ6752 is not set
# CONFIG_REGULATOR_RTQ2208 is not set
# CONFIG_REGULATOR_SGM3804 is not set
# CONFIG_REGULATOR_SLG51000 is not set
# CONFIG_REGULATOR_SY8106A is not set
# CONFIG_REGULATOR_SY8824X is not set
# CONFIG_REGULATOR_SY8827N is not set
# CONFIG_REGULATOR_TPS51632 is not set
# CONFIG_REGULATOR_TPS62360 is not set
# CONFIG_REGULATOR_TPS6286X is not set
# CONFIG_REGULATOR_TPS6287X is not set
# CONFIG_REGULATOR_TPS65023 is not set
# CONFIG_REGULATOR_TPS6507X is not set
# CONFIG_REGULATOR_TPS65132 is not set
# CONFIG_REGULATOR_TPS65185 is not set
# CONFIG_REGULATOR_TPS6524X is not set
CONFIG_REGULATOR_TWL4030=y
# CONFIG_REGULATOR_VCTRL is not set
CONFIG_RC_CORE=y
# CONFIG_LIRC is not set
# CONFIG_RC_MAP is not set
# CONFIG_RC_DECODERS is not set
CONFIG_RC_DEVICES=y
# CONFIG_IR_ENE is not set
# CONFIG_IR_FINTEK is not set
# CONFIG_IR_GPIO_CIR is not set
# CONFIG_IR_HIX5HD2 is not set
CONFIG_IR_IGORPLUGUSB=y
CONFIG_IR_IGUANA=y
CONFIG_IR_IMON=y
CONFIG_IR_IMON_RAW=y
# CONFIG_IR_ITE_CIR is not set
CONFIG_IR_MCEUSB=y
# CONFIG_IR_NUVOTON is not set
CONFIG_IR_REDRAT3=y
# CONFIG_IR_SERIAL is not set
CONFIG_IR_STREAMZAP=y
CONFIG_IR_TOY=y
CONFIG_IR_TTUSBIR=y
# CONFIG_IR_WINBOND_CIR is not set
CONFIG_RC_ATI_REMOTE=y
# CONFIG_RC_LOOPBACK is not set
CONFIG_RC_XBOX_DVD=y
CONFIG_CEC_CORE=y

#
# CEC support
#
# CONFIG_MEDIA_CEC_RC is not set
CONFIG_MEDIA_CEC_SUPPORT=y
# CONFIG_CEC_CH7322 is not set
# CONFIG_CEC_NXP_TDA9950 is not set
# CONFIG_CEC_GPIO is not set
# CONFIG_CEC_SECO is not set
# CONFIG_USB_EXTRON_DA_HD_4K_PLUS_CEC is not set
CONFIG_USB_PULSE8_CEC=y
CONFIG_USB_RAINSHADOW_CEC=y
# end of CEC support

CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_SUPPORT_FILTER=y
# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set

#
# Media device types
#
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
CONFIG_MEDIA_RADIO_SUPPORT=y
CONFIG_MEDIA_SDR_SUPPORT=y
CONFIG_MEDIA_PLATFORM_SUPPORT=y
CONFIG_MEDIA_TEST_SUPPORT=y
# end of Media device types

CONFIG_VIDEO_DEV=y
CONFIG_MEDIA_CONTROLLER=y
CONFIG_DVB_CORE=y

#
# Video4Linux options
#
CONFIG_VIDEO_V4L2_I2C=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_VIDEO_ADV_DEBUG is not set
# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
CONFIG_VIDEO_TUNER=y
CONFIG_V4L2_MEM2MEM_DEV=y
# end of Video4Linux options

#
# Media controller options
#
CONFIG_MEDIA_CONTROLLER_DVB=y
# end of Media controller options

#
# Digital TV options
#
# CONFIG_DVB_MMAP is not set
# CONFIG_DVB_NET is not set
CONFIG_DVB_MAX_ADAPTERS=16
# CONFIG_DVB_DYNAMIC_MINORS is not set
# CONFIG_DVB_DEMUX_SECTION_LOSS_LOG is not set
# CONFIG_DVB_ULE_DEBUG is not set
# end of Digital TV options

#
# Media drivers
#

#
# Drivers filtered as selected at 'Filter media drivers'
#

#
# Media drivers
#
CONFIG_MEDIA_USB_SUPPORT=y

#
# Webcam devices
#
CONFIG_USB_GSPCA=y
CONFIG_USB_GSPCA_BENQ=y
CONFIG_USB_GSPCA_CONEX=y
CONFIG_USB_GSPCA_CPIA1=y
CONFIG_USB_GSPCA_DTCS033=y
CONFIG_USB_GSPCA_ETOMS=y
CONFIG_USB_GSPCA_FINEPIX=y
CONFIG_USB_GSPCA_JEILINJ=y
CONFIG_USB_GSPCA_JL2005BCD=y
CONFIG_USB_GSPCA_KINECT=y
CONFIG_USB_GSPCA_KONICA=y
CONFIG_USB_GSPCA_MARS=y
CONFIG_USB_GSPCA_MR97310A=y
CONFIG_USB_GSPCA_NW80X=y
CONFIG_USB_GSPCA_OV519=y
CONFIG_USB_GSPCA_OV534=y
CONFIG_USB_GSPCA_OV534_9=y
CONFIG_USB_GSPCA_PAC207=y
CONFIG_USB_GSPCA_PAC7302=y
CONFIG_USB_GSPCA_PAC7311=y
CONFIG_USB_GSPCA_SE401=y
CONFIG_USB_GSPCA_SN9C2028=y
CONFIG_USB_GSPCA_SN9C20X=y
CONFIG_USB_GSPCA_SONIXB=y
CONFIG_USB_GSPCA_SONIXJ=y
CONFIG_USB_GSPCA_SPCA1528=y
CONFIG_USB_GSPCA_SPCA500=y
CONFIG_USB_GSPCA_SPCA501=y
CONFIG_USB_GSPCA_SPCA505=y
CONFIG_USB_GSPCA_SPCA506=y
CONFIG_USB_GSPCA_SPCA508=y
CONFIG_USB_GSPCA_SPCA561=y
CONFIG_USB_GSPCA_SQ905=y
CONFIG_USB_GSPCA_SQ905C=y
CONFIG_USB_GSPCA_SQ930X=y
CONFIG_USB_GSPCA_STK014=y
CONFIG_USB_GSPCA_STK1135=y
CONFIG_USB_GSPCA_STV0680=y
CONFIG_USB_GSPCA_SUNPLUS=y
CONFIG_USB_GSPCA_T613=y
CONFIG_USB_GSPCA_TOPRO=y
CONFIG_USB_GSPCA_TOUPTEK=y
CONFIG_USB_GSPCA_TV8532=y
CONFIG_USB_GSPCA_VC032X=y
CONFIG_USB_GSPCA_VICAM=y
CONFIG_USB_GSPCA_XIRLINK_CIT=y
CONFIG_USB_GSPCA_ZC3XX=y
CONFIG_USB_GL860=y
CONFIG_USB_M5602=y
CONFIG_USB_STV06XX=y
CONFIG_USB_PWC=y
# CONFIG_USB_PWC_DEBUG is not set
CONFIG_USB_PWC_INPUT_EVDEV=y
CONFIG_USB_S2255=y
CONFIG_VIDEO_USBTV=y
CONFIG_USB_VIDEO_CLASS=y
CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y

#
# Analog TV USB devices
#
CONFIG_VIDEO_GO7007=y
CONFIG_VIDEO_GO7007_USB=y
CONFIG_VIDEO_GO7007_LOADER=y
CONFIG_VIDEO_GO7007_USB_S2250_BOARD=y
CONFIG_VIDEO_HDPVR=y
CONFIG_VIDEO_PVRUSB2=y
CONFIG_VIDEO_PVRUSB2_SYSFS=y
CONFIG_VIDEO_PVRUSB2_DVB=y
# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
CONFIG_VIDEO_STK1160=y

#
# Analog/digital TV USB devices
#
CONFIG_VIDEO_AU0828=y
CONFIG_VIDEO_AU0828_V4L2=y
CONFIG_VIDEO_AU0828_RC=y
CONFIG_VIDEO_CX231XX=y
CONFIG_VIDEO_CX231XX_RC=y
CONFIG_VIDEO_CX231XX_ALSA=y
CONFIG_VIDEO_CX231XX_DVB=y

#
# Digital TV USB devices
#
CONFIG_DVB_AS102=y
CONFIG_DVB_B2C2_FLEXCOP_USB=y
# CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG is not set
CONFIG_DVB_USB_V2=y
CONFIG_DVB_USB_AF9015=y
CONFIG_DVB_USB_AF9035=y
CONFIG_DVB_USB_ANYSEE=y
CONFIG_DVB_USB_AU6610=y
CONFIG_DVB_USB_AZ6007=y
CONFIG_DVB_USB_CE6230=y
CONFIG_DVB_USB_DVBSKY=y
CONFIG_DVB_USB_EC168=y
CONFIG_DVB_USB_GL861=y
CONFIG_DVB_USB_LME2510=y
CONFIG_DVB_USB_MXL111SF=y
CONFIG_DVB_USB_RTL28XXU=y
CONFIG_DVB_USB_ZD1301=y
CONFIG_DVB_USB=y
# CONFIG_DVB_USB_DEBUG is not set
CONFIG_DVB_USB_A800=y
CONFIG_DVB_USB_AF9005=y
CONFIG_DVB_USB_AF9005_REMOTE=y
CONFIG_DVB_USB_AZ6027=y
CONFIG_DVB_USB_CINERGY_T2=y
CONFIG_DVB_USB_CXUSB=y
CONFIG_DVB_USB_CXUSB_ANALOG=y
CONFIG_DVB_USB_DIB0700=y
CONFIG_DVB_USB_DIB3000MC=y
CONFIG_DVB_USB_DIBUSB_MB=y
# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
CONFIG_DVB_USB_DIBUSB_MC=y
CONFIG_DVB_USB_DIGITV=y
CONFIG_DVB_USB_DTT200U=y
CONFIG_DVB_USB_DTV5100=y
CONFIG_DVB_USB_DW2102=y
CONFIG_DVB_USB_GP8PSK=y
CONFIG_DVB_USB_M920X=y
CONFIG_DVB_USB_NOVA_T_USB2=y
CONFIG_DVB_USB_OPERA1=y
CONFIG_DVB_USB_PCTV452E=y
CONFIG_DVB_USB_TECHNISAT_USB2=y
CONFIG_DVB_USB_TTUSB2=y
CONFIG_DVB_USB_UMT_010=y
CONFIG_DVB_USB_VP702X=y
CONFIG_DVB_USB_VP7045=y
CONFIG_SMS_USB_DRV=y
CONFIG_DVB_TTUSB_BUDGET=y
CONFIG_DVB_TTUSB_DEC=y

#
# Webcam, TV (analog/digital) USB devices
#
CONFIG_VIDEO_EM28XX=y
CONFIG_VIDEO_EM28XX_V4L2=y
CONFIG_VIDEO_EM28XX_ALSA=y
CONFIG_VIDEO_EM28XX_DVB=y
CONFIG_VIDEO_EM28XX_RC=y

#
# Software defined radio USB devices
#
CONFIG_USB_AIRSPY=y
CONFIG_USB_HACKRF=y
CONFIG_USB_MSI2500=y
# CONFIG_MEDIA_PCI_SUPPORT is not set
CONFIG_RADIO_ADAPTERS=y
# CONFIG_RADIO_MAXIRADIO is not set
# CONFIG_RADIO_SAA7706H is not set
CONFIG_RADIO_SHARK=y
CONFIG_RADIO_SHARK2=y
CONFIG_RADIO_SI4713=y
CONFIG_RADIO_TEA575X=y
# CONFIG_RADIO_TEA5764 is not set
# CONFIG_RADIO_TEF6862 is not set
CONFIG_USB_DSBR=y
CONFIG_USB_KEENE=y
CONFIG_USB_MA901=y
CONFIG_USB_MR800=y
CONFIG_USB_RAREMONO=y
CONFIG_RADIO_SI470X=y
CONFIG_USB_SI470X=y
# CONFIG_I2C_SI470X is not set
CONFIG_USB_SI4713=y
# CONFIG_PLATFORM_SI4713 is not set
CONFIG_I2C_SI4713=y
# CONFIG_MEDIA_PLATFORM_DRIVERS is not set

#
# MMC/SDIO DVB adapters
#
CONFIG_SMS_SDIO_DRV=y
CONFIG_V4L_TEST_DRIVERS=y
CONFIG_VIDEO_VIM2M=y
CONFIG_VIDEO_VICODEC=y
CONFIG_VIDEO_VIMC=y
CONFIG_VIDEO_VIVID=y
CONFIG_VIDEO_VIVID_CEC=y
# CONFIG_VIDEO_VIVID_OSD is not set
CONFIG_VIDEO_VIVID_MAX_DEVS=64
# CONFIG_VIDEO_VISL is not set
CONFIG_DVB_TEST_DRIVERS=y
CONFIG_DVB_VIDTV=y

#
# FireWire (IEEE 1394) Adapters
#
# CONFIG_DVB_FIREDTV is not set
CONFIG_MEDIA_COMMON_OPTIONS=y

#
# common driver options
#
CONFIG_CYPRESS_FIRMWARE=y
CONFIG_TTPCI_EEPROM=y
CONFIG_UVC_COMMON=y
CONFIG_VIDEO_CX2341X=y
CONFIG_VIDEO_TVEEPROM=y
CONFIG_DVB_B2C2_FLEXCOP=y
CONFIG_SMS_SIANO_MDTV=y
CONFIG_SMS_SIANO_RC=y
CONFIG_SMS_SIANO_DEBUGFS=y
CONFIG_VIDEO_V4L2_TPG=y
CONFIG_VIDEOBUF2_CORE=y
CONFIG_VIDEOBUF2_V4L2=y
CONFIG_VIDEOBUF2_MEMOPS=y
CONFIG_VIDEOBUF2_DMA_CONTIG=y
CONFIG_VIDEOBUF2_VMALLOC=y
CONFIG_VIDEOBUF2_DMA_SG=y
# end of Media drivers

#
# Media ancillary drivers
#
CONFIG_MEDIA_ATTACH=y
# CONFIG_VIDEO_IR_I2C is not set
# CONFIG_VIDEO_CAMERA_SENSOR is not set

#
# Camera ISPs
#
# CONFIG_VIDEO_THP7312 is not set
# end of Camera ISPs

# CONFIG_VIDEO_CAMERA_LENS is not set

#
# Flash devices
#
# CONFIG_VIDEO_ADP1653 is not set
# CONFIG_VIDEO_LM3560 is not set
# CONFIG_VIDEO_LM3646 is not set
# end of Flash devices

#
# Audio decoders, processors and mixers
#
# CONFIG_VIDEO_CS3308 is not set
# CONFIG_VIDEO_CS5345 is not set
CONFIG_VIDEO_CS53L32A=y
CONFIG_VIDEO_MSP3400=y
# CONFIG_VIDEO_SONY_BTF_MPX is not set
# CONFIG_VIDEO_TDA1997X is not set
# CONFIG_VIDEO_TDA7432 is not set
# CONFIG_VIDEO_TDA9840 is not set
# CONFIG_VIDEO_TEA6415C is not set
# CONFIG_VIDEO_TEA6420 is not set
# CONFIG_VIDEO_TLV320AIC23B is not set
# CONFIG_VIDEO_TVAUDIO is not set
# CONFIG_VIDEO_UDA1342 is not set
# CONFIG_VIDEO_VP27SMPX is not set
# CONFIG_VIDEO_WM8739 is not set
CONFIG_VIDEO_WM8775=y
# end of Audio decoders, processors and mixers

#
# RDS decoders
#
# CONFIG_VIDEO_SAA6588 is not set
# end of RDS decoders

#
# Video decoders
#
# CONFIG_VIDEO_ADV7180 is not set
# CONFIG_VIDEO_ADV7183 is not set
# CONFIG_VIDEO_ADV748X is not set
# CONFIG_VIDEO_ADV7604 is not set
# CONFIG_VIDEO_ADV7842 is not set
# CONFIG_VIDEO_BT819 is not set
# CONFIG_VIDEO_BT856 is not set
# CONFIG_VIDEO_BT866 is not set
# CONFIG_VIDEO_ISL7998X is not set
# CONFIG_VIDEO_LT6911UXE is not set
# CONFIG_VIDEO_KS0127 is not set
# CONFIG_VIDEO_MAX9286 is not set
# CONFIG_VIDEO_ML86V7667 is not set
# CONFIG_VIDEO_SAA7110 is not set
CONFIG_VIDEO_SAA711X=y
# CONFIG_VIDEO_TC358743 is not set
# CONFIG_VIDEO_TC358746 is not set
# CONFIG_VIDEO_TVP514X is not set
# CONFIG_VIDEO_TVP5150 is not set
# CONFIG_VIDEO_TVP7002 is not set
# CONFIG_VIDEO_TW2804 is not set
# CONFIG_VIDEO_TW9900 is not set
# CONFIG_VIDEO_TW9903 is not set
# CONFIG_VIDEO_TW9906 is not set
# CONFIG_VIDEO_TW9910 is not set
# CONFIG_VIDEO_VPX3220 is not set

#
# Video and audio decoders
#
# CONFIG_VIDEO_SAA717X is not set
CONFIG_VIDEO_CX25840=y
# end of Video decoders

#
# Video encoders
#
# CONFIG_VIDEO_ADV7170 is not set
# CONFIG_VIDEO_ADV7175 is not set
# CONFIG_VIDEO_ADV7343 is not set
# CONFIG_VIDEO_ADV7393 is not set
# CONFIG_VIDEO_ADV7511 is not set
# CONFIG_VIDEO_AK881X is not set
# CONFIG_VIDEO_SAA7127 is not set
# CONFIG_VIDEO_SAA7185 is not set
# CONFIG_VIDEO_THS8200 is not set
# end of Video encoders

#
# Video improvement chips
#
# CONFIG_VIDEO_UPD64031A is not set
# CONFIG_VIDEO_UPD64083 is not set
# end of Video improvement chips

#
# Audio/Video compression chips
#
# CONFIG_VIDEO_SAA6752HS is not set
# end of Audio/Video compression chips

#
# SDR tuner chips
#
# CONFIG_SDR_MAX2175 is not set
# end of SDR tuner chips

#
# Miscellaneous helper chips
#
# CONFIG_VIDEO_INTEL_CVS is not set
# CONFIG_VIDEO_I2C is not set
# CONFIG_VIDEO_M52790 is not set
# CONFIG_VIDEO_ST_MIPID02 is not set
# CONFIG_VIDEO_THS7303 is not set
# end of Miscellaneous helper chips

#
# Video serializers and deserializers
#
# CONFIG_VIDEO_DS90UB913 is not set
# CONFIG_VIDEO_DS90UB953 is not set
# CONFIG_VIDEO_DS90UB960 is not set
# CONFIG_VIDEO_MAX96714 is not set
# CONFIG_VIDEO_MAX96717 is not set
# end of Video serializers and deserializers

#
# Media SPI Adapters
#
# CONFIG_CXD2880_SPI_DRV is not set
# CONFIG_VIDEO_GS1662 is not set
# end of Media SPI Adapters

CONFIG_MEDIA_TUNER=y

#
# Customize TV tuners
#
# CONFIG_MEDIA_TUNER_E4000 is not set
# CONFIG_MEDIA_TUNER_FC0011 is not set
# CONFIG_MEDIA_TUNER_FC0012 is not set
# CONFIG_MEDIA_TUNER_FC0013 is not set
# CONFIG_MEDIA_TUNER_FC2580 is not set
# CONFIG_MEDIA_TUNER_IT913X is not set
# CONFIG_MEDIA_TUNER_M88RS6000T is not set
# CONFIG_MEDIA_TUNER_MAX2165 is not set
# CONFIG_MEDIA_TUNER_MC44S803 is not set
CONFIG_MEDIA_TUNER_MSI001=y
# CONFIG_MEDIA_TUNER_MT2060 is not set
# CONFIG_MEDIA_TUNER_MT2063 is not set
# CONFIG_MEDIA_TUNER_MT20XX is not set
# CONFIG_MEDIA_TUNER_MT2131 is not set
# CONFIG_MEDIA_TUNER_MT2266 is not set
# CONFIG_MEDIA_TUNER_MXL301RF is not set
# CONFIG_MEDIA_TUNER_MXL5005S is not set
# CONFIG_MEDIA_TUNER_MXL5007T is not set
# CONFIG_MEDIA_TUNER_QM1D1B0004 is not set
# CONFIG_MEDIA_TUNER_QM1D1C0042 is not set
# CONFIG_MEDIA_TUNER_QT1010 is not set
# CONFIG_MEDIA_TUNER_R820T is not set
# CONFIG_MEDIA_TUNER_SI2157 is not set
# CONFIG_MEDIA_TUNER_SIMPLE is not set
# CONFIG_MEDIA_TUNER_TDA18212 is not set
# CONFIG_MEDIA_TUNER_TDA18218 is not set
# CONFIG_MEDIA_TUNER_TDA18250 is not set
# CONFIG_MEDIA_TUNER_TDA18271 is not set
# CONFIG_MEDIA_TUNER_TDA827X is not set
# CONFIG_MEDIA_TUNER_TDA8290 is not set
# CONFIG_MEDIA_TUNER_TDA9887 is not set
# CONFIG_MEDIA_TUNER_TEA5761 is not set
# CONFIG_MEDIA_TUNER_TEA5767 is not set
# CONFIG_MEDIA_TUNER_TUA9001 is not set
# CONFIG_MEDIA_TUNER_XC2028 is not set
# CONFIG_MEDIA_TUNER_XC4000 is not set
# CONFIG_MEDIA_TUNER_XC5000 is not set
# end of Customize TV tuners

#
# Customise DVB Frontends
#

#
# Multistandard (satellite) frontends
#
# CONFIG_DVB_M88DS3103 is not set
# CONFIG_DVB_MXL5XX is not set
# CONFIG_DVB_STB0899 is not set
# CONFIG_DVB_STB6100 is not set
# CONFIG_DVB_STV090x is not set
# CONFIG_DVB_STV0910 is not set
# CONFIG_DVB_STV6110x is not set
# CONFIG_DVB_STV6111 is not set

#
# Multistandard (cable + terrestrial) frontends
#
# CONFIG_DVB_DRXK is not set
# CONFIG_DVB_MN88472 is not set
# CONFIG_DVB_MN88473 is not set
# CONFIG_DVB_SI2165 is not set
# CONFIG_DVB_TDA18271C2DD is not set

#
# DVB-S (satellite) frontends
#
# CONFIG_DVB_CX24110 is not set
# CONFIG_DVB_CX24116 is not set
# CONFIG_DVB_CX24117 is not set
# CONFIG_DVB_CX24120 is not set
# CONFIG_DVB_CX24123 is not set
# CONFIG_DVB_DS3000 is not set
# CONFIG_DVB_MB86A16 is not set
# CONFIG_DVB_MT312 is not set
# CONFIG_DVB_S5H1420 is not set
# CONFIG_DVB_SI21XX is not set
# CONFIG_DVB_STB6000 is not set
# CONFIG_DVB_STV0288 is not set
# CONFIG_DVB_STV0299 is not set
# CONFIG_DVB_STV0900 is not set
# CONFIG_DVB_STV6110 is not set
# CONFIG_DVB_TDA10071 is not set
# CONFIG_DVB_TDA10086 is not set
# CONFIG_DVB_TDA8083 is not set
# CONFIG_DVB_TDA8261 is not set
# CONFIG_DVB_TDA826X is not set
# CONFIG_DVB_TS2020 is not set
# CONFIG_DVB_TUA6100 is not set
# CONFIG_DVB_TUNER_CX24113 is not set
# CONFIG_DVB_TUNER_ITD1000 is not set
# CONFIG_DVB_VES1X93 is not set
# CONFIG_DVB_ZL10036 is not set
# CONFIG_DVB_ZL10039 is not set

#
# DVB-T (terrestrial) frontends
#
CONFIG_DVB_AF9013=y
CONFIG_DVB_AS102_FE=y
# CONFIG_DVB_CX22700 is not set
# CONFIG_DVB_CX22702 is not set
# CONFIG_DVB_CXD2820R is not set
# CONFIG_DVB_CXD2841ER is not set
CONFIG_DVB_DIB3000MB=y
CONFIG_DVB_DIB3000MC=y
# CONFIG_DVB_DIB7000M is not set
# CONFIG_DVB_DIB7000P is not set
# CONFIG_DVB_DIB9000 is not set
# CONFIG_DVB_DRXD is not set
CONFIG_DVB_EC100=y
CONFIG_DVB_GP8PSK_FE=y
# CONFIG_DVB_L64781 is not set
# CONFIG_DVB_MT352 is not set
# CONFIG_DVB_NXT6000 is not set
CONFIG_DVB_RTL2830=y
CONFIG_DVB_RTL2832=y
CONFIG_DVB_RTL2832_SDR=y
# CONFIG_DVB_S5H1432 is not set
# CONFIG_DVB_SI2168 is not set
# CONFIG_DVB_SP887X is not set
# CONFIG_DVB_STV0367 is not set
# CONFIG_DVB_TDA10048 is not set
# CONFIG_DVB_TDA1004X is not set
# CONFIG_DVB_ZD1301_DEMOD is not set
CONFIG_DVB_ZL10353=y
# CONFIG_DVB_CXD2880 is not set

#
# DVB-C (cable) frontends
#
# CONFIG_DVB_STV0297 is not set
# CONFIG_DVB_TDA10021 is not set
# CONFIG_DVB_TDA10023 is not set
# CONFIG_DVB_VES1820 is not set

#
# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
#
# CONFIG_DVB_AU8522_DTV is not set
# CONFIG_DVB_AU8522_V4L is not set
# CONFIG_DVB_BCM3510 is not set
# CONFIG_DVB_LG2160 is not set
# CONFIG_DVB_LGDT3305 is not set
# CONFIG_DVB_LGDT3306A is not set
# CONFIG_DVB_LGDT330X is not set
# CONFIG_DVB_MXL692 is not set
# CONFIG_DVB_NXT200X is not set
# CONFIG_DVB_OR51132 is not set
# CONFIG_DVB_OR51211 is not set
# CONFIG_DVB_S5H1409 is not set
# CONFIG_DVB_S5H1411 is not set

#
# ISDB-T (terrestrial) frontends
#
# CONFIG_DVB_DIB8000 is not set
# CONFIG_DVB_MB86A20S is not set
# CONFIG_DVB_S921 is not set

#
# ISDB-S (satellite) & ISDB-T (terrestrial) frontends
#
# CONFIG_DVB_MN88443X is not set
# CONFIG_DVB_TC90522 is not set

#
# Digital terrestrial only tuners/PLL
#
# CONFIG_DVB_PLL is not set
# CONFIG_DVB_TUNER_DIB0070 is not set
# CONFIG_DVB_TUNER_DIB0090 is not set

#
# SEC control devices for DVB-S
#
# CONFIG_DVB_A8293 is not set
CONFIG_DVB_AF9033=y
# CONFIG_DVB_ASCOT2E is not set
# CONFIG_DVB_ATBM8830 is not set
# CONFIG_DVB_HELENE is not set
# CONFIG_DVB_HORUS3A is not set
# CONFIG_DVB_ISL6405 is not set
# CONFIG_DVB_ISL6421 is not set
# CONFIG_DVB_ISL6423 is not set
# CONFIG_DVB_IX2505V is not set
# CONFIG_DVB_LGS8GL5 is not set
# CONFIG_DVB_LGS8GXX is not set
# CONFIG_DVB_LNBH25 is not set
# CONFIG_DVB_LNBH29 is not set
# CONFIG_DVB_LNBP21 is not set
# CONFIG_DVB_LNBP22 is not set
# CONFIG_DVB_M88RS2000 is not set
# CONFIG_DVB_TDA665x is not set
# CONFIG_DVB_DRX39XYJ is not set

#
# Common Interface (EN50221) controller drivers
#
# CONFIG_DVB_CXD2099 is not set
# CONFIG_DVB_SP2 is not set
# end of Customise DVB Frontends

#
# Tools to develop new frontends
#
# CONFIG_DVB_DUMMY_FE is not set
# end of Media ancillary drivers

#
# Graphics support
#
CONFIG_APERTURE_HELPERS=y
CONFIG_SCREEN_INFO=y
CONFIG_VIDEO=y
# CONFIG_AUXDISPLAY is not set
# CONFIG_PANEL is not set
CONFIG_AGP=y
CONFIG_AGP_AMD64=y
CONFIG_AGP_INTEL=y
# CONFIG_AGP_SIS is not set
# CONFIG_AGP_VIA is not set
CONFIG_INTEL_GTT=y
# CONFIG_VGA_SWITCHEROO is not set
CONFIG_DRM=y

#
# DRM debugging options
#
# CONFIG_DRM_WERROR is not set
CONFIG_DRM_DEBUG_MM=y
# end of DRM debugging options

CONFIG_DRM_KMS_HELPER=y
# CONFIG_DRM_PANIC is not set
# CONFIG_DRM_RAS is not set
# CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS is not set
# CONFIG_DRM_DEBUG_MODESET_LOCK is not set
CONFIG_DRM_CLIENT=y
CONFIG_DRM_CLIENT_LIB=y
CONFIG_DRM_CLIENT_SELECTION=y
CONFIG_DRM_CLIENT_SETUP=y

#
# Supported DRM clients
#
CONFIG_DRM_FBDEV_EMULATION=y
CONFIG_DRM_FBDEV_OVERALLOC=100
# CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM is not set
# CONFIG_DRM_CLIENT_LOG is not set
CONFIG_DRM_CLIENT_DEFAULT_FBDEV=y
CONFIG_DRM_CLIENT_DEFAULT="fbdev"
# end of Supported DRM clients

# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set
CONFIG_DRM_DISPLAY_DP_AUX_BUS=y
CONFIG_DRM_DISPLAY_HELPER=y
# CONFIG_DRM_DISPLAY_DP_AUX_CEC is not set
# CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV is not set
CONFIG_DRM_DISPLAY_DP_HELPER=y
CONFIG_DRM_TTM=y
CONFIG_DRM_TTM_HELPER=y
CONFIG_DRM_GEM_SHMEM_HELPER=y
# CONFIG_DRM_AMDGPU is not set

#
# ARM devices
#
# CONFIG_DRM_KOMEDA is not set
# end of ARM devices

# CONFIG_DRM_AST is not set
CONFIG_DRM_BRIDGE=y
CONFIG_DRM_PANEL_BRIDGE=y
CONFIG_DRM_AUX_BRIDGE=y
CONFIG_DRM_AUX_HPD_BRIDGE=y

#
# Display Interface Bridges
#
# CONFIG_DRM_CHIPONE_ICN6211 is not set
# CONFIG_DRM_CHRONTEL_CH7033 is not set
# CONFIG_DRM_DISPLAY_CONNECTOR is not set
# CONFIG_DRM_I2C_NXP_TDA998X is not set
# CONFIG_DRM_ITE_IT6263 is not set
# CONFIG_DRM_ITE_IT6505 is not set
# CONFIG_DRM_LONTIUM_LT8912B is not set
# CONFIG_DRM_LONTIUM_LT9211 is not set
# CONFIG_DRM_LONTIUM_LT9611 is not set
# CONFIG_DRM_LONTIUM_LT9611UXC is not set
# CONFIG_DRM_LONTIUM_LT8713SX is not set
# CONFIG_DRM_ITE_IT66121 is not set
# CONFIG_DRM_LVDS_CODEC is not set
# CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW is not set
# CONFIG_DRM_NWL_MIPI_DSI is not set
# CONFIG_DRM_NXP_PTN3460 is not set
# CONFIG_DRM_PARADE_PS8622 is not set
# CONFIG_DRM_PARADE_PS8640 is not set
# CONFIG_DRM_SAMSUNG_DSIM is not set
# CONFIG_DRM_SIL_SII8620 is not set
# CONFIG_DRM_SII902X is not set
# CONFIG_DRM_SII9234 is not set
# CONFIG_DRM_SIMPLE_BRIDGE is not set
# CONFIG_DRM_SOLOMON_SSD2825 is not set
# CONFIG_DRM_THINE_THC63LVD1024 is not set
# CONFIG_DRM_TOSHIBA_TC358762 is not set
# CONFIG_DRM_TOSHIBA_TC358764 is not set
# CONFIG_DRM_TOSHIBA_TC358767 is not set
# CONFIG_DRM_TOSHIBA_TC358768 is not set
# CONFIG_DRM_TOSHIBA_TC358775 is not set
# CONFIG_DRM_TI_DLPC3433 is not set
# CONFIG_DRM_TI_TDP158 is not set
# CONFIG_DRM_TI_TFP410 is not set
# CONFIG_DRM_TI_SN65DSI83 is not set
# CONFIG_DRM_TI_SN65DSI86 is not set
# CONFIG_DRM_TI_TPD12S015 is not set
# CONFIG_DRM_WAVESHARE_BRIDGE is not set
# CONFIG_DRM_ANALOGIX_ANX6345 is not set
# CONFIG_DRM_ANALOGIX_ANX78XX is not set
# CONFIG_DRM_ANALOGIX_ANX7625 is not set
# CONFIG_DRM_I2C_ADV7511 is not set
# CONFIG_DRM_CDNS_DSI is not set
# CONFIG_DRM_CDNS_MHDP8546 is not set
# end of Display Interface Bridges

# CONFIG_DRM_ETNAVIV is not set
# CONFIG_DRM_GMA500 is not set
CONFIG_DRM_GUD=y
# CONFIG_DRM_HISI_HIBMC is not set
# CONFIG_DRM_LOGICVC is not set
# CONFIG_DRM_MGAG200 is not set
# CONFIG_DRM_NOUVEAU is not set
CONFIG_DRM_PANEL=y

#
# Display Panels
#
# CONFIG_DRM_PANEL_ABT_Y030XX067A is not set
# CONFIG_DRM_PANEL_ARM_VERSATILE is not set
# CONFIG_DRM_PANEL_AUO_A030JTN01 is not set
# CONFIG_DRM_PANEL_LVDS is not set
# CONFIG_DRM_PANEL_ILITEK_IL9322 is not set
# CONFIG_DRM_PANEL_ILITEK_ILI9341 is not set
# CONFIG_DRM_PANEL_ILITEK_ILI9806E_SPI is not set
# CONFIG_DRM_PANEL_INNOLUX_EJ030NA is not set
# CONFIG_DRM_PANEL_LG_LB035Q02 is not set
# CONFIG_DRM_PANEL_LG_LG4573 is not set
# CONFIG_DRM_PANEL_NEC_NL8048HL11 is not set
# CONFIG_DRM_PANEL_NEWVISION_NV3052C is not set
# CONFIG_DRM_PANEL_NOVATEK_NT39016 is not set
# CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO is not set
# CONFIG_DRM_PANEL_ORISETECH_OTA5601A is not set
# CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01 is not set
# CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20 is not set
# CONFIG_DRM_PANEL_SAMSUNG_DB7430 is not set
# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set
# CONFIG_DRM_PANEL_SAMSUNG_S6D27A1 is not set
# CONFIG_DRM_PANEL_SAMSUNG_S6D7AA0 is not set
# CONFIG_DRM_PANEL_SAMSUNG_S6E63M0 is not set
# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set
# CONFIG_DRM_PANEL_SAMSUNG_S6E8FC0 is not set
# CONFIG_DRM_PANEL_SEIKO_43WVF1G is not set
# CONFIG_DRM_PANEL_SHARP_LS037V7DW01 is not set
# CONFIG_DRM_PANEL_SITRONIX_ST7701 is not set
# CONFIG_DRM_PANEL_SITRONIX_ST7789V is not set
# CONFIG_DRM_PANEL_SONY_ACX565AKM is not set
CONFIG_DRM_PANEL_EDP=y
# CONFIG_DRM_PANEL_SIMPLE is not set
# CONFIG_DRM_PANEL_TPO_TD028TTEC1 is not set
# CONFIG_DRM_PANEL_TPO_TD043MTEA1 is not set
# CONFIG_DRM_PANEL_TPO_TPG110 is not set
# CONFIG_DRM_PANEL_WIDECHIPS_WS2401 is not set
# end of Display Panels

# CONFIG_DRM_QXL is not set
# CONFIG_DRM_RADEON is not set
# CONFIG_DRM_ST7571 is not set
# CONFIG_DRM_ST7586 is not set
# CONFIG_DRM_ST7735R is not set
# CONFIG_DRM_ST7920 is not set
# CONFIG_DRM_SSD130X is not set

#
# Drivers for system framebuffers
#
CONFIG_DRM_SYSFB_HELPER=y
CONFIG_DRM_SIMPLEDRM=y
# CONFIG_DRM_VESADRM is not set
# end of Drivers for system framebuffers

# CONFIG_DRM_APPLETBDRM is not set
# CONFIG_DRM_ARCPGU is not set
CONFIG_DRM_BOCHS=y
CONFIG_DRM_CIRRUS_QEMU=y
CONFIG_DRM_GM12U320=y
# CONFIG_DRM_PANEL_MIPI_DBI is not set
# CONFIG_DRM_PIXPAPER is not set
# CONFIG_TINYDRM_HX8357D is not set
# CONFIG_TINYDRM_ILI9163 is not set
# CONFIG_TINYDRM_ILI9225 is not set
# CONFIG_TINYDRM_ILI9341 is not set
# CONFIG_TINYDRM_ILI9486 is not set
# CONFIG_TINYDRM_MI0283QT is not set
# CONFIG_TINYDRM_REPAPER is not set
# CONFIG_TINYDRM_SHARP_MEMORY is not set
CONFIG_DRM_UDL=y
# CONFIG_DRM_VBOXVIDEO is not set
CONFIG_DRM_VGEM=y
CONFIG_DRM_VIRTIO_GPU=y
CONFIG_DRM_VIRTIO_GPU_KMS=y
CONFIG_DRM_VKMS=y
CONFIG_DRM_VMWGFX=y
# CONFIG_DRM_VMWGFX_MKSSTATS is not set
# CONFIG_DRM_XE is not set
CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y

#
# Frame buffer Devices
#
CONFIG_FB=y
# CONFIG_FB_CIRRUS is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
# CONFIG_FB_ARC is not set
# CONFIG_FB_ASILIANT is not set
# CONFIG_FB_IMSTT is not set
CONFIG_FB_VGA16=y
# CONFIG_FB_UVESA is not set
CONFIG_FB_VESA=y
# CONFIG_FB_N411 is not set
# CONFIG_FB_OPENCORES is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_I740 is not set
# CONFIG_FB_MATROX is not set
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
# CONFIG_FB_S3 is not set
# CONFIG_FB_SAVAGE is not set
# CONFIG_FB_SIS is not set
# CONFIG_FB_VIA is not set
# CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_KYRO is not set
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
# CONFIG_FB_VT8623 is not set
# CONFIG_FB_TRIDENT is not set
# CONFIG_FB_ARK is not set
# CONFIG_FB_PM3 is not set
# CONFIG_FB_CARMINE is not set
# CONFIG_FB_SMSCUFX is not set
# CONFIG_FB_UDL is not set
# CONFIG_FB_IBM_GXT4500 is not set
CONFIG_FB_VIRTUAL=y
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_MB862XX is not set
# CONFIG_FB_SSD1307 is not set
# CONFIG_FB_SM712 is not set
CONFIG_FB_CORE=y
CONFIG_FB_NOTIFY=y
CONFIG_FB_DEVICE=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
CONFIG_FB_SYS_FILLRECT=y
CONFIG_FB_SYS_COPYAREA=y
CONFIG_FB_SYS_IMAGEBLIT=y
# CONFIG_FB_FOREIGN_ENDIAN is not set
CONFIG_FB_SYSMEM_FOPS=y
CONFIG_FB_DEFERRED_IO=y
CONFIG_FB_IOMEM_FOPS=y
CONFIG_FB_IOMEM_HELPERS=y
CONFIG_FB_SYSMEM_HELPERS=y
CONFIG_FB_SYSMEM_HELPERS_DEFERRED=y
CONFIG_FB_TILEBLITTING=y
# end of Frame buffer Devices

#
# Backlight & LCD device support
#
CONFIG_LCD_CLASS_DEVICE=y
# CONFIG_LCD_L4F00242T03 is not set
# CONFIG_LCD_LMS283GF05 is not set
# CONFIG_LCD_LTV350QV is not set
# CONFIG_LCD_ILI922X is not set
# CONFIG_LCD_ILI9320 is not set
# CONFIG_LCD_TDO24M is not set
# CONFIG_LCD_VGG2432A4 is not set
# CONFIG_LCD_PLATFORM is not set
# CONFIG_LCD_AMS369FG06 is not set
# CONFIG_LCD_LMS501KF03 is not set
# CONFIG_LCD_HX8357 is not set
# CONFIG_LCD_OTM3225A is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=y
# CONFIG_BACKLIGHT_AW99706 is not set
# CONFIG_BACKLIGHT_KTD253 is not set
# CONFIG_BACKLIGHT_KTD2801 is not set
# CONFIG_BACKLIGHT_KTZ8866 is not set
# CONFIG_BACKLIGHT_MAX25014 is not set
# CONFIG_BACKLIGHT_MT6370 is not set
# CONFIG_BACKLIGHT_APPLE is not set
# CONFIG_BACKLIGHT_QCOM_WLED is not set
# CONFIG_BACKLIGHT_SAHARA is not set
# CONFIG_BACKLIGHT_ADP8860 is not set
# CONFIG_BACKLIGHT_ADP8870 is not set
# CONFIG_BACKLIGHT_LM3509 is not set
# CONFIG_BACKLIGHT_LM3639 is not set
# CONFIG_BACKLIGHT_PANDORA is not set
# CONFIG_BACKLIGHT_GPIO is not set
# CONFIG_BACKLIGHT_LV5207LP is not set
# CONFIG_BACKLIGHT_BD6107 is not set
# CONFIG_BACKLIGHT_ARCXCNN is not set
# CONFIG_BACKLIGHT_LED is not set
# end of Backlight & LCD device support

CONFIG_VGASTATE=y
CONFIG_VIDEOMODE_HELPERS=y
CONFIG_HDMI=y
# CONFIG_FIRMWARE_EDID is not set

#
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
CONFIG_DUMMY_CONSOLE=y
CONFIG_DUMMY_CONSOLE_COLUMNS=80
CONFIG_DUMMY_CONSOLE_ROWS=25
CONFIG_FRAMEBUFFER_CONSOLE=y
# CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION is not set
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
# CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set
# end of Console display driver support

CONFIG_LOGO=y
CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_MONO_FILE="drivers/video/logo/logo_linux_mono.pbm"
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_VGA16_FILE="drivers/video/logo/logo_linux_vga16.ppm"
# CONFIG_LOGO_LINUX_CLUT224 is not set
# CONFIG_TRACE_GPU_MEM is not set
# end of Graphics support

# CONFIG_DRM_ACCEL is not set
CONFIG_SOUND=y
CONFIG_SOUND_OSS_CORE=y
CONFIG_SOUND_OSS_CORE_PRECLAIM=y
CONFIG_SND=y
CONFIG_SND_TIMER=y
CONFIG_SND_PCM=y
CONFIG_SND_HWDEP=y
CONFIG_SND_SEQ_DEVICE=y
CONFIG_SND_RAWMIDI=y
CONFIG_SND_UMP=y
CONFIG_SND_UMP_LEGACY_RAWMIDI=y
CONFIG_SND_JACK=y
CONFIG_SND_JACK_INPUT_DEV=y
CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
CONFIG_SND_PCM_OSS_PLUGINS=y
CONFIG_SND_PCM_TIMER=y
CONFIG_SND_HRTIMER=y
# CONFIG_SND_DYNAMIC_MINORS is not set
# CONFIG_SND_SUPPORT_OLD_API is not set
CONFIG_SND_PROC_FS=y
CONFIG_SND_VERBOSE_PROCFS=y
CONFIG_SND_CTL_FAST_LOOKUP=y
CONFIG_SND_DEBUG=y
# CONFIG_SND_DEBUG_VERBOSE is not set
CONFIG_SND_PCM_XRUN_DEBUG=y
# CONFIG_SND_CTL_INPUT_VALIDATION is not set
# CONFIG_SND_CTL_DEBUG is not set
# CONFIG_SND_JACK_INJECTION_DEBUG is not set
# CONFIG_SND_UTIMER is not set
CONFIG_SND_VMASTER=y
CONFIG_SND_DMA_SGBUF=y
CONFIG_SND_CTL_LED=y
CONFIG_SND_SEQUENCER=y
CONFIG_SND_SEQ_DUMMY=y
CONFIG_SND_SEQUENCER_OSS=y
CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
CONFIG_SND_SEQ_MIDI_EVENT=y
CONFIG_SND_SEQ_MIDI=y
CONFIG_SND_SEQ_VIRMIDI=y
# CONFIG_SND_SEQ_UMP is not set
CONFIG_SND_DRIVERS=y
# CONFIG_SND_PCSP is not set
CONFIG_SND_DUMMY=y
CONFIG_SND_ALOOP=y
# CONFIG_SND_PCMTEST is not set
CONFIG_SND_VIRMIDI=y
# CONFIG_SND_MTPAV is not set
# CONFIG_SND_MTS64 is not set
# CONFIG_SND_SERIAL_U16550 is not set
# CONFIG_SND_SERIAL_GENERIC is not set
# CONFIG_SND_MPU401 is not set
# CONFIG_SND_PORTMAN2X4 is not set
CONFIG_SND_PCI=y
# CONFIG_SND_AD1889 is not set
# CONFIG_SND_ALS300 is not set
# CONFIG_SND_ALS4000 is not set
# CONFIG_SND_ALI5451 is not set
# CONFIG_SND_ASIHPI is not set
# CONFIG_SND_ATIIXP is not set
# CONFIG_SND_ATIIXP_MODEM is not set
# CONFIG_SND_AU8810 is not set
# CONFIG_SND_AU8820 is not set
# CONFIG_SND_AU8830 is not set
# CONFIG_SND_AW2 is not set
# CONFIG_SND_AZT3328 is not set
# CONFIG_SND_BT87X is not set
# CONFIG_SND_CA0106 is not set
# CONFIG_SND_CMIPCI is not set
# CONFIG_SND_OXYGEN is not set
# CONFIG_SND_CS4281 is not set
# CONFIG_SND_CS46XX is not set
# CONFIG_SND_CTXFI is not set
# CONFIG_SND_DARLA20 is not set
# CONFIG_SND_GINA20 is not set
# CONFIG_SND_LAYLA20 is not set
# CONFIG_SND_DARLA24 is not set
# CONFIG_SND_GINA24 is not set
# CONFIG_SND_LAYLA24 is not set
# CONFIG_SND_MONA is not set
# CONFIG_SND_MIA is not set
# CONFIG_SND_ECHO3G is not set
# CONFIG_SND_INDIGO is not set
# CONFIG_SND_INDIGOIO is not set
# CONFIG_SND_INDIGODJ is not set
# CONFIG_SND_INDIGOIOX is not set
# CONFIG_SND_INDIGODJX is not set
# CONFIG_SND_EMU10K1 is not set
# CONFIG_SND_EMU10K1X is not set
# CONFIG_SND_ENS1370 is not set
# CONFIG_SND_ENS1371 is not set
# CONFIG_SND_ES1938 is not set
# CONFIG_SND_ES1968 is not set
# CONFIG_SND_FM801 is not set
# CONFIG_SND_HDSP is not set
# CONFIG_SND_HDSPM is not set
# CONFIG_SND_ICE1712 is not set
# CONFIG_SND_ICE1724 is not set
# CONFIG_SND_INTEL8X0 is not set
# CONFIG_SND_INTEL8X0M is not set
# CONFIG_SND_KORG1212 is not set
# CONFIG_SND_LOLA is not set
# CONFIG_SND_LX6464ES is not set
# CONFIG_SND_MAESTRO3 is not set
# CONFIG_SND_MIXART is not set
# CONFIG_SND_NM256 is not set
# CONFIG_SND_PCXHR is not set
# CONFIG_SND_RIPTIDE is not set
# CONFIG_SND_RME32 is not set
# CONFIG_SND_RME96 is not set
# CONFIG_SND_RME9652 is not set
# CONFIG_SND_SE6X is not set
# CONFIG_SND_SONICVIBES is not set
# CONFIG_SND_TRIDENT is not set
# CONFIG_SND_VIA82XX is not set
# CONFIG_SND_VIA82XX_MODEM is not set
# CONFIG_SND_VIRTUOSO is not set
# CONFIG_SND_VX222 is not set
# CONFIG_SND_YMFPCI is not set

#
# HD-Audio
#
CONFIG_SND_HDA=y
CONFIG_SND_HDA_HWDEP=y
CONFIG_SND_HDA_RECONFIG=y
CONFIG_SND_HDA_INPUT_BEEP=y
CONFIG_SND_HDA_INPUT_BEEP_MODE=1
CONFIG_SND_HDA_PATCH_LOADER=y
CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0
# CONFIG_SND_HDA_CTL_DEV_ID is not set
CONFIG_SND_HDA_PREALLOC_SIZE=0
CONFIG_SND_HDA_INTEL=y
# CONFIG_SND_HDA_ACPI is not set
CONFIG_SND_HDA_GENERIC_LEDS=y
CONFIG_SND_HDA_CODEC_ANALOG=y
CONFIG_SND_HDA_CODEC_SIGMATEL=y
CONFIG_SND_HDA_CODEC_VIA=y
CONFIG_SND_HDA_CODEC_CONEXANT=y
# CONFIG_SND_HDA_CODEC_SENARYTECH is not set
CONFIG_SND_HDA_CODEC_CA0110=y
CONFIG_SND_HDA_CODEC_CA0132=y
# CONFIG_SND_HDA_CODEC_CA0132_DSP is not set
CONFIG_SND_HDA_CODEC_CMEDIA=y
# CONFIG_SND_HDA_CODEC_CM9825 is not set
CONFIG_SND_HDA_CODEC_SI3054=y
CONFIG_SND_HDA_GENERIC=y
CONFIG_SND_HDA_CODEC_REALTEK=y
# CONFIG_SND_HDA_CODEC_ALC260 is not set
# CONFIG_SND_HDA_CODEC_ALC262 is not set
# CONFIG_SND_HDA_CODEC_ALC268 is not set
# CONFIG_SND_HDA_CODEC_ALC269 is not set
# CONFIG_SND_HDA_CODEC_ALC662 is not set
# CONFIG_SND_HDA_CODEC_ALC680 is not set
# CONFIG_SND_HDA_CODEC_ALC861 is not set
# CONFIG_SND_HDA_CODEC_ALC861VD is not set
# CONFIG_SND_HDA_CODEC_ALC880 is not set
# CONFIG_SND_HDA_CODEC_ALC882 is not set
CONFIG_SND_HDA_CODEC_CIRRUS=y
# CONFIG_SND_HDA_CODEC_CS420X is not set
# CONFIG_SND_HDA_CODEC_CS421X is not set
# CONFIG_SND_HDA_CODEC_CS8409 is not set
CONFIG_SND_HDA_CODEC_HDMI=y
# CONFIG_SND_HDA_CODEC_HDMI_GENERIC is not set
# CONFIG_SND_HDA_CODEC_HDMI_SIMPLE is not set
# CONFIG_SND_HDA_CODEC_HDMI_INTEL is not set
# CONFIG_SND_HDA_CODEC_HDMI_ATI is not set
# CONFIG_SND_HDA_CODEC_HDMI_NVIDIA is not set
# CONFIG_SND_HDA_CODEC_HDMI_NVIDIA_MCP is not set
# CONFIG_SND_HDA_CODEC_HDMI_TEGRA is not set
# CONFIG_SND_HDA_SCODEC_CS35L56_I2C is not set
# CONFIG_SND_HDA_SCODEC_CS35L56_SPI is not set
CONFIG_SND_HDA_CORE=y
CONFIG_SND_INTEL_NHLT=y
CONFIG_SND_INTEL_DSP_CONFIG=y
CONFIG_SND_INTEL_SOUNDWIRE_ACPI=y
# end of HD-Audio

# CONFIG_SND_SPI is not set
CONFIG_SND_USB=y
CONFIG_SND_USB_AUDIO=y
CONFIG_SND_USB_AUDIO_MIDI_V2=y
CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER=y
CONFIG_SND_USB_UA101=y
CONFIG_SND_USB_USX2Y=y
CONFIG_SND_USB_CAIAQ=y
CONFIG_SND_USB_CAIAQ_INPUT=y
CONFIG_SND_USB_US122L=y
# CONFIG_SND_USB_US144MKII is not set
CONFIG_SND_USB_6FIRE=y
CONFIG_SND_USB_HIFACE=y
CONFIG_SND_BCD2000=y
CONFIG_SND_USB_LINE6=y
CONFIG_SND_USB_POD=y
CONFIG_SND_USB_PODHD=y
CONFIG_SND_USB_TONEPORT=y
CONFIG_SND_USB_VARIAX=y
# CONFIG_SND_FIREWIRE is not set
CONFIG_SND_PCMCIA=y
# CONFIG_SND_VXPOCKET is not set
# CONFIG_SND_PDAUDIOCF is not set
CONFIG_SND_SOC=y
# CONFIG_SND_SOC_USB is not set

#
# Analog Devices
#
# CONFIG_SND_SOC_ADI_AXI_I2S is not set
# CONFIG_SND_SOC_ADI_AXI_SPDIF is not set
# end of Analog Devices

#
# AMD
#
# CONFIG_SND_SOC_AMD_ACP is not set
# CONFIG_SND_SOC_AMD_ACP3x is not set
# CONFIG_SND_SOC_AMD_RENOIR is not set
# CONFIG_SND_SOC_AMD_ACP5x is not set
# CONFIG_SND_SOC_AMD_ACP6x is not set
# CONFIG_SND_AMD_ACP_CONFIG is not set
# CONFIG_SND_SOC_AMD_ACP_COMMON is not set
# end of AMD

#
# Apple
#
# end of Apple

#
# Atmel
#
# CONFIG_SND_SOC_MIKROE_PROTO is not set
# end of Atmel

#
# Au1x
#
# end of Au1x

#
# Broadcom
#
# CONFIG_SND_BCM63XX_I2S_WHISTLER is not set
# end of Broadcom

#
# Cirrus Logic
#
# end of Cirrus Logic

#
# DesignWare
#
# CONFIG_SND_DESIGNWARE_I2S is not set
# end of DesignWare

#
# Freescale
#

#
# Common SoC Audio options for Freescale CPUs:
#
# CONFIG_SND_SOC_FSL_ASRC is not set
# CONFIG_SND_SOC_FSL_SAI is not set
# CONFIG_SND_SOC_FSL_AUDMIX is not set
# CONFIG_SND_SOC_FSL_SSI is not set
# CONFIG_SND_SOC_FSL_SPDIF is not set
# CONFIG_SND_SOC_FSL_ESAI is not set
# CONFIG_SND_SOC_FSL_MICFIL is not set
# CONFIG_SND_SOC_FSL_XCVR is not set
# CONFIG_SND_SOC_IMX_AUDMUX is not set
# end of Freescale

#
# Google
#
# CONFIG_SND_SOC_CHV3_I2S is not set
# end of Google

#
# Hisilicon
#
# CONFIG_SND_I2S_HI6210_I2S is not set
# end of Hisilicon

#
# JZ4740
#
# end of JZ4740

#
# Kirkwood
#
# end of Kirkwood

#
# Loongson
#
# end of Loongson

#
# Intel
#
# CONFIG_SND_SOC_INTEL_SST_TOPLEVEL is not set
# CONFIG_SND_SOC_INTEL_AVS is not set
# end of Intel

#
# Mediatek
#
# CONFIG_SND_SOC_MTK_BTCVSD is not set
# end of Mediatek

#
# PXA
#
# end of PXA

#
# SoundWire (SDCA)
#
# CONFIG_SND_SOC_SDCA is not set
CONFIG_SND_SOC_SDCA_OPTIONAL=y
# end of SoundWire (SDCA)

#
# ST SPEAr
#
# end of ST SPEAr

#
# Spreadtrum
#
# end of Spreadtrum

#
# STMicroelectronics STM32
#
# end of STMicroelectronics STM32

#
# Tegra
#
# end of Tegra

#
# Xilinx
#
# CONFIG_SND_SOC_XILINX_I2S is not set
# CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER is not set
# CONFIG_SND_SOC_XILINX_SPDIF is not set
# end of Xilinx

#
# Xtensa
#
# CONFIG_SND_SOC_XTFPGA_I2S is not set
# end of Xtensa

# CONFIG_SND_SOC_SOF_TOPLEVEL is not set
CONFIG_SND_SOC_I2C_AND_SPI=y

#
# CODEC drivers
#
# CONFIG_SND_SOC_AC97_CODEC is not set
# CONFIG_SND_SOC_ADAU1372_I2C is not set
# CONFIG_SND_SOC_ADAU1372_SPI is not set
# CONFIG_SND_SOC_ADAU1373 is not set
# CONFIG_SND_SOC_ADAU1701 is not set
# CONFIG_SND_SOC_ADAU1761_I2C is not set
# CONFIG_SND_SOC_ADAU1761_SPI is not set
# CONFIG_SND_SOC_ADAU7002 is not set
# CONFIG_SND_SOC_ADAU7118_HW is not set
# CONFIG_SND_SOC_ADAU7118_I2C is not set
# CONFIG_SND_SOC_AK4104 is not set
# CONFIG_SND_SOC_AK4118 is not set
# CONFIG_SND_SOC_AK4375 is not set
# CONFIG_SND_SOC_AK4458 is not set
# CONFIG_SND_SOC_AK4554 is not set
# CONFIG_SND_SOC_AK4613 is not set
# CONFIG_SND_SOC_AK4619 is not set
# CONFIG_SND_SOC_AK4642 is not set
# CONFIG_SND_SOC_AK5386 is not set
# CONFIG_SND_SOC_AK5558 is not set
# CONFIG_SND_SOC_ALC5623 is not set
# CONFIG_SND_SOC_AUDIO_IIO_AUX is not set
# CONFIG_SND_SOC_AW8738 is not set
# CONFIG_SND_SOC_AW88395 is not set
# CONFIG_SND_SOC_AW88166 is not set
# CONFIG_SND_SOC_AW88261 is not set
# CONFIG_SND_SOC_AW88081 is not set
# CONFIG_SND_SOC_AW87390 is not set
# CONFIG_SND_SOC_AW88399 is not set
# CONFIG_SND_SOC_BD28623 is not set
# CONFIG_SND_SOC_BT_SCO is not set
# CONFIG_SND_SOC_CHV3_CODEC is not set
# CONFIG_SND_SOC_CS35L32 is not set
# CONFIG_SND_SOC_CS35L33 is not set
# CONFIG_SND_SOC_CS35L34 is not set
# CONFIG_SND_SOC_CS35L35 is not set
# CONFIG_SND_SOC_CS35L36 is not set
# CONFIG_SND_SOC_CS35L41_SPI is not set
# CONFIG_SND_SOC_CS35L41_I2C is not set
# CONFIG_SND_SOC_CS35L45_SPI is not set
# CONFIG_SND_SOC_CS35L45_I2C is not set
# CONFIG_SND_SOC_CS35L56_I2C is not set
# CONFIG_SND_SOC_CS35L56_SPI is not set
# CONFIG_SND_SOC_CS35L56_SDW is not set
# CONFIG_SND_SOC_CS42L42 is not set
# CONFIG_SND_SOC_CS42L42_SDW is not set
# CONFIG_SND_SOC_CS42L51_I2C is not set
# CONFIG_SND_SOC_CS42L52 is not set
# CONFIG_SND_SOC_CS42L56 is not set
# CONFIG_SND_SOC_CS42L73 is not set
# CONFIG_SND_SOC_CS42L83 is not set
# CONFIG_SND_SOC_CS42L84 is not set
# CONFIG_SND_SOC_CS4234 is not set
# CONFIG_SND_SOC_CS4265 is not set
# CONFIG_SND_SOC_CS4270 is not set
# CONFIG_SND_SOC_CS4271_I2C is not set
# CONFIG_SND_SOC_CS4271_SPI is not set
# CONFIG_SND_SOC_CS42XX8_SPI is not set
# CONFIG_SND_SOC_CS42XX8_I2C is not set
# CONFIG_SND_SOC_CS43130 is not set
# CONFIG_SND_SOC_CS4341 is not set
# CONFIG_SND_SOC_CS4349 is not set
# CONFIG_SND_SOC_CS48L32 is not set
# CONFIG_SND_SOC_CS53L30 is not set
# CONFIG_SND_SOC_CS530X_I2C is not set
# CONFIG_SND_SOC_CS530X_SPI is not set
# CONFIG_SND_SOC_CX2072X is not set
# CONFIG_SND_SOC_DA7213 is not set
# CONFIG_SND_SOC_DMIC is not set
# CONFIG_SND_SOC_ES7134 is not set
# CONFIG_SND_SOC_ES7241 is not set
# CONFIG_SND_SOC_ES8311 is not set
# CONFIG_SND_SOC_ES8316 is not set
# CONFIG_SND_SOC_ES8323 is not set
# CONFIG_SND_SOC_ES8326 is not set
# CONFIG_SND_SOC_ES8328_I2C is not set
# CONFIG_SND_SOC_ES8328_SPI is not set
# CONFIG_SND_SOC_ES8375 is not set
# CONFIG_SND_SOC_ES8389 is not set
# CONFIG_SND_SOC_FS210X is not set
# CONFIG_SND_SOC_GTM601 is not set
# CONFIG_SND_SOC_HDA is not set
# CONFIG_SND_SOC_ICS43432 is not set
# CONFIG_SND_SOC_IDT821034 is not set
# CONFIG_SND_SOC_MAX98088 is not set
# CONFIG_SND_SOC_MAX98090 is not set
# CONFIG_SND_SOC_MAX98357A is not set
# CONFIG_SND_SOC_MAX98504 is not set
# CONFIG_SND_SOC_MAX9867 is not set
# CONFIG_SND_SOC_MAX98927 is not set
# CONFIG_SND_SOC_MAX98520 is not set
# CONFIG_SND_SOC_MAX98363 is not set
# CONFIG_SND_SOC_MAX98373_I2C is not set
# CONFIG_SND_SOC_MAX98373_SDW is not set
# CONFIG_SND_SOC_MAX98388 is not set
# CONFIG_SND_SOC_MAX98390 is not set
# CONFIG_SND_SOC_MAX98396 is not set
# CONFIG_SND_SOC_MAX9860 is not set
# CONFIG_SND_SOC_MSM8916_WCD_DIGITAL is not set
# CONFIG_SND_SOC_PCM1681 is not set
# CONFIG_SND_SOC_PCM1754 is not set
# CONFIG_SND_SOC_PCM1789_I2C is not set
# CONFIG_SND_SOC_PCM179X_I2C is not set
# CONFIG_SND_SOC_PCM179X_SPI is not set
# CONFIG_SND_SOC_PCM186X_I2C is not set
# CONFIG_SND_SOC_PCM186X_SPI is not set
# CONFIG_SND_SOC_PCM3060_I2C is not set
# CONFIG_SND_SOC_PCM3060_SPI is not set
# CONFIG_SND_SOC_PCM3168A_I2C is not set
# CONFIG_SND_SOC_PCM3168A_SPI is not set
# CONFIG_SND_SOC_PCM5102A is not set
# CONFIG_SND_SOC_PCM512x_I2C is not set
# CONFIG_SND_SOC_PCM512x_SPI is not set
# CONFIG_SND_SOC_PCM6240 is not set
# CONFIG_SND_SOC_PEB2466 is not set
# CONFIG_SND_SOC_PM4125_SDW is not set
# CONFIG_SND_SOC_RT1017_SDCA_SDW is not set
# CONFIG_SND_SOC_RT1308_SDW is not set
# CONFIG_SND_SOC_RT1316_SDW is not set
# CONFIG_SND_SOC_RT1318_SDW is not set
# CONFIG_SND_SOC_RT1320_SDW is not set
# CONFIG_SND_SOC_RT5575 is not set
# CONFIG_SND_SOC_RT5616 is not set
# CONFIG_SND_SOC_RT5631 is not set
# CONFIG_SND_SOC_RT5640 is not set
# CONFIG_SND_SOC_RT5659 is not set
# CONFIG_SND_SOC_RT5682_SDW is not set
# CONFIG_SND_SOC_RT700_SDW is not set
# CONFIG_SND_SOC_RT711_SDW is not set
# CONFIG_SND_SOC_RT711_SDCA_SDW is not set
# CONFIG_SND_SOC_RT712_SDCA_SDW is not set
# CONFIG_SND_SOC_RT712_SDCA_DMIC_SDW is not set
# CONFIG_SND_SOC_RT721_SDCA_SDW is not set
# CONFIG_SND_SOC_RT722_SDCA_SDW is not set
# CONFIG_SND_SOC_RT715_SDW is not set
# CONFIG_SND_SOC_RT715_SDCA_SDW is not set
# CONFIG_SND_SOC_RT9120 is not set
# CONFIG_SND_SOC_RT9123 is not set
# CONFIG_SND_SOC_RT9123P is not set
# CONFIG_SND_SOC_RTQ9124 is not set
# CONFIG_SND_SOC_RTQ9128 is not set
# CONFIG_SND_SOC_SDW_MOCKUP is not set
# CONFIG_SND_SOC_SGTL5000 is not set
# CONFIG_SND_SOC_SIMPLE_AMPLIFIER is not set
# CONFIG_SND_SOC_SIMPLE_MUX is not set
# CONFIG_SND_SOC_SMA1303 is not set
# CONFIG_SND_SOC_SMA1307 is not set
# CONFIG_SND_SOC_SPDIF is not set
# CONFIG_SND_SOC_SRC4XXX_I2C is not set
# CONFIG_SND_SOC_SSM2305 is not set
# CONFIG_SND_SOC_SSM2518 is not set
# CONFIG_SND_SOC_SSM2602_SPI is not set
# CONFIG_SND_SOC_SSM2602_I2C is not set
# CONFIG_SND_SOC_SSM3515 is not set
# CONFIG_SND_SOC_SSM4567 is not set
# CONFIG_SND_SOC_STA32X is not set
# CONFIG_SND_SOC_STA350 is not set
# CONFIG_SND_SOC_STI_SAS is not set
# CONFIG_SND_SOC_TAS2552 is not set
# CONFIG_SND_SOC_TAS2562 is not set
# CONFIG_SND_SOC_TAS2764 is not set
# CONFIG_SND_SOC_TAS2770 is not set
# CONFIG_SND_SOC_TAS2780 is not set
# CONFIG_SND_SOC_TAS2781_I2C is not set
# CONFIG_SND_SOC_TAS5086 is not set
# CONFIG_SND_SOC_TAS571X is not set
# CONFIG_SND_SOC_TAS5720 is not set
# CONFIG_SND_SOC_TAS5805M is not set
# CONFIG_SND_SOC_TAS6424 is not set
# CONFIG_SND_SOC_TAS675X is not set
# CONFIG_SND_SOC_TDA7419 is not set
# CONFIG_SND_SOC_TFA9879 is not set
# CONFIG_SND_SOC_TFA989X is not set
# CONFIG_SND_SOC_TLV320ADC3XXX is not set
# CONFIG_SND_SOC_TLV320AIC23_I2C is not set
# CONFIG_SND_SOC_TLV320AIC23_SPI is not set
# CONFIG_SND_SOC_TLV320AIC31XX is not set
# CONFIG_SND_SOC_TLV320AIC32X4_I2C is not set
# CONFIG_SND_SOC_TLV320AIC32X4_SPI is not set
# CONFIG_SND_SOC_TLV320AIC3X_I2C is not set
# CONFIG_SND_SOC_TLV320AIC3X_SPI is not set
# CONFIG_SND_SOC_TLV320ADCX140 is not set
# CONFIG_SND_SOC_TS3A227E is not set
# CONFIG_SND_SOC_TSCS42XX is not set
# CONFIG_SND_SOC_TSCS454 is not set
# CONFIG_SND_SOC_UDA1334 is not set
# CONFIG_SND_SOC_UDA1342 is not set
# CONFIG_SND_SOC_UDA1380 is not set
# CONFIG_SND_SOC_WCD937X_SDW is not set
# CONFIG_SND_SOC_WCD938X_SDW is not set
# CONFIG_SND_SOC_WCD939X_SDW is not set
# CONFIG_SND_SOC_WM8510 is not set
# CONFIG_SND_SOC_WM8523 is not set
# CONFIG_SND_SOC_WM8524 is not set
# CONFIG_SND_SOC_WM8580 is not set
# CONFIG_SND_SOC_WM8711 is not set
# CONFIG_SND_SOC_WM8728 is not set
# CONFIG_SND_SOC_WM8731_I2C is not set
# CONFIG_SND_SOC_WM8731_SPI is not set
# CONFIG_SND_SOC_WM8737 is not set
# CONFIG_SND_SOC_WM8741 is not set
# CONFIG_SND_SOC_WM8750 is not set
# CONFIG_SND_SOC_WM8753 is not set
# CONFIG_SND_SOC_WM8770 is not set
# CONFIG_SND_SOC_WM8776 is not set
# CONFIG_SND_SOC_WM8782 is not set
# CONFIG_SND_SOC_WM8804_I2C is not set
# CONFIG_SND_SOC_WM8804_SPI is not set
# CONFIG_SND_SOC_WM8903 is not set
# CONFIG_SND_SOC_WM8904 is not set
# CONFIG_SND_SOC_WM8940 is not set
# CONFIG_SND_SOC_WM8960 is not set
# CONFIG_SND_SOC_WM8961 is not set
# CONFIG_SND_SOC_WM8962 is not set
# CONFIG_SND_SOC_WM8974 is not set
# CONFIG_SND_SOC_WM8978 is not set
# CONFIG_SND_SOC_WM8985 is not set
# CONFIG_SND_SOC_WSA881X is not set
# CONFIG_SND_SOC_WSA883X is not set
# CONFIG_SND_SOC_WSA884X is not set
# CONFIG_SND_SOC_ZL38060 is not set
# CONFIG_SND_SOC_MAX9759 is not set
# CONFIG_SND_SOC_MT6351 is not set
# CONFIG_SND_SOC_MT6357 is not set
# CONFIG_SND_SOC_MT6358 is not set
# CONFIG_SND_SOC_MT6660 is not set
# CONFIG_SND_SOC_NAU8315 is not set
# CONFIG_SND_SOC_NAU8325 is not set
# CONFIG_SND_SOC_NAU8540 is not set
# CONFIG_SND_SOC_NAU8810 is not set
# CONFIG_SND_SOC_NAU8821 is not set
# CONFIG_SND_SOC_NAU8822 is not set
# CONFIG_SND_SOC_NAU8824 is not set
# CONFIG_SND_SOC_NTP8918 is not set
# CONFIG_SND_SOC_NTP8835 is not set
# CONFIG_SND_SOC_TPA6130A2 is not set
# CONFIG_SND_SOC_LPASS_WSA_MACRO is not set
# CONFIG_SND_SOC_LPASS_VA_MACRO is not set
# CONFIG_SND_SOC_LPASS_RX_MACRO is not set
# CONFIG_SND_SOC_LPASS_TX_MACRO is not set
# end of CODEC drivers

#
# Generic drivers
#
# CONFIG_SND_SIMPLE_CARD is not set
# CONFIG_SND_AUDIO_GRAPH_CARD is not set
# CONFIG_SND_AUDIO_GRAPH_CARD2 is not set
# CONFIG_SND_TEST_COMPONENT is not set
# end of Generic drivers

CONFIG_SND_X86=y
CONFIG_SND_VIRTIO=y
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
CONFIG_HID_BATTERY_STRENGTH=y
CONFIG_HIDRAW=y
CONFIG_UHID=y
CONFIG_HID_GENERIC=y
CONFIG_HID_HAPTIC=y

#
# Special HID drivers
#
CONFIG_HID_A4TECH=y
CONFIG_HID_ACCUTOUCH=y
CONFIG_HID_ACRUX=y
CONFIG_HID_ACRUX_FF=y
CONFIG_HID_APPLE=y
CONFIG_HID_APPLEIR=y
# CONFIG_HID_APPLETB_BL is not set
# CONFIG_HID_APPLETB_KBD is not set
CONFIG_HID_ASUS=y
CONFIG_HID_AUREAL=y
CONFIG_HID_BELKIN=y
CONFIG_HID_BETOP_FF=y
CONFIG_HID_BIGBEN_FF=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CORSAIR=y
CONFIG_HID_COUGAR=y
CONFIG_HID_MACALLY=y
CONFIG_HID_PRODIKEYS=y
CONFIG_HID_CMEDIA=y
CONFIG_HID_CP2112=y
CONFIG_HID_CREATIVE_SB0540=y
CONFIG_HID_CYPRESS=y
CONFIG_HID_DRAGONRISE=y
CONFIG_DRAGONRISE_FF=y
CONFIG_HID_EMS_FF=y
CONFIG_HID_ELAN=y
CONFIG_HID_ELECOM=y
CONFIG_HID_ELO=y
CONFIG_HID_EVISION=y
CONFIG_HID_EZKEY=y
CONFIG_HID_FT260=y
CONFIG_HID_GEMBIRD=y
CONFIG_HID_GFRM=y
CONFIG_HID_GLORIOUS=y
CONFIG_HID_HOLTEK=y
CONFIG_HOLTEK_FF=y
CONFIG_HID_VIVALDI_COMMON=y
# CONFIG_HID_GOODIX_SPI is not set
CONFIG_HID_GOOGLE_STADIA_FF=y
CONFIG_HID_VIVALDI=y
CONFIG_HID_GT683R=y
CONFIG_HID_KEYTOUCH=y
CONFIG_HID_KYE=y
# CONFIG_HID_KYSONA is not set
CONFIG_HID_UCLOGIC=y
CONFIG_HID_WALTOP=y
CONFIG_HID_VIEWSONIC=y
CONFIG_HID_VRC2=y
CONFIG_HID_XIAOMI=y
CONFIG_HID_GYRATION=y
CONFIG_HID_ICADE=y
CONFIG_HID_ITE=y
CONFIG_HID_JABRA=y
CONFIG_HID_TWINHAN=y
CONFIG_HID_KENSINGTON=y
CONFIG_HID_LCPOWER=y
CONFIG_HID_LED=y
CONFIG_HID_LENOVO=y
# CONFIG_HID_LENOVO_GO is not set
# CONFIG_HID_LENOVO_GO_S is not set
CONFIG_HID_LETSKETCH=y
CONFIG_HID_LOGITECH=y
CONFIG_HID_LOGITECH_DJ=y
CONFIG_HID_LOGITECH_HIDPP=y
CONFIG_LOGITECH_FF=y
CONFIG_LOGIRUMBLEPAD2_FF=y
CONFIG_LOGIG940_FF=y
CONFIG_LOGIWHEELS_FF=y
CONFIG_HID_MAGICMOUSE=y
CONFIG_HID_MALTRON=y
CONFIG_HID_MAYFLASH=y
CONFIG_HID_MEGAWORLD_FF=y
# CONFIG_HID_RAKK is not set
CONFIG_HID_REDRAGON=y
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
CONFIG_HID_MULTITOUCH=y
CONFIG_HID_NINTENDO=y
CONFIG_NINTENDO_FF=y
CONFIG_HID_NTI=y
CONFIG_HID_NTRIG=y
CONFIG_HID_NVIDIA_SHIELD=y
CONFIG_NVIDIA_SHIELD_FF=y
CONFIG_HID_ORTEK=y
# CONFIG_HID_OXP is not set
CONFIG_HID_PANTHERLORD=y
CONFIG_PANTHERLORD_FF=y
CONFIG_HID_PENMOUNT=y
CONFIG_HID_PETALYNX=y
CONFIG_HID_PICOLCD=y
CONFIG_HID_PICOLCD_FB=y
CONFIG_HID_PICOLCD_BACKLIGHT=y
CONFIG_HID_PICOLCD_LCD=y
CONFIG_HID_PICOLCD_LEDS=y
CONFIG_HID_PICOLCD_CIR=y
CONFIG_HID_PLANTRONICS=y
CONFIG_HID_PLAYSTATION=y
CONFIG_PLAYSTATION_FF=y
CONFIG_HID_PXRC=y
# CONFIG_HID_RAPOO is not set
CONFIG_HID_RAZER=y
CONFIG_HID_PRIMAX=y
CONFIG_HID_RETRODE=y
CONFIG_HID_ROCCAT=y
CONFIG_HID_SAITEK=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SEMITEK=y
CONFIG_HID_SIGMAMICRO=y
CONFIG_HID_SONY=y
CONFIG_SONY_FF=y
CONFIG_HID_SPEEDLINK=y
CONFIG_HID_STEAM=y
CONFIG_STEAM_FF=y
CONFIG_HID_STEELSERIES=y
CONFIG_HID_SUNPLUS=y
CONFIG_HID_RMI=y
CONFIG_HID_GREENASIA=y
CONFIG_GREENASIA_FF=y
CONFIG_HID_SMARTJOYPLUS=y
CONFIG_SMARTJOYPLUS_FF=y
CONFIG_HID_TIVO=y
CONFIG_HID_TOPSEED=y
CONFIG_HID_TOPRE=y
CONFIG_HID_THINGM=y
CONFIG_HID_THRUSTMASTER=y
CONFIG_THRUSTMASTER_FF=y
CONFIG_HID_UDRAW_PS3=y
CONFIG_HID_U2FZERO=y
# CONFIG_HID_UNIVERSAL_PIDFF is not set
CONFIG_HID_WACOM=y
CONFIG_HID_WIIMOTE=y
# CONFIG_HID_WINWING is not set
CONFIG_HID_XINMO=y
CONFIG_HID_ZEROPLUS=y
CONFIG_ZEROPLUS_FF=y
CONFIG_HID_ZYDACRON=y
CONFIG_HID_SENSOR_HUB=y
CONFIG_HID_SENSOR_CUSTOM_SENSOR=y
CONFIG_HID_ALPS=y
CONFIG_HID_MCP2200=y
CONFIG_HID_MCP2221=y
CONFIG_HID_HUAWEI=y
# end of Special HID drivers

#
# HID-BPF support
#
# end of HID-BPF support

CONFIG_I2C_HID=y
CONFIG_I2C_HID_ACPI=y
CONFIG_I2C_HID_OF=y
# CONFIG_I2C_HID_OF_ELAN is not set
# CONFIG_I2C_HID_OF_GOODIX is not set
CONFIG_I2C_HID_CORE=y

#
# Intel ISH HID support
#
CONFIG_INTEL_ISH_HID=y
CONFIG_INTEL_ISH_FIRMWARE_DOWNLOADER=y
# end of Intel ISH HID support

#
# AMD SFH HID Support
#
CONFIG_AMD_SFH_HID=y
# end of AMD SFH HID Support

#
# Surface System Aggregator Module HID support
#
CONFIG_SURFACE_HID=y
CONFIG_SURFACE_KBD=y
# end of Surface System Aggregator Module HID support

CONFIG_SURFACE_HID_CORE=y

#
# Intel THC HID Support
#
# CONFIG_INTEL_THC_HID is not set
# end of Intel THC HID Support

#
# USB HID support
#
CONFIG_USB_HID=y
CONFIG_HID_PID=y
CONFIG_USB_HIDDEV=y
# end of USB HID support

CONFIG_USB_OHCI_LITTLE_ENDIAN=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_COMMON=y
CONFIG_USB_LED_TRIG=y
CONFIG_USB_ULPI_BUS=y
CONFIG_USB_CONN_GPIO=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB=y
CONFIG_USB_PCI=y
CONFIG_USB_PCI_AMD=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y

#
# Miscellaneous USB options
#
CONFIG_USB_DEFAULT_PERSIST=y
CONFIG_USB_FEW_INIT_RETRIES=y
CONFIG_USB_DYNAMIC_MINORS=y
CONFIG_USB_OTG=y
# CONFIG_USB_OTG_PRODUCTLIST is not set
# CONFIG_USB_OTG_DISABLE_EXTERNAL_HUB is not set
CONFIG_USB_OTG_FSM=y
CONFIG_USB_LEDS_TRIGGER_USBPORT=y
CONFIG_USB_AUTOSUSPEND_DELAY=2
CONFIG_USB_DEFAULT_AUTHORIZATION_MODE=1
CONFIG_USB_MON=y

#
# USB Host Controller Drivers
#
CONFIG_USB_C67X00_HCD=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_DBGCAP=y
CONFIG_USB_XHCI_PCI=y
CONFIG_USB_XHCI_PCI_RENESAS=y
CONFIG_USB_XHCI_PLATFORM=y
# CONFIG_USB_XHCI_SIDEBAND is not set
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_EHCI_TT_NEWSCHED=y
CONFIG_USB_EHCI_PCI=y
CONFIG_USB_EHCI_FSL=y
CONFIG_USB_EHCI_HCD_PLATFORM=y
CONFIG_USB_OXU210HP_HCD=y
CONFIG_USB_ISP116X_HCD=y
CONFIG_USB_MAX3421_HCD=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PCI=y
# CONFIG_USB_OHCI_HCD_SSB is not set
CONFIG_USB_OHCI_HCD_PLATFORM=y
CONFIG_USB_UHCI_HCD=y
CONFIG_USB_SL811_HCD=y
CONFIG_USB_SL811_HCD_ISO=y
CONFIG_USB_SL811_CS=y
CONFIG_USB_R8A66597_HCD=y
CONFIG_USB_HCD_BCMA=y
CONFIG_USB_HCD_SSB=y
# CONFIG_USB_HCD_TEST_MODE is not set

#
# USB Device Class drivers
#
CONFIG_USB_ACM=y
CONFIG_USB_PRINTER=y
CONFIG_USB_WDM=y
CONFIG_USB_TMC=y

#
# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; see USB_STORAGE Help for more info
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
CONFIG_USB_STORAGE_REALTEK=y
CONFIG_REALTEK_AUTOPM=y
CONFIG_USB_STORAGE_DATAFAB=y
CONFIG_USB_STORAGE_FREECOM=y
CONFIG_USB_STORAGE_ISD200=y
CONFIG_USB_STORAGE_USBAT=y
CONFIG_USB_STORAGE_SDDR09=y
CONFIG_USB_STORAGE_SDDR55=y
CONFIG_USB_STORAGE_JUMPSHOT=y
CONFIG_USB_STORAGE_ALAUDA=y
CONFIG_USB_STORAGE_ONETOUCH=y
CONFIG_USB_STORAGE_KARMA=y
CONFIG_USB_STORAGE_CYPRESS_ATACB=y
CONFIG_USB_STORAGE_ENE_UB6250=y
CONFIG_USB_UAS=y

#
# USB Imaging devices
#
CONFIG_USB_MDC800=y
CONFIG_USB_MICROTEK=y
CONFIG_USBIP_CORE=y
CONFIG_USBIP_VHCI_HCD=y
CONFIG_USBIP_VHCI_HC_PORTS=8
CONFIG_USBIP_VHCI_NR_HCS=16
CONFIG_USBIP_HOST=y
CONFIG_USBIP_VUDC=y
# CONFIG_USBIP_DEBUG is not set

#
# USB dual-mode controller drivers
#
CONFIG_USB_CDNS_SUPPORT=y
CONFIG_USB_CDNS3=y
CONFIG_USB_CDNS3_HOST=y
CONFIG_USB_CDNS3_GADGET=y

#
# Platform glue driver support
#
CONFIG_USB_CDNS3_PCI_WRAP=y
CONFIG_USB_CDNSP_PCI=y
CONFIG_USB_MUSB_HDRC=y
# CONFIG_USB_MUSB_HOST is not set
# CONFIG_USB_MUSB_GADGET is not set
CONFIG_USB_MUSB_DUAL_ROLE=y

#
# Platform Glue Layer
#

#
# MUSB DMA mode
#
CONFIG_MUSB_PIO_ONLY=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_ULPI=y
# CONFIG_USB_DWC3_HOST is not set
CONFIG_USB_DWC3_GADGET=y
# CONFIG_USB_DWC3_DUAL_ROLE is not set

#
# Platform Glue Driver Support
#
CONFIG_USB_DWC3_PCI=y
CONFIG_USB_DWC3_HAPS=y
CONFIG_USB_DWC3_OF_SIMPLE=y
CONFIG_USB_DWC3_GENERIC_PLAT=y
# CONFIG_USB_DWC3_GOOGLE is not set
CONFIG_USB_DWC2=y
CONFIG_USB_DWC2_HOST=y

#
# Gadget/Dual-role mode requires USB Gadget support to be enabled
#
# CONFIG_USB_DWC2_PERIPHERAL is not set
# CONFIG_USB_DWC2_DUAL_ROLE is not set
CONFIG_USB_DWC2_PCI=y
# CONFIG_USB_DWC2_DEBUG is not set
# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set
CONFIG_USB_CHIPIDEA=y
CONFIG_USB_CHIPIDEA_UDC=y
CONFIG_USB_CHIPIDEA_HOST=y
CONFIG_USB_CHIPIDEA_PCI=y
CONFIG_USB_CHIPIDEA_MSM=y
CONFIG_USB_CHIPIDEA_NPCM=y
# CONFIG_USB_CHIPIDEA_IMX is not set
CONFIG_USB_CHIPIDEA_GENERIC=y
# CONFIG_USB_CHIPIDEA_TEGRA is not set
CONFIG_USB_ISP1760=y
CONFIG_USB_ISP1760_HCD=y
CONFIG_USB_ISP1761_UDC=y
# CONFIG_USB_ISP1760_HOST_ROLE is not set
# CONFIG_USB_ISP1760_GADGET_ROLE is not set
CONFIG_USB_ISP1760_DUAL_ROLE=y

#
# USB port drivers
#
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_CONSOLE=y
CONFIG_USB_SERIAL_GENERIC=y
CONFIG_USB_SERIAL_SIMPLE=y
CONFIG_USB_SERIAL_AIRCABLE=y
CONFIG_USB_SERIAL_ARK3116=y
CONFIG_USB_SERIAL_BELKIN=y
CONFIG_USB_SERIAL_CH341=y
CONFIG_USB_SERIAL_WHITEHEAT=y
CONFIG_USB_SERIAL_DIGI_ACCELEPORT=y
CONFIG_USB_SERIAL_CP210X=y
CONFIG_USB_SERIAL_CYPRESS_M8=y
CONFIG_USB_SERIAL_EMPEG=y
CONFIG_USB_SERIAL_FTDI_SIO=y
CONFIG_USB_SERIAL_VISOR=y
CONFIG_USB_SERIAL_IPAQ=y
CONFIG_USB_SERIAL_IR=y
CONFIG_USB_SERIAL_EDGEPORT=y
CONFIG_USB_SERIAL_EDGEPORT_TI=y
CONFIG_USB_SERIAL_F81232=y
CONFIG_USB_SERIAL_F8153X=y
CONFIG_USB_SERIAL_GARMIN=y
CONFIG_USB_SERIAL_IPW=y
CONFIG_USB_SERIAL_IUU=y
CONFIG_USB_SERIAL_KEYSPAN_PDA=y
CONFIG_USB_SERIAL_KEYSPAN=y
CONFIG_USB_SERIAL_KLSI=y
CONFIG_USB_SERIAL_KOBIL_SCT=y
CONFIG_USB_SERIAL_MCT_U232=y
CONFIG_USB_SERIAL_METRO=y
CONFIG_USB_SERIAL_MOS7720=y
CONFIG_USB_SERIAL_MOS7715_PARPORT=y
CONFIG_USB_SERIAL_MOS7840=y
CONFIG_USB_SERIAL_MXUPORT=y
CONFIG_USB_SERIAL_NAVMAN=y
CONFIG_USB_SERIAL_PL2303=y
CONFIG_USB_SERIAL_OTI6858=y
CONFIG_USB_SERIAL_QCAUX=y
CONFIG_USB_SERIAL_QUALCOMM=y
CONFIG_USB_SERIAL_SPCP8X5=y
CONFIG_USB_SERIAL_SAFE=y
# CONFIG_USB_SERIAL_SAFE_PADDED is not set
CONFIG_USB_SERIAL_SIERRAWIRELESS=y
CONFIG_USB_SERIAL_SYMBOL=y
CONFIG_USB_SERIAL_TI=y
CONFIG_USB_SERIAL_CYBERJACK=y
CONFIG_USB_SERIAL_WWAN=y
CONFIG_USB_SERIAL_OPTION=y
CONFIG_USB_SERIAL_OMNINET=y
CONFIG_USB_SERIAL_OPTICON=y
CONFIG_USB_SERIAL_XSENS_MT=y
CONFIG_USB_SERIAL_WISHBONE=y
CONFIG_USB_SERIAL_SSU100=y
CONFIG_USB_SERIAL_QT2=y
CONFIG_USB_SERIAL_UPD78F0730=y
CONFIG_USB_SERIAL_XR=y
CONFIG_USB_SERIAL_DEBUG=y

#
# USB Miscellaneous drivers
#
CONFIG_USB_USS720=y
CONFIG_USB_EMI62=y
CONFIG_USB_EMI26=y
CONFIG_USB_ADUTUX=y
CONFIG_USB_SEVSEG=y
CONFIG_USB_LEGOTOWER=y
CONFIG_USB_LCD=y
CONFIG_USB_CYPRESS_CY7C63=y
CONFIG_USB_CYTHERM=y
CONFIG_USB_IDMOUSE=y
CONFIG_USB_APPLEDISPLAY=y
CONFIG_APPLE_MFI_FASTCHARGE=y
CONFIG_USB_LJCA=y
# CONFIG_USB_USBIO is not set
CONFIG_USB_SISUSBVGA=y
CONFIG_USB_LD=y
CONFIG_USB_TRANCEVIBRATOR=y
CONFIG_USB_IOWARRIOR=y
CONFIG_USB_TEST=y
CONFIG_USB_EHSET_TEST_FIXTURE=y
CONFIG_USB_ISIGHTFW=y
CONFIG_USB_YUREX=y
CONFIG_USB_EZUSB_FX2=y
CONFIG_USB_HUB_USB251XB=y
CONFIG_USB_HSIC_USB3503=y
CONFIG_USB_HSIC_USB4604=y
CONFIG_USB_LINK_LAYER_TEST=y
CONFIG_USB_CHAOSKEY=y
# CONFIG_USB_ONBOARD_DEV is not set
CONFIG_USB_ATM=y
CONFIG_USB_SPEEDTOUCH=y
CONFIG_USB_CXACRU=y
CONFIG_USB_UEAGLEATM=y
CONFIG_USB_XUSBATM=y

#
# USB Physical Layer drivers
#
CONFIG_USB_PHY=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_TAHVO_USB=y
CONFIG_TAHVO_USB_HOST_BY_DEFAULT=y
CONFIG_USB_ISP1301=y
# end of USB Physical Layer drivers

CONFIG_USB_GADGET=y
# CONFIG_USB_GADGET_DEBUG is not set
CONFIG_USB_GADGET_DEBUG_FILES=y
CONFIG_USB_GADGET_DEBUG_FS=y
CONFIG_USB_GADGET_VBUS_DRAW=2
CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
CONFIG_U_SERIAL_CONSOLE=y

#
# USB Peripheral Controller
#
CONFIG_USB_GR_UDC=y
CONFIG_USB_R8A66597=y
CONFIG_USB_PXA27X=y
CONFIG_USB_SNP_CORE=y
# CONFIG_USB_SNP_UDC_PLAT is not set
# CONFIG_USB_M66592 is not set
CONFIG_USB_BDC_UDC=y
CONFIG_USB_AMD5536UDC=y
CONFIG_USB_NET2280=y
CONFIG_USB_GOKU=y
CONFIG_USB_EG20T=y
# CONFIG_USB_GADGET_XILINX is not set
CONFIG_USB_MAX3420_UDC=y
CONFIG_USB_CDNS2_UDC=y
CONFIG_USB_DUMMY_HCD=y
# end of USB Peripheral Controller

CONFIG_USB_LIBCOMPOSITE=y
CONFIG_USB_F_ACM=y
CONFIG_USB_F_SS_LB=y
CONFIG_USB_U_SERIAL=y
CONFIG_USB_U_ETHER=y
CONFIG_USB_U_AUDIO=y
CONFIG_USB_F_SERIAL=y
CONFIG_USB_F_OBEX=y
CONFIG_USB_F_NCM=y
CONFIG_USB_F_ECM=y
CONFIG_USB_F_PHONET=y
CONFIG_USB_F_EEM=y
CONFIG_USB_F_SUBSET=y
CONFIG_USB_F_RNDIS=y
CONFIG_USB_F_MASS_STORAGE=y
CONFIG_USB_F_FS=y
CONFIG_USB_F_UAC1=y
CONFIG_USB_F_UAC1_LEGACY=y
CONFIG_USB_F_UAC2=y
CONFIG_USB_F_UVC=y
CONFIG_USB_F_MIDI=y
CONFIG_USB_F_MIDI2=y
CONFIG_USB_F_HID=y
CONFIG_USB_F_PRINTER=y
CONFIG_USB_F_TCM=y
CONFIG_USB_CONFIGFS=y
CONFIG_USB_CONFIGFS_SERIAL=y
CONFIG_USB_CONFIGFS_ACM=y
CONFIG_USB_CONFIGFS_OBEX=y
CONFIG_USB_CONFIGFS_NCM=y
CONFIG_USB_CONFIGFS_ECM=y
CONFIG_USB_CONFIGFS_ECM_SUBSET=y
CONFIG_USB_CONFIGFS_RNDIS=y
CONFIG_USB_CONFIGFS_EEM=y
CONFIG_USB_CONFIGFS_PHONET=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_LB_SS=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_F_UAC1=y
CONFIG_USB_CONFIGFS_F_UAC1_LEGACY=y
CONFIG_USB_CONFIGFS_F_UAC2=y
CONFIG_USB_CONFIGFS_F_MIDI=y
CONFIG_USB_CONFIGFS_F_MIDI2=y
CONFIG_USB_CONFIGFS_F_HID=y
CONFIG_USB_CONFIGFS_F_UVC=y
CONFIG_USB_CONFIGFS_F_PRINTER=y
CONFIG_USB_CONFIGFS_F_TCM=y

#
# USB Gadget precomposed configurations
#
# CONFIG_USB_ZERO is not set
# CONFIG_USB_AUDIO is not set
# CONFIG_USB_ETH is not set
# CONFIG_USB_G_NCM is not set
CONFIG_USB_GADGETFS=y
# CONFIG_USB_FUNCTIONFS is not set
# CONFIG_USB_MASS_STORAGE is not set
# CONFIG_USB_GADGET_TARGET is not set
# CONFIG_USB_G_SERIAL is not set
# CONFIG_USB_MIDI_GADGET is not set
# CONFIG_USB_G_PRINTER is not set
# CONFIG_USB_CDC_COMPOSITE is not set
# CONFIG_USB_G_NOKIA is not set
# CONFIG_USB_G_ACM_MS is not set
# CONFIG_USB_G_MULTI is not set
# CONFIG_USB_G_HID is not set
# CONFIG_USB_G_DBGP is not set
# CONFIG_USB_G_WEBCAM is not set
CONFIG_USB_RAW_GADGET=y
# end of USB Gadget precomposed configurations

CONFIG_TYPEC=y
CONFIG_TYPEC_TCPM=y
CONFIG_TYPEC_TCPCI=y
CONFIG_TYPEC_RT1711H=y
CONFIG_TYPEC_MT6360=y
CONFIG_TYPEC_TCPCI_MT6370=y
CONFIG_TYPEC_TCPCI_MAXIM=y
CONFIG_TYPEC_FUSB302=y
CONFIG_TYPEC_WCOVE=y
CONFIG_TYPEC_UCSI=y
CONFIG_UCSI_CCG=y
CONFIG_UCSI_ACPI=y
CONFIG_UCSI_STM32G0=y
CONFIG_TYPEC_TPS6598X=y
CONFIG_TYPEC_ANX7411=y
CONFIG_TYPEC_RT1719=y
CONFIG_TYPEC_HD3SS3220=y
CONFIG_TYPEC_STUSB160X=y
CONFIG_TYPEC_WUSB3801=y

#
# USB Type-C Multiplexer/DeMultiplexer Switch support
#
CONFIG_TYPEC_MUX_FSA4480=y
CONFIG_TYPEC_MUX_GPIO_SBU=y
CONFIG_TYPEC_MUX_PI3USB30532=y
CONFIG_TYPEC_MUX_INTEL_PMC=y
# CONFIG_TYPEC_MUX_IT5205 is not set
CONFIG_TYPEC_MUX_NB7VPQ904M=y
# CONFIG_TYPEC_MUX_PS883X is not set
CONFIG_TYPEC_MUX_PTN36502=y
# CONFIG_TYPEC_MUX_TUSB1046 is not set
CONFIG_TYPEC_MUX_WCD939X_USBSS=y
# end of USB Type-C Multiplexer/DeMultiplexer Switch support

#
# USB Type-C Alternate Mode drivers
#
CONFIG_TYPEC_DP_ALTMODE=y
CONFIG_TYPEC_NVIDIA_ALTMODE=y
# CONFIG_TYPEC_TBT_ALTMODE is not set
# end of USB Type-C Alternate Mode drivers

CONFIG_USB_ROLE_SWITCH=y
CONFIG_USB_ROLES_INTEL_XHCI=y
CONFIG_MMC=y
# CONFIG_PWRSEQ_EMMC is not set
# CONFIG_PWRSEQ_SD8787 is not set
# CONFIG_PWRSEQ_SIMPLE is not set
# CONFIG_MMC_BLOCK is not set
# CONFIG_SDIO_UART is not set
# CONFIG_MMC_TEST is not set
# CONFIG_MMC_CRYPTO is not set

#
# MMC/SD/SDIO Host Controller Drivers
#
# CONFIG_MMC_DEBUG is not set
# CONFIG_MMC_SDHCI is not set
# CONFIG_MMC_WBSD is not set
# CONFIG_MMC_TIFM_SD is not set
# CONFIG_MMC_SPI is not set
# CONFIG_MMC_SDRICOH_CS is not set
# CONFIG_MMC_CB710 is not set
# CONFIG_MMC_VIA_SDMMC is not set
CONFIG_MMC_VUB300=y
CONFIG_MMC_USHC=y
# CONFIG_MMC_USDHI6ROL0 is not set
CONFIG_MMC_REALTEK_USB=y
# CONFIG_MMC_CQHCI is not set
# CONFIG_MMC_HSQ is not set
# CONFIG_MMC_TOSHIBA_PCI is not set
# CONFIG_MMC_MTK is not set
# CONFIG_SCSI_UFSHCD is not set
CONFIG_MEMSTICK=y
# CONFIG_MEMSTICK_DEBUG is not set

#
# MemoryStick drivers
#
# CONFIG_MEMSTICK_UNSAFE_RESUME is not set
# CONFIG_MSPRO_BLOCK is not set
# CONFIG_MS_BLOCK is not set

#
# MemoryStick Host Controller Drivers
#
# CONFIG_MEMSTICK_TIFM_MS is not set
# CONFIG_MEMSTICK_JMICRON_38X is not set
# CONFIG_MEMSTICK_R592 is not set
CONFIG_MEMSTICK_REALTEK_USB=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
# CONFIG_LEDS_CLASS_FLASH is not set
CONFIG_LEDS_CLASS_MULTICOLOR=y
# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set

#
# LED drivers
#
# CONFIG_LEDS_AN30259A is not set
# CONFIG_LEDS_APU is not set
# CONFIG_LEDS_OSRAM_AMS_AS3668 is not set
# CONFIG_LEDS_AW200XX is not set
# CONFIG_LEDS_AW2013 is not set
# CONFIG_LEDS_BCM6328 is not set
# CONFIG_LEDS_BCM6358 is not set
# CONFIG_LEDS_CHT_WCOVE is not set
# CONFIG_LEDS_CR0014114 is not set
# CONFIG_LEDS_EL15203000 is not set
# CONFIG_LEDS_LM3530 is not set
# CONFIG_LEDS_LM3532 is not set
# CONFIG_LEDS_LM3642 is not set
# CONFIG_LEDS_LM3692X is not set
# CONFIG_LEDS_PCA9532 is not set
# CONFIG_LEDS_GPIO is not set
# CONFIG_LEDS_LP3944 is not set
# CONFIG_LEDS_LP3952 is not set
# CONFIG_LEDS_LP50XX is not set
# CONFIG_LEDS_LP55XX_COMMON is not set
# CONFIG_LEDS_LP8860 is not set
# CONFIG_LEDS_LP8864 is not set
# CONFIG_LEDS_PCA955X is not set
# CONFIG_LEDS_PCA963X is not set
# CONFIG_LEDS_PCA995X is not set
# CONFIG_LEDS_DAC124S085 is not set
# CONFIG_LEDS_REGULATOR is not set
# CONFIG_LEDS_BD2606MVV is not set
# CONFIG_LEDS_BD2802 is not set
# CONFIG_LEDS_INTEL_SS4200 is not set
# CONFIG_LEDS_LT3593 is not set
# CONFIG_LEDS_TCA6507 is not set
# CONFIG_LEDS_TLC591XX is not set
# CONFIG_LEDS_LM355x is not set
# CONFIG_LEDS_IS31FL319X is not set
# CONFIG_LEDS_IS31FL32XX is not set

#
# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)
#
# CONFIG_LEDS_BLINKM is not set
# CONFIG_LEDS_SYSCON is not set
# CONFIG_LEDS_MLXCPLD is not set
# CONFIG_LEDS_MLXREG is not set
# CONFIG_LEDS_USER is not set
# CONFIG_LEDS_NIC78BX is not set
# CONFIG_LEDS_SPI_BYTE is not set
# CONFIG_LEDS_LM3697 is not set
# CONFIG_LEDS_ST1202 is not set
# CONFIG_LEDS_LGM is not set

#
# Flash and Torch LED drivers
#

#
# RGB LED drivers
#
# CONFIG_LEDS_GROUP_MULTICOLOR is not set
# CONFIG_LEDS_KTD202X is not set
# CONFIG_LEDS_LP5812 is not set
# CONFIG_LEDS_LP5860_CORE is not set
# CONFIG_LEDS_LP5860_SPI is not set
# CONFIG_LEDS_NCP5623 is not set
# CONFIG_LEDS_MT6370_RGB is not set

#
# LED Triggers
#
CONFIG_LEDS_TRIGGERS=y
# CONFIG_LEDS_TRIGGER_TIMER is not set
# CONFIG_LEDS_TRIGGER_ONESHOT is not set
# CONFIG_LEDS_TRIGGER_DISK is not set
# CONFIG_LEDS_TRIGGER_MTD is not set
# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
# CONFIG_LEDS_TRIGGER_ACTIVITY is not set
# CONFIG_LEDS_TRIGGER_GPIO is not set
# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set

#
# iptables trigger is under Netfilter config (LED target)
#
# CONFIG_LEDS_TRIGGER_TRANSIENT is not set
# CONFIG_LEDS_TRIGGER_CAMERA is not set
# CONFIG_LEDS_TRIGGER_PANIC is not set
# CONFIG_LEDS_TRIGGER_NETDEV is not set
# CONFIG_LEDS_TRIGGER_PATTERN is not set
# CONFIG_LEDS_TRIGGER_TTY is not set
# CONFIG_LEDS_TRIGGER_INPUT_EVENTS is not set

#
# Simatic LED drivers
#
# CONFIG_ACCESSIBILITY is not set
CONFIG_INFINIBAND=y
CONFIG_INFINIBAND_USER_MAD=y
CONFIG_INFINIBAND_USER_ACCESS=y
CONFIG_INFINIBAND_USER_ACCESS_CORE=y
CONFIG_INFINIBAND_USER_MEM=y
CONFIG_INFINIBAND_ON_DEMAND_PAGING=y
CONFIG_INFINIBAND_ADDR_TRANS=y
CONFIG_INFINIBAND_ADDR_TRANS_CONFIGFS=y
CONFIG_INFINIBAND_VIRT_DMA=y
# CONFIG_INFINIBAND_EFA is not set
# CONFIG_INFINIBAND_ERDMA is not set
CONFIG_MLX4_INFINIBAND=y
# CONFIG_INFINIBAND_MTHCA is not set
# CONFIG_INFINIBAND_OCRDMA is not set
# CONFIG_INFINIBAND_USNIC is not set
# CONFIG_INFINIBAND_VMWARE_PVRDMA is not set
# CONFIG_INFINIBAND_RDMAVT is not set
CONFIG_RDMA_RXE=y
CONFIG_RDMA_SIW=y
CONFIG_INFINIBAND_IPOIB=y
CONFIG_INFINIBAND_IPOIB_CM=y
CONFIG_INFINIBAND_IPOIB_DEBUG=y
# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
CONFIG_INFINIBAND_SRP=y
# CONFIG_INFINIBAND_SRPT is not set
CONFIG_INFINIBAND_ISER=y
CONFIG_INFINIBAND_RTRS=y
CONFIG_INFINIBAND_RTRS_CLIENT=y
# CONFIG_INFINIBAND_RTRS_SERVER is not set
CONFIG_EDAC_ATOMIC_SCRUB=y
CONFIG_EDAC_SUPPORT=y
CONFIG_EDAC=y
# CONFIG_EDAC_DEBUG is not set
# CONFIG_EDAC_DECODE_MCE is not set
# CONFIG_EDAC_SCRUB is not set
# CONFIG_EDAC_ECS is not set
# CONFIG_EDAC_MEM_REPAIR is not set
# CONFIG_EDAC_E752X is not set
# CONFIG_EDAC_I82975X is not set
# CONFIG_EDAC_I3000 is not set
# CONFIG_EDAC_I3200 is not set
# CONFIG_EDAC_IE31200 is not set
# CONFIG_EDAC_X38 is not set
# CONFIG_EDAC_I5400 is not set
# CONFIG_EDAC_I7CORE is not set
# CONFIG_EDAC_I5100 is not set
# CONFIG_EDAC_I7300 is not set
# CONFIG_EDAC_SBRIDGE is not set
# CONFIG_EDAC_SKX is not set
# CONFIG_EDAC_I10NM is not set
# CONFIG_EDAC_IMH is not set
# CONFIG_EDAC_PND2 is not set
# CONFIG_EDAC_IGEN6 is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_MC146818_LIB=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_HCTOSYS is not set
CONFIG_RTC_SYSTOHC=y
CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
# CONFIG_RTC_DEBUG is not set
# CONFIG_RTC_NVMEM is not set

#
# RTC interfaces
#
CONFIG_RTC_INTF_SYSFS=y
CONFIG_RTC_INTF_PROC=y
CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
# CONFIG_RTC_DRV_TEST is not set

#
# I2C RTC drivers
#
# CONFIG_RTC_DRV_ABB5ZES3 is not set
# CONFIG_RTC_DRV_ABEOZ9 is not set
# CONFIG_RTC_DRV_ABX80X is not set
# CONFIG_RTC_DRV_DS1307 is not set
# CONFIG_RTC_DRV_DS1374 is not set
# CONFIG_RTC_DRV_DS1672 is not set
# CONFIG_RTC_DRV_HYM8563 is not set
# CONFIG_RTC_DRV_MAX6900 is not set
# CONFIG_RTC_DRV_MAX31335 is not set
# CONFIG_RTC_DRV_NCT3018Y is not set
# CONFIG_RTC_DRV_RS5C372 is not set
# CONFIG_RTC_DRV_ISL1208 is not set
# CONFIG_RTC_DRV_ISL12022 is not set
# CONFIG_RTC_DRV_ISL12026 is not set
# CONFIG_RTC_DRV_X1205 is not set
# CONFIG_RTC_DRV_PCF8523 is not set
# CONFIG_RTC_DRV_PCF85363 is not set
# CONFIG_RTC_DRV_PCF8563 is not set
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_BQ32K is not set
# CONFIG_RTC_DRV_TWL4030 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
# CONFIG_RTC_DRV_RX8010 is not set
# CONFIG_RTC_DRV_RX8111 is not set
# CONFIG_RTC_DRV_RX8581 is not set
# CONFIG_RTC_DRV_RX8025 is not set
# CONFIG_RTC_DRV_EM3027 is not set
# CONFIG_RTC_DRV_RV3028 is not set
# CONFIG_RTC_DRV_RV3032 is not set
# CONFIG_RTC_DRV_RV8803 is not set
# CONFIG_RTC_DRV_SD2405AL is not set
# CONFIG_RTC_DRV_SD3078 is not set

#
# SPI RTC drivers
#
# CONFIG_RTC_DRV_M41T93 is not set
# CONFIG_RTC_DRV_M41T94 is not set
# CONFIG_RTC_DRV_DS1302 is not set
# CONFIG_RTC_DRV_DS1305 is not set
# CONFIG_RTC_DRV_DS1343 is not set
# CONFIG_RTC_DRV_DS1347 is not set
# CONFIG_RTC_DRV_DS1390 is not set
# CONFIG_RTC_DRV_MAX6916 is not set
# CONFIG_RTC_DRV_R9701 is not set
# CONFIG_RTC_DRV_RX4581 is not set
# CONFIG_RTC_DRV_RS5C348 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
# CONFIG_RTC_DRV_PCF2123 is not set
# CONFIG_RTC_DRV_MCP795 is not set
CONFIG_RTC_I2C_AND_SPI=y

#
# SPI and I2C RTC drivers
#
# CONFIG_RTC_DRV_DS3232 is not set
# CONFIG_RTC_DRV_PCF2127 is not set
# CONFIG_RTC_DRV_PCF85063 is not set
# CONFIG_RTC_DRV_RV3029C2 is not set
# CONFIG_RTC_DRV_RX6110 is not set

#
# Platform RTC drivers
#
CONFIG_RTC_DRV_CMOS=y
# CONFIG_RTC_DRV_DS1286 is not set
# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1685_FAMILY is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_DS2404 is not set
# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
# CONFIG_RTC_DRV_MSM6242 is not set
# CONFIG_RTC_DRV_RP5C01 is not set
# CONFIG_RTC_DRV_ZYNQMP is not set

#
# on-CPU RTC drivers
#
# CONFIG_RTC_DRV_CADENCE is not set
# CONFIG_RTC_DRV_FTRTC010 is not set
# CONFIG_RTC_DRV_R7301 is not set
# CONFIG_RTC_DRV_GOLDFISH is not set

#
# HID Sensor RTC drivers
#
CONFIG_RTC_DRV_HID_SENSOR_TIME=y
CONFIG_DMADEVICES=y
# CONFIG_DMADEVICES_DEBUG is not set

#
# DMA Devices
#
CONFIG_DMA_ENGINE=y
CONFIG_DMA_VIRTUAL_CHANNELS=y
CONFIG_DMA_ACPI=y
CONFIG_DMA_OF=y
# CONFIG_ALTERA_MSGDMA is not set
# CONFIG_DW_AXI_DMAC is not set
# CONFIG_FSL_EDMA is not set
CONFIG_INTEL_IDMA64=y
# CONFIG_INTEL_IDXD is not set
# CONFIG_INTEL_IDXD_COMPAT is not set
CONFIG_INTEL_IOATDMA=y
# CONFIG_PLX_DMA is not set
# CONFIG_SWITCHTEC_DMA is not set
# CONFIG_XILINX_DMA is not set
# CONFIG_XILINX_XDMA is not set
# CONFIG_XILINX_ZYNQMP_DPDMA is not set
# CONFIG_AMD_PTDMA is not set
# CONFIG_AMD_QDMA is not set
# CONFIG_QCOM_HIDMA_MGMT is not set
# CONFIG_QCOM_HIDMA is not set
CONFIG_DW_DMAC_CORE=y
# CONFIG_DW_DMAC is not set
# CONFIG_DW_DMAC_PCI is not set
# CONFIG_DW_EDMA is not set
CONFIG_HSU_DMA=y
# CONFIG_SF_PDMA is not set
# CONFIG_INTEL_LDMA is not set

#
# DMA Clients
#
CONFIG_ASYNC_TX_DMA=y
# CONFIG_DMATEST is not set
CONFIG_DMA_ENGINE_RAID=y

#
# DMABUF options
#
CONFIG_SYNC_FILE=y
CONFIG_SW_SYNC=y
CONFIG_UDMABUF=y
# CONFIG_DMABUF_DEBUG is not set
CONFIG_DMABUF_HEAPS=y
CONFIG_DMABUF_HEAPS_SYSTEM=y
# CONFIG_DMABUF_HEAPS_SYSTEM_CC_SHARED is not set
CONFIG_DMABUF_HEAPS_CMA=y
# end of DMABUF options

CONFIG_DCA=y
# CONFIG_UIO is not set
CONFIG_VFIO=y
CONFIG_VFIO_DEVICE_CDEV=y
# CONFIG_VFIO_GROUP is not set
CONFIG_VFIO_VIRQFD=y
# CONFIG_VFIO_DEBUGFS is not set

#
# VFIO support for PCI devices
#
CONFIG_VFIO_PCI_CORE=y
CONFIG_VFIO_PCI_INTX=y
CONFIG_VFIO_PCI=y
# CONFIG_VFIO_PCI_VGA is not set
# CONFIG_VFIO_PCI_IGD is not set
# CONFIG_VIRTIO_VFIO_PCI is not set
# end of VFIO support for PCI devices

CONFIG_IRQ_BYPASS_MANAGER=y
# CONFIG_VIRT_DRIVERS is not set
CONFIG_VIRTIO_ANCHOR=y
CONFIG_VIRTIO=y
CONFIG_VIRTIO_PCI_LIB=y
CONFIG_VIRTIO_PCI_LIB_LEGACY=y
CONFIG_VIRTIO_MENU=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_PCI_ADMIN_LEGACY=y
CONFIG_VIRTIO_PCI_LEGACY=y
CONFIG_VIRTIO_VDPA=y
CONFIG_VIRTIO_PMEM=y
CONFIG_VIRTIO_BALLOON=y
CONFIG_VIRTIO_MEM=y
CONFIG_VIRTIO_INPUT=y
CONFIG_VIRTIO_MMIO=y
CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
CONFIG_VIRTIO_DMA_SHARED_BUFFER=y
# CONFIG_VIRTIO_DEBUG is not set
# CONFIG_VIRTIO_RTC is not set
CONFIG_VDPA=y
CONFIG_VDPA_SIM=y
CONFIG_VDPA_SIM_NET=y
CONFIG_VDPA_SIM_BLOCK=y
# CONFIG_VDPA_USER is not set
# CONFIG_IFCVF is not set
# CONFIG_MLX5_VDPA_STEERING_DEBUG is not set
CONFIG_VP_VDPA=y
# CONFIG_ALIBABA_ENI_VDPA is not set
# CONFIG_SNET_VDPA is not set
# CONFIG_OCTEONEP_VDPA is not set
CONFIG_VHOST_IOTLB=y
CONFIG_VHOST_RING=y
CONFIG_VHOST_TASK=y
CONFIG_VHOST=y
CONFIG_VHOST_MENU=y
CONFIG_VHOST_NET=y
# CONFIG_VHOST_SCSI is not set
CONFIG_VHOST_VSOCK=y
CONFIG_VHOST_VDPA=y
CONFIG_VHOST_CROSS_ENDIAN_LEGACY=y
CONFIG_VHOST_ENABLE_FORK_OWNER_CONTROL=y

#
# Microsoft Hyper-V guest support
#
# CONFIG_HYPERV is not set
# end of Microsoft Hyper-V guest support

CONFIG_GREYBUS=y
# CONFIG_GREYBUS_BEAGLEPLAY is not set
CONFIG_GREYBUS_ES2=y
CONFIG_COMEDI=y
# CONFIG_COMEDI_DEBUG is not set
CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB=2048
CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB=20480
CONFIG_COMEDI_MISC_DRIVERS=y
CONFIG_COMEDI_BOND=y
CONFIG_COMEDI_TEST=y
CONFIG_COMEDI_PARPORT=y
CONFIG_COMEDI_ISA_DRIVERS=y
CONFIG_COMEDI_PCL711=y
CONFIG_COMEDI_PCL724=y
CONFIG_COMEDI_PCL726=y
CONFIG_COMEDI_PCL730=y
CONFIG_COMEDI_PCL812=y
CONFIG_COMEDI_PCL816=y
CONFIG_COMEDI_PCL818=y
CONFIG_COMEDI_PCM3724=y
CONFIG_COMEDI_AMPLC_DIO200_ISA=y
CONFIG_COMEDI_AMPLC_PC236_ISA=y
CONFIG_COMEDI_AMPLC_PC263_ISA=y
CONFIG_COMEDI_RTI800=y
CONFIG_COMEDI_RTI802=y
CONFIG_COMEDI_DAC02=y
CONFIG_COMEDI_DAS16M1=y
CONFIG_COMEDI_DAS08_ISA=y
# CONFIG_COMEDI_DAS16 is not set
CONFIG_COMEDI_DAS800=y
CONFIG_COMEDI_DAS1800=y
CONFIG_COMEDI_DAS6402=y
CONFIG_COMEDI_DT2801=y
CONFIG_COMEDI_DT2811=y
CONFIG_COMEDI_DT2814=y
CONFIG_COMEDI_DT2815=y
CONFIG_COMEDI_DT2817=y
CONFIG_COMEDI_DT282X=y
CONFIG_COMEDI_DMM32AT=y
CONFIG_COMEDI_FL512=y
CONFIG_COMEDI_AIO_AIO12_8=y
CONFIG_COMEDI_AIO_IIRO_16=y
# CONFIG_COMEDI_II_PCI20KC is not set
CONFIG_COMEDI_C6XDIGIO=y
CONFIG_COMEDI_MPC624=y
CONFIG_COMEDI_ADQ12B=y
CONFIG_COMEDI_NI_AT_A2150=y
CONFIG_COMEDI_NI_AT_AO=y
# CONFIG_COMEDI_NI_ATMIO is not set
CONFIG_COMEDI_NI_ATMIO16D=y
CONFIG_COMEDI_NI_LABPC_ISA=y
CONFIG_COMEDI_PCMAD=y
CONFIG_COMEDI_PCMDA12=y
CONFIG_COMEDI_PCMMIO=y
CONFIG_COMEDI_PCMUIO=y
CONFIG_COMEDI_MULTIQ3=y
CONFIG_COMEDI_S526=y
CONFIG_COMEDI_PCI_DRIVERS=y
CONFIG_COMEDI_8255_PCI=y
# CONFIG_COMEDI_ADDI_APCI_1032 is not set
# CONFIG_COMEDI_ADDI_APCI_1500 is not set
# CONFIG_COMEDI_ADDI_APCI_1516 is not set
# CONFIG_COMEDI_ADDI_APCI_1564 is not set
# CONFIG_COMEDI_ADDI_APCI_16XX is not set
# CONFIG_COMEDI_ADDI_APCI_2032 is not set
# CONFIG_COMEDI_ADDI_APCI_2200 is not set
# CONFIG_COMEDI_ADDI_APCI_3120 is not set
# CONFIG_COMEDI_ADDI_APCI_3501 is not set
# CONFIG_COMEDI_ADDI_APCI_3XXX is not set
# CONFIG_COMEDI_ADL_PCI6208 is not set
# CONFIG_COMEDI_ADL_PCI7250 is not set
# CONFIG_COMEDI_ADL_PCI7X3X is not set
# CONFIG_COMEDI_ADL_PCI8164 is not set
# CONFIG_COMEDI_ADL_PCI9111 is not set
CONFIG_COMEDI_ADL_PCI9118=y
# CONFIG_COMEDI_ADV_PCI1710 is not set
# CONFIG_COMEDI_ADV_PCI1720 is not set
# CONFIG_COMEDI_ADV_PCI1723 is not set
# CONFIG_COMEDI_ADV_PCI1724 is not set
# CONFIG_COMEDI_ADV_PCI1760 is not set
# CONFIG_COMEDI_ADV_PCI_DIO is not set
# CONFIG_COMEDI_AMPLC_DIO200_PCI is not set
# CONFIG_COMEDI_AMPLC_PC236_PCI is not set
# CONFIG_COMEDI_AMPLC_PC263_PCI is not set
# CONFIG_COMEDI_AMPLC_PCI224 is not set
# CONFIG_COMEDI_AMPLC_PCI230 is not set
# CONFIG_COMEDI_CONTEC_PCI_DIO is not set
# CONFIG_COMEDI_DAS08_PCI is not set
# CONFIG_COMEDI_DT3000 is not set
# CONFIG_COMEDI_DYNA_PCI10XX is not set
# CONFIG_COMEDI_GSC_HPDI is not set
# CONFIG_COMEDI_MF6X4 is not set
# CONFIG_COMEDI_ICP_MULTI is not set
# CONFIG_COMEDI_DAQBOARD2000 is not set
# CONFIG_COMEDI_JR3_PCI is not set
# CONFIG_COMEDI_KE_COUNTER is not set
# CONFIG_COMEDI_CB_PCIDAS64 is not set
# CONFIG_COMEDI_CB_PCIDAS is not set
# CONFIG_COMEDI_CB_PCIDDA is not set
# CONFIG_COMEDI_CB_PCIMDAS is not set
# CONFIG_COMEDI_CB_PCIMDDA is not set
# CONFIG_COMEDI_ME4000 is not set
# CONFIG_COMEDI_ME_DAQ is not set
# CONFIG_COMEDI_NI_6527 is not set
# CONFIG_COMEDI_NI_65XX is not set
# CONFIG_COMEDI_NI_660X is not set
# CONFIG_COMEDI_NI_670X is not set
CONFIG_COMEDI_NI_LABPC_PCI=y
# CONFIG_COMEDI_NI_PCIDIO is not set
# CONFIG_COMEDI_NI_PCIMIO is not set
# CONFIG_COMEDI_RTD520 is not set
# CONFIG_COMEDI_S626 is not set
CONFIG_COMEDI_PCMCIA_DRIVERS=y
# CONFIG_COMEDI_CB_DAS16_CS is not set
# CONFIG_COMEDI_DAS08_CS is not set
CONFIG_COMEDI_NI_DAQ_700_CS=y
# CONFIG_COMEDI_NI_DAQ_DIO24_CS is not set
CONFIG_COMEDI_NI_LABPC_CS=y
# CONFIG_COMEDI_NI_MIO_CS is not set
# CONFIG_COMEDI_QUATECH_DAQP_CS is not set
CONFIG_COMEDI_USB_DRIVERS=y
CONFIG_COMEDI_DT9812=y
CONFIG_COMEDI_NI_USB6501=y
CONFIG_COMEDI_USBDUX=y
CONFIG_COMEDI_USBDUXFAST=y
CONFIG_COMEDI_USBDUXSIGMA=y
CONFIG_COMEDI_VMK80XX=y
CONFIG_COMEDI_8254=y
CONFIG_COMEDI_8255=y
CONFIG_COMEDI_8255_SA=y
CONFIG_COMEDI_KCOMEDILIB=y
CONFIG_COMEDI_AMPLC_DIO200=y
CONFIG_COMEDI_AMPLC_PC236=y
CONFIG_COMEDI_DAS08=y
CONFIG_COMEDI_ISADMA=y
CONFIG_COMEDI_NI_LABPC=y
CONFIG_COMEDI_NI_LABPC_ISADMA=y
# CONFIG_COMEDI_TESTS is not set
# CONFIG_GPIB is not set
CONFIG_STAGING=y
# CONFIG_RTL8723BS is not set

#
# IIO staging drivers
#

#
# Accelerometers
#
# CONFIG_ADIS16203 is not set
# end of Accelerometers

#
# Analog to digital converters
#
# CONFIG_AD7816 is not set
# end of Analog to digital converters

#
# Analog digital bi-direction converters
#
# CONFIG_ADT7316 is not set
# end of Analog digital bi-direction converters

#
# Direct Digital Synthesis
#
# CONFIG_AD9832 is not set
# CONFIG_AD9834 is not set
# end of Direct Digital Synthesis

#
# Network Analyzer, Impedance Converters
#
# CONFIG_AD5933 is not set
# end of Network Analyzer, Impedance Converters
# end of IIO staging drivers

# CONFIG_FB_SM750 is not set
# CONFIG_STAGING_MEDIA is not set
# CONFIG_FB_TFT is not set
# CONFIG_MOST_COMPONENTS is not set
# CONFIG_GREYBUS_AUDIO is not set
# CONFIG_GREYBUS_BOOTROM is not set
# CONFIG_GREYBUS_FIRMWARE is not set
CONFIG_GREYBUS_HID=y
# CONFIG_GREYBUS_LOG is not set
# CONFIG_GREYBUS_LOOPBACK is not set
# CONFIG_GREYBUS_POWER is not set
# CONFIG_GREYBUS_RAW is not set
# CONFIG_GREYBUS_VIBRATOR is not set
CONFIG_GREYBUS_BRIDGED_PHY=y
# CONFIG_GREYBUS_GPIO is not set
# CONFIG_GREYBUS_I2C is not set
# CONFIG_GREYBUS_SDIO is not set
# CONFIG_GREYBUS_SPI is not set
# CONFIG_GREYBUS_UART is not set
CONFIG_GREYBUS_USB=y
# CONFIG_XIL_AXIS_FIFO is not set
# CONFIG_VME_BUS is not set
# CONFIG_GOLDFISH is not set
# CONFIG_CHROME_PLATFORMS is not set
# CONFIG_MELLANOX_PLATFORM is not set
CONFIG_SURFACE_PLATFORMS=y
# CONFIG_SURFACE3_WMI is not set
# CONFIG_SURFACE_3_POWER_OPREGION is not set
# CONFIG_SURFACE_ACPI_NOTIFY is not set
# CONFIG_SURFACE_AGGREGATOR_CDEV is not set
# CONFIG_SURFACE_AGGREGATOR_HUB is not set
CONFIG_SURFACE_AGGREGATOR_REGISTRY=y
# CONFIG_SURFACE_AGGREGATOR_TABLET_SWITCH is not set
# CONFIG_SURFACE_DTX is not set
# CONFIG_SURFACE_GPE is not set
# CONFIG_SURFACE_HOTPLUG is not set
# CONFIG_SURFACE_PLATFORM_PROFILE is not set
# CONFIG_SURFACE_PRO3_BUTTON is not set
CONFIG_SURFACE_AGGREGATOR=y
CONFIG_SURFACE_AGGREGATOR_BUS=y
CONFIG_X86_PLATFORM_DEVICES=y
CONFIG_WMI_BMOF=y
# CONFIG_HUAWEI_WMI is not set
# CONFIG_X86_PLATFORM_DRIVERS_UNIWILL is not set
# CONFIG_MXM_WMI is not set
# CONFIG_NVIDIA_WMI_EC_BACKLIGHT is not set
# CONFIG_XIAOMI_WMI is not set
# CONFIG_REDMI_WMI is not set
# CONFIG_GIGABYTE_WMI is not set
# CONFIG_BITLAND_MIFS_WMI is not set
# CONFIG_ACERHDF is not set
# CONFIG_ACER_WIRELESS is not set
# CONFIG_ACER_WMI is not set

#
# AMD HSMP Driver
#
# CONFIG_AMD_HSMP_ACPI is not set
# CONFIG_AMD_HSMP_PLAT is not set
# end of AMD HSMP Driver

# CONFIG_AMD_PMC is not set
# CONFIG_AMD_HFI is not set
# CONFIG_AMD_3D_VCACHE is not set
# CONFIG_AMD_WBRF is not set
# CONFIG_AMD_ISP_PLATFORM is not set
# CONFIG_ADV_SWBUTTON is not set
# CONFIG_APPLE_GMUX is not set
# CONFIG_ASUS_LAPTOP is not set
# CONFIG_ASUS_WIRELESS is not set
# CONFIG_ASUS_ARMOURY is not set
CONFIG_ASUS_WMI=y
# CONFIG_ASUS_WMI_DEPRECATED_ATTRS is not set
# CONFIG_ASUS_NB_WMI is not set
CONFIG_ASUS_TF103C_DOCK=y
# CONFIG_AYANEO_EC is not set
CONFIG_EEEPC_LAPTOP=y
# CONFIG_EEEPC_WMI is not set
# CONFIG_X86_PLATFORM_DRIVERS_DELL is not set
# CONFIG_AMILO_RFKILL is not set
# CONFIG_FUJITSU_LAPTOP is not set
# CONFIG_FUJITSU_TABLET is not set
# CONFIG_GPD_POCKET_FAN is not set
# CONFIG_X86_PLATFORM_DRIVERS_HP is not set
# CONFIG_WIRELESS_HOTKEY is not set
# CONFIG_IBM_RTL is not set
# CONFIG_SENSORS_HDAPS is not set
# CONFIG_INTEL_ATOMISP2_PM is not set
# CONFIG_INTEL_IFS is not set
# CONFIG_INTEL_SAR_INT1092 is not set
# CONFIG_INTEL_SKL_INT3472 is not set

#
# Intel Speed Select Technology interface support
#
# CONFIG_INTEL_SPEED_SELECT_INTERFACE is not set
# end of Intel Speed Select Technology interface support

# CONFIG_INTEL_WMI_SBL_FW_UPDATE is not set
# CONFIG_INTEL_WMI_THUNDERBOLT is not set

#
# Intel Uncore Frequency Control
#
# CONFIG_INTEL_UNCORE_FREQ_CONTROL is not set
# end of Intel Uncore Frequency Control

# CONFIG_INTEL_HID_EVENT is not set
# CONFIG_INTEL_VBTN is not set
# CONFIG_INTEL_EHL_PSE_IO is not set
# CONFIG_INTEL_INT0002_VGPIO is not set
# CONFIG_INTEL_OAKTRAIL is not set
# CONFIG_INTEL_BXTWC_PMIC_TMU is not set
CONFIG_INTEL_CHTWC_INT33FE=y
CONFIG_INTEL_ISHTP_ECLITE=y
# CONFIG_INTEL_PUNIT_IPC is not set
# CONFIG_INTEL_RST is not set
# CONFIG_INTEL_SMARTCONNECT is not set
# CONFIG_INTEL_TURBO_MAX_3 is not set
# CONFIG_INTEL_VSEC is not set
# CONFIG_IDEAPAD_LAPTOP is not set
# CONFIG_LENOVO_WMI_HOTKEY_UTILITIES is not set
# CONFIG_LENOVO_WMI_CAMERA is not set
# CONFIG_THINKPAD_ACPI is not set
# CONFIG_THINKPAD_LMI is not set
# CONFIG_YOGABOOK is not set
# CONFIG_YT2_1380 is not set
# CONFIG_LENOVO_WMI_GAMEZONE is not set
# CONFIG_LENOVO_WMI_TUNING is not set
# CONFIG_ACPI_QUICKSTART is not set
# CONFIG_MEEGOPAD_ANX7428 is not set
# CONFIG_MSI_EC is not set
# CONFIG_MSI_LAPTOP is not set
# CONFIG_MSI_WMI is not set
# CONFIG_MSI_WMI_PLATFORM is not set
# CONFIG_PCENGINES_APU2 is not set
# CONFIG_PORTWELL_EC is not set
# CONFIG_BARCO_P50_GPIO is not set
# CONFIG_SAMSUNG_GALAXYBOOK is not set
# CONFIG_SAMSUNG_LAPTOP is not set
# CONFIG_SAMSUNG_Q10 is not set
# CONFIG_ACPI_TOSHIBA is not set
# CONFIG_TOSHIBA_BT_RFKILL is not set
# CONFIG_TOSHIBA_HAPS is not set
# CONFIG_TOSHIBA_WMI is not set
# CONFIG_ACPI_CMPC is not set
# CONFIG_COMPAL_LAPTOP is not set
# CONFIG_LG_LAPTOP is not set
# CONFIG_PANASONIC_LAPTOP is not set
# CONFIG_SONY_LAPTOP is not set
# CONFIG_SYSTEM76_ACPI is not set
# CONFIG_TOPSTAR_LAPTOP is not set
# CONFIG_SERIAL_MULTI_INSTANTIATE is not set
# CONFIG_INSPUR_PLATFORM_PROFILE is not set
# CONFIG_DASHARO_ACPI is not set
# CONFIG_INTEL_IPS is not set
CONFIG_INTEL_SCU_IPC=y
# CONFIG_INTEL_SCU_PCI is not set
# CONFIG_INTEL_SCU_PLATFORM is not set
# CONFIG_SIEMENS_SIMATIC_IPC is not set
# CONFIG_SILICOM_PLATFORM is not set
# CONFIG_WINMATE_FM07_KEYS is not set
# CONFIG_OXP_EC is not set
# CONFIG_TUXEDO_NB04_WMI_AB is not set
CONFIG_P2SB=y
CONFIG_ACPI_WMI=y
# CONFIG_ACPI_WMI_LEGACY_DEVICE_NAMES is not set
CONFIG_HAVE_CLK=y
CONFIG_HAVE_CLK_PREPARE=y
CONFIG_COMMON_CLK=y
# CONFIG_LMK04832 is not set
# CONFIG_COMMON_CLK_MAX9485 is not set
# CONFIG_COMMON_CLK_SI5341 is not set
# CONFIG_COMMON_CLK_SI5351 is not set
# CONFIG_COMMON_CLK_SI514 is not set
# CONFIG_COMMON_CLK_SI544 is not set
# CONFIG_COMMON_CLK_SI570 is not set
# CONFIG_COMMON_CLK_CDCE706 is not set
# CONFIG_COMMON_CLK_CDCE925 is not set
# CONFIG_COMMON_CLK_CS2000_CP is not set
# CONFIG_CLK_TWL is not set
# CONFIG_COMMON_CLK_AXI_CLKGEN is not set
# CONFIG_COMMON_CLK_RS9_PCIE is not set
# CONFIG_COMMON_CLK_SI521XX is not set
# CONFIG_COMMON_CLK_VC3 is not set
# CONFIG_COMMON_CLK_VC5 is not set
# CONFIG_COMMON_CLK_VC7 is not set
# CONFIG_COMMON_CLK_FIXED_MMIO is not set
# CONFIG_CLK_LGM_CGU is not set
# CONFIG_XILINX_VCU is not set
# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set
# CONFIG_HWSPINLOCK is not set

#
# Clock Source drivers
#
CONFIG_CLKEVT_I8253=y
CONFIG_I8253_LOCK=y
CONFIG_CLKBLD_I8253=y
# end of Clock Source drivers

CONFIG_MAILBOX=y
# CONFIG_PLATFORM_MHU is not set
CONFIG_PCC=y
# CONFIG_ALTERA_MBOX is not set
# CONFIG_MAILBOX_TEST is not set
CONFIG_IOMMU_IOVA=y
CONFIG_IOMMU_API=y
CONFIG_IOMMUFD_DRIVER=y
CONFIG_IOMMU_SUPPORT=y

#
# Generic IOMMU Pagetable Support
#
# end of Generic IOMMU Pagetable Support

# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
CONFIG_IOMMU_IOPF=y
CONFIG_AMD_IOMMU=y
# CONFIG_AMD_IOMMU_IOMMUFD is not set
CONFIG_DMAR_TABLE=y
CONFIG_INTEL_IOMMU=y
CONFIG_INTEL_IOMMU_SVM=y
CONFIG_INTEL_IOMMU_DEFAULT_ON=y
CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON=y
CONFIG_INTEL_IOMMU_PERF_EVENTS=y
CONFIG_IOMMUFD_DRIVER_CORE=y
CONFIG_IOMMUFD=y
CONFIG_IOMMUFD_TEST=y
CONFIG_IRQ_REMAP=y
# CONFIG_VIRTIO_IOMMU is not set
CONFIG_GENERIC_PT=y
CONFIG_DEBUG_GENERIC_PT=y
CONFIG_IOMMU_PT=y
CONFIG_IOMMU_PT_AMDV1=y
CONFIG_IOMMU_PT_VTDSS=y
# CONFIG_IOMMU_PT_RISCV64 is not set
CONFIG_IOMMU_PT_X86_64=y

#
# Remoteproc drivers
#
# CONFIG_REMOTEPROC is not set
# end of Remoteproc drivers

#
# Rpmsg drivers
#
# CONFIG_RPMSG_QCOM_GLINK_RPM is not set
# CONFIG_RPMSG_VIRTIO is not set
# end of Rpmsg drivers

CONFIG_SOUNDWIRE=y

#
# SoundWire Devices
#
# CONFIG_SOUNDWIRE_AMD is not set
# CONFIG_SOUNDWIRE_INTEL is not set
# CONFIG_SOUNDWIRE_QCOM is not set

#
# SOC (System On Chip) specific Drivers
#

#
# Amlogic SoC drivers
#
# end of Amlogic SoC drivers

#
# Broadcom SoC drivers
#
# end of Broadcom SoC drivers

#
# NXP/Freescale QorIQ SoC drivers
#
# end of NXP/Freescale QorIQ SoC drivers

#
# fujitsu SoC drivers
#
# end of fujitsu SoC drivers

#
# i.MX SoC drivers
#
# end of i.MX SoC drivers

#
# Enable LiteX SoC Builder specific drivers
#
# CONFIG_LITEX_SOC_CONTROLLER is not set
# end of Enable LiteX SoC Builder specific drivers

# CONFIG_WPCM450_SOC is not set

#
# Qualcomm SoC drivers
#
CONFIG_QCOM_QMI_HELPERS=y
# end of Qualcomm SoC drivers

# CONFIG_SOC_TI is not set

#
# Xilinx SoC drivers
#
# end of Xilinx SoC drivers
# end of SOC (System On Chip) specific Drivers

#
# PM Domains
#

#
# Amlogic PM Domains
#
# end of Amlogic PM Domains

#
# Broadcom PM Domains
#
# end of Broadcom PM Domains

#
# i.MX PM Domains
#
# end of i.MX PM Domains

#
# Qualcomm PM Domains
#
# end of Qualcomm PM Domains
# end of PM Domains

# CONFIG_PM_DEVFREQ is not set
CONFIG_EXTCON=y

#
# Extcon Device Drivers
#
# CONFIG_EXTCON_ADC_JACK is not set
# CONFIG_EXTCON_FSA9480 is not set
# CONFIG_EXTCON_GPIO is not set
# CONFIG_EXTCON_INTEL_INT3496 is not set
CONFIG_EXTCON_INTEL_CHT_WC=y
# CONFIG_EXTCON_LC824206XA is not set
# CONFIG_EXTCON_MAX3355 is not set
# CONFIG_EXTCON_MAX14526 is not set
CONFIG_EXTCON_PTN5150=y
# CONFIG_EXTCON_RT8973A is not set
# CONFIG_EXTCON_SM5502 is not set
# CONFIG_EXTCON_USB_GPIO is not set
CONFIG_EXTCON_USBC_TUSB320=y
# CONFIG_MEMORY is not set
CONFIG_IIO=y
CONFIG_IIO_BUFFER=y
# CONFIG_IIO_BUFFER_CB is not set
# CONFIG_IIO_BUFFER_DMA is not set
# CONFIG_IIO_BUFFER_DMAENGINE is not set
# CONFIG_IIO_BUFFER_HW_CONSUMER is not set
CONFIG_IIO_KFIFO_BUF=y
CONFIG_IIO_TRIGGERED_BUFFER=y
# CONFIG_IIO_CONFIGFS is not set
CONFIG_IIO_TRIGGER=y
CONFIG_IIO_CONSUMERS_PER_TRIGGER=2
# CONFIG_IIO_SW_DEVICE is not set
# CONFIG_IIO_SW_TRIGGER is not set
# CONFIG_IIO_TRIGGERED_EVENT is not set

#
# Accelerometers
#
# CONFIG_ADIS16201 is not set
# CONFIG_ADIS16209 is not set
# CONFIG_ADXL313_I2C is not set
# CONFIG_ADXL313_SPI is not set
# CONFIG_ADXL345_I2C is not set
# CONFIG_ADXL345_SPI is not set
# CONFIG_ADXL355_I2C is not set
# CONFIG_ADXL355_SPI is not set
# CONFIG_ADXL367_SPI is not set
# CONFIG_ADXL367_I2C is not set
# CONFIG_ADXL372_SPI is not set
# CONFIG_ADXL372_I2C is not set
# CONFIG_ADXL380_SPI is not set
# CONFIG_ADXL380_I2C is not set
# CONFIG_BMA180 is not set
# CONFIG_BMA220 is not set
# CONFIG_BMA400 is not set
# CONFIG_BMC150_ACCEL is not set
# CONFIG_BMI088_ACCEL is not set
# CONFIG_DA280 is not set
# CONFIG_DA311 is not set
# CONFIG_DMARD06 is not set
# CONFIG_DMARD09 is not set
# CONFIG_DMARD10 is not set
# CONFIG_FXLS8962AF_I2C is not set
# CONFIG_FXLS8962AF_SPI is not set
CONFIG_HID_SENSOR_ACCEL_3D=y
# CONFIG_IIO_ST_ACCEL_3AXIS is not set
# CONFIG_IIO_KX022A_SPI is not set
# CONFIG_IIO_KX022A_I2C is not set
# CONFIG_KXSD9 is not set
# CONFIG_KXCJK1013 is not set
# CONFIG_MC3230 is not set
# CONFIG_MMA7455_I2C is not set
# CONFIG_MMA7455_SPI is not set
# CONFIG_MMA7660 is not set
# CONFIG_MMA8452 is not set
# CONFIG_MMA9551 is not set
# CONFIG_MMA9553 is not set
# CONFIG_MSA311 is not set
# CONFIG_MXC4005 is not set
# CONFIG_MXC6255 is not set
# CONFIG_SCA3000 is not set
# CONFIG_SCA3300 is not set
# CONFIG_STK8312 is not set
# CONFIG_STK8BA50 is not set
# end of Accelerometers

#
# Analog to digital converters
#
# CONFIG_AD4000 is not set
# CONFIG_AD4080 is not set
# CONFIG_AD4130 is not set
# CONFIG_AD4134 is not set
# CONFIG_AD4170_4 is not set
# CONFIG_AD4691 is not set
# CONFIG_AD4695 is not set
# CONFIG_AD7091R5 is not set
# CONFIG_AD7091R8 is not set
# CONFIG_AD7124 is not set
# CONFIG_AD7173 is not set
# CONFIG_AD7191 is not set
# CONFIG_AD7192 is not set
# CONFIG_AD7266 is not set
# CONFIG_AD7280 is not set
# CONFIG_AD7291 is not set
# CONFIG_AD7292 is not set
# CONFIG_AD7298 is not set
# CONFIG_AD7380 is not set
# CONFIG_AD7476 is not set
# CONFIG_AD7606_IFACE_PARALLEL is not set
# CONFIG_AD7606_IFACE_SPI is not set
# CONFIG_AD7766 is not set
# CONFIG_AD7768_1 is not set
# CONFIG_AD7779 is not set
# CONFIG_AD7780 is not set
# CONFIG_AD7791 is not set
# CONFIG_AD7793 is not set
# CONFIG_AD7887 is not set
# CONFIG_AD7923 is not set
# CONFIG_AD7944 is not set
# CONFIG_AD7949 is not set
# CONFIG_AD799X is not set
# CONFIG_AD9467 is not set
# CONFIG_ADE9000 is not set
# CONFIG_CC10001_ADC is not set
CONFIG_DLN2_ADC=y
# CONFIG_ENVELOPE_DETECTOR is not set
# CONFIG_GEHC_PMC_ADC is not set
# CONFIG_HI8435 is not set
# CONFIG_HX711 is not set
# CONFIG_INA2XX_ADC is not set
# CONFIG_LTC2309 is not set
# CONFIG_LTC2471 is not set
# CONFIG_LTC2485 is not set
# CONFIG_LTC2496 is not set
# CONFIG_LTC2497 is not set
# CONFIG_MAX1027 is not set
# CONFIG_MAX11100 is not set
# CONFIG_MAX1118 is not set
# CONFIG_MAX11205 is not set
# CONFIG_MAX11410 is not set
# CONFIG_MAX1241 is not set
# CONFIG_MAX1363 is not set
# CONFIG_MAX14001 is not set
# CONFIG_MAX34408 is not set
# CONFIG_MAX9611 is not set
# CONFIG_MCP320X is not set
# CONFIG_MCP3422 is not set
# CONFIG_MCP3564 is not set
# CONFIG_MCP3911 is not set
# CONFIG_MEDIATEK_MT6360_ADC is not set
# CONFIG_MEDIATEK_MT6370_ADC is not set
# CONFIG_NAU7802 is not set
# CONFIG_NCT7201 is not set
# CONFIG_PAC1921 is not set
# CONFIG_PAC1934 is not set
# CONFIG_ROHM_BD79112 is not set
# CONFIG_ROHM_BD79124 is not set
# CONFIG_RICHTEK_RTQ6056 is not set
# CONFIG_SD_ADC_MODULATOR is not set
# CONFIG_TI_ADC081C is not set
# CONFIG_TI_ADC0832 is not set
# CONFIG_TI_ADC084S021 is not set
# CONFIG_TI_ADC108S102 is not set
# CONFIG_TI_ADC12138 is not set
# CONFIG_TI_ADC128S052 is not set
# CONFIG_TI_ADC161S626 is not set
# CONFIG_TI_ADS1015 is not set
# CONFIG_TI_ADS1018 is not set
# CONFIG_TI_ADS1100 is not set
# CONFIG_TI_ADS1119 is not set
# CONFIG_TI_ADS124S08 is not set
# CONFIG_TI_ADS1298 is not set
# CONFIG_TI_ADS131E08 is not set
# CONFIG_TI_ADS131M02 is not set
# CONFIG_TI_ADS7138 is not set
# CONFIG_TI_ADS7924 is not set
# CONFIG_TI_ADS7950 is not set
# CONFIG_TI_ADS8344 is not set
# CONFIG_TI_ADS8688 is not set
# CONFIG_TI_LMP92064 is not set
# CONFIG_TI_TLC4541 is not set
# CONFIG_TI_TSC2046 is not set
# CONFIG_TWL4030_MADC is not set
# CONFIG_TWL6030_GPADC is not set
# CONFIG_VF610_ADC is not set
CONFIG_VIPERBOARD_ADC=y
# CONFIG_XILINX_XADC is not set
# end of Analog to digital converters

#
# Analog to digital and digital to analog converters
#
# CONFIG_AD74115 is not set
# CONFIG_AD74413R is not set
# end of Analog to digital and digital to analog converters

#
# Analog Front Ends
#
# CONFIG_IIO_RESCALE is not set
# end of Analog Front Ends

#
# Amplifiers
#
# CONFIG_AD8366 is not set
# CONFIG_ADA4250 is not set
# CONFIG_ADL8113 is not set
# CONFIG_HMC425 is not set
# end of Amplifiers

#
# Capacitance to digital converters
#
# CONFIG_AD7150 is not set
# CONFIG_AD7746 is not set
# end of Capacitance to digital converters

#
# Chemical Sensors
#
# CONFIG_AOSONG_AGS02MA is not set
# CONFIG_ATLAS_PH_SENSOR is not set
# CONFIG_ATLAS_EZO_SENSOR is not set
# CONFIG_BME680 is not set
# CONFIG_CCS811 is not set
# CONFIG_ENS160 is not set
# CONFIG_IAQCORE is not set
# CONFIG_MHZ19B is not set
# CONFIG_PMS7003 is not set
# CONFIG_SCD30_CORE is not set
# CONFIG_SCD4X is not set
# CONFIG_SEN0322 is not set
# CONFIG_SENSIRION_SGP30 is not set
# CONFIG_SENSIRION_SGP40 is not set
# CONFIG_SPS30_I2C is not set
# CONFIG_SPS30_SERIAL is not set
# CONFIG_SENSEAIR_SUNRISE_CO2 is not set
# CONFIG_VZ89X is not set
# end of Chemical Sensors

#
# Hid Sensor IIO Common
#
CONFIG_HID_SENSOR_IIO_COMMON=y
CONFIG_HID_SENSOR_IIO_TRIGGER=y
# end of Hid Sensor IIO Common

#
# IIO SCMI Sensors
#
# end of IIO SCMI Sensors

#
# SSP Sensor Common
#
# CONFIG_IIO_SSP_SENSORHUB is not set
# end of SSP Sensor Common

#
# Digital to analog converters
#
# CONFIG_AD3530R is not set
# CONFIG_AD3552R_HS is not set
# CONFIG_AD3552R is not set
# CONFIG_AD5064 is not set
# CONFIG_AD5360 is not set
# CONFIG_AD5380 is not set
# CONFIG_AD5421 is not set
# CONFIG_AD5446_SPI is not set
# CONFIG_AD5446_I2C is not set
# CONFIG_AD5449 is not set
# CONFIG_AD5592R is not set
# CONFIG_AD5593R is not set
# CONFIG_AD5504 is not set
# CONFIG_AD5624R_SPI is not set
# CONFIG_AD5706R is not set
# CONFIG_AD9739A is not set
# CONFIG_LTC2688 is not set
# CONFIG_AD5686_SPI is not set
# CONFIG_AD5696_I2C is not set
# CONFIG_AD5755 is not set
# CONFIG_AD5758 is not set
# CONFIG_AD5761 is not set
# CONFIG_AD5764 is not set
# CONFIG_AD5766 is not set
# CONFIG_AD5770R is not set
# CONFIG_AD5791 is not set
# CONFIG_AD7293 is not set
# CONFIG_AD7303 is not set
# CONFIG_AD8460 is not set
# CONFIG_AD8801 is not set
# CONFIG_BD79703 is not set
# CONFIG_CIO_DAC is not set
# CONFIG_DPOT_DAC is not set
# CONFIG_DS4424 is not set
# CONFIG_LTC1660 is not set
# CONFIG_LTC2632 is not set
# CONFIG_LTC2664 is not set
# CONFIG_M62332 is not set
# CONFIG_MAX517 is not set
# CONFIG_MAX22007 is not set
# CONFIG_MAX5522 is not set
# CONFIG_MAX5821 is not set
# CONFIG_MCP4725 is not set
# CONFIG_MCP4728 is not set
# CONFIG_MCP47FEB02 is not set
# CONFIG_MCP4821 is not set
# CONFIG_MCP4922 is not set
# CONFIG_TI_DAC082S085 is not set
# CONFIG_TI_DAC5571 is not set
# CONFIG_TI_DAC7311 is not set
# CONFIG_TI_DAC7612 is not set
# CONFIG_VF610_DAC is not set
# end of Digital to analog converters

#
# IIO dummy driver
#
# end of IIO dummy driver

#
# Filters
#
# CONFIG_ADMV8818 is not set
# end of Filters

#
# Frequency Synthesizers DDS/PLL
#

#
# Clock Generator/Distribution
#
# CONFIG_AD9523 is not set
# end of Clock Generator/Distribution

#
# Phase-Locked Loop (PLL) frequency synthesizers
#
# CONFIG_ADF4350 is not set
# CONFIG_ADF4371 is not set
# CONFIG_ADF4377 is not set
# CONFIG_ADMFM2000 is not set
# CONFIG_ADMV1013 is not set
# CONFIG_ADMV1014 is not set
# CONFIG_ADMV4420 is not set
# CONFIG_ADRF6780 is not set
# end of Phase-Locked Loop (PLL) frequency synthesizers
# end of Frequency Synthesizers DDS/PLL

#
# Digital gyroscope sensors
#
# CONFIG_ADIS16080 is not set
# CONFIG_ADIS16130 is not set
# CONFIG_ADIS16136 is not set
# CONFIG_ADIS16260 is not set
# CONFIG_ADXRS290 is not set
# CONFIG_ADXRS450 is not set
# CONFIG_BMG160 is not set
# CONFIG_FXAS21002C is not set
CONFIG_HID_SENSOR_GYRO_3D=y
# CONFIG_MPU3050_I2C is not set
# CONFIG_IIO_ST_GYRO_3AXIS is not set
# CONFIG_ITG3200 is not set
# end of Digital gyroscope sensors

#
# Health Sensors
#

#
# Heart Rate Monitors
#
# CONFIG_AFE4403 is not set
# CONFIG_AFE4404 is not set
# CONFIG_MAX30100 is not set
# CONFIG_MAX30102 is not set
# end of Heart Rate Monitors
# end of Health Sensors

#
# Humidity sensors
#
# CONFIG_AM2315 is not set
# CONFIG_DHT11 is not set
# CONFIG_ENS210 is not set
# CONFIG_HDC100X is not set
# CONFIG_HDC2010 is not set
# CONFIG_HDC3020 is not set
CONFIG_HID_SENSOR_HUMIDITY=y
# CONFIG_HTS221 is not set
# CONFIG_HTU21 is not set
# CONFIG_SI7005 is not set
# CONFIG_SI7020 is not set
# end of Humidity sensors

#
# Inertial measurement units
#
# CONFIG_ADIS16400 is not set
# CONFIG_ADIS16460 is not set
# CONFIG_ADIS16475 is not set
# CONFIG_ADIS16480 is not set
# CONFIG_ADIS16550 is not set
# CONFIG_BMI160_I2C is not set
# CONFIG_BMI160_SPI is not set
# CONFIG_BMI270_I2C is not set
# CONFIG_BMI270_SPI is not set
# CONFIG_BMI323_I2C is not set
# CONFIG_BMI323_SPI is not set
# CONFIG_BOSCH_BNO055_SERIAL is not set
# CONFIG_BOSCH_BNO055_I2C is not set
# CONFIG_FXOS8700_I2C is not set
# CONFIG_FXOS8700_SPI is not set
# CONFIG_KMX61 is not set
# CONFIG_INV_ICM42600_I2C is not set
# CONFIG_INV_ICM42600_SPI is not set
# CONFIG_INV_ICM45600_I2C is not set
# CONFIG_INV_ICM45600_SPI is not set
# CONFIG_INV_MPU6050_I2C is not set
# CONFIG_INV_MPU6050_SPI is not set
# CONFIG_SMI240 is not set
# CONFIG_SMI330_I2C is not set
# CONFIG_SMI330_SPI is not set
# CONFIG_IIO_ST_LSM6DSX is not set
# CONFIG_IIO_ST_LSM9DS0 is not set
# end of Inertial measurement units

#
# Light sensors
#
# CONFIG_ACPI_ALS is not set
# CONFIG_ADJD_S311 is not set
# CONFIG_ADUX1020 is not set
# CONFIG_AL3000A is not set
# CONFIG_AL3010 is not set
# CONFIG_AL3320A is not set
# CONFIG_APDS9160 is not set
# CONFIG_APDS9300 is not set
# CONFIG_APDS9306 is not set
# CONFIG_APDS9960 is not set
# CONFIG_APDS9999 is not set
# CONFIG_AS73211 is not set
# CONFIG_BH1745 is not set
# CONFIG_BH1750 is not set
# CONFIG_BH1780 is not set
# CONFIG_CM32181 is not set
# CONFIG_CM3232 is not set
# CONFIG_CM3323 is not set
# CONFIG_CM3605 is not set
# CONFIG_CM36651 is not set
# CONFIG_GP2AP002 is not set
# CONFIG_GP2AP020A00F is not set
# CONFIG_SENSORS_ISL29018 is not set
# CONFIG_SENSORS_ISL29028 is not set
# CONFIG_ISL29125 is not set
# CONFIG_ISL76682 is not set
CONFIG_HID_SENSOR_ALS=y
CONFIG_HID_SENSOR_PROX=y
# CONFIG_JSA1212 is not set
# CONFIG_ROHM_BU27034 is not set
# CONFIG_RPR0521 is not set
# CONFIG_LTR390 is not set
# CONFIG_LTR501 is not set
# CONFIG_LTRF216A is not set
# CONFIG_LV0104CS is not set
# CONFIG_MAX44000 is not set
# CONFIG_MAX44009 is not set
# CONFIG_NOA1305 is not set
# CONFIG_OPT3001 is not set
# CONFIG_OPT4001 is not set
# CONFIG_OPT4060 is not set
# CONFIG_PA12203001 is not set
# CONFIG_SI1133 is not set
# CONFIG_SI1145 is not set
# CONFIG_STK3310 is not set
# CONFIG_ST_UVIS25 is not set
# CONFIG_TCS3414 is not set
# CONFIG_TCS3472 is not set
# CONFIG_SENSORS_TSL2563 is not set
# CONFIG_TSL2583 is not set
# CONFIG_TSL2591 is not set
# CONFIG_TSL2772 is not set
# CONFIG_TSL4531 is not set
# CONFIG_US5182D is not set
# CONFIG_VCNL4000 is not set
# CONFIG_VCNL4035 is not set
# CONFIG_VEML3235 is not set
# CONFIG_VEML3328 is not set
# CONFIG_VEML6030 is not set
# CONFIG_VEML6040 is not set
# CONFIG_VEML6046X00 is not set
# CONFIG_VEML6070 is not set
# CONFIG_VEML6075 is not set
# CONFIG_VL6180 is not set
# CONFIG_ZOPT2201 is not set
# end of Light sensors

#
# Magnetometer sensors
#
# CONFIG_AF8133J is not set
# CONFIG_AK8974 is not set
# CONFIG_AK8975 is not set
# CONFIG_AK09911 is not set
# CONFIG_ALS31300 is not set
# CONFIG_BMC150_MAGN_I2C is not set
# CONFIG_BMC150_MAGN_SPI is not set
# CONFIG_MAG3110 is not set
CONFIG_HID_SENSOR_MAGNETOMETER_3D=y
# CONFIG_MMC35240 is not set
# CONFIG_MMC5633 is not set
# CONFIG_MMC5983 is not set
# CONFIG_IIO_ST_MAGN_3AXIS is not set
# CONFIG_INFINEON_TLV493D is not set
# CONFIG_SENSORS_HMC5843_I2C is not set
# CONFIG_SENSORS_HMC5843_SPI is not set
# CONFIG_SENSORS_RM3100_I2C is not set
# CONFIG_SENSORS_RM3100_SPI is not set
# CONFIG_SI7210 is not set
# CONFIG_TI_TMAG5273 is not set
# CONFIG_YAMAHA_YAS530 is not set
# end of Magnetometer sensors

#
# Multiplexers
#
# CONFIG_IIO_MUX is not set
# end of Multiplexers

#
# Inclinometer sensors
#
CONFIG_HID_SENSOR_INCLINOMETER_3D=y
CONFIG_HID_SENSOR_DEVICE_ROTATION=y
# end of Inclinometer sensors

#
# Triggers - standalone
#
# CONFIG_IIO_SYSFS_TRIGGER is not set
# end of Triggers - standalone

#
# Linear and angular position sensors
#
CONFIG_HID_SENSOR_CUSTOM_INTEL_HINGE=y
# end of Linear and angular position sensors

#
# Digital potentiometers
#
# CONFIG_AD5110 is not set
# CONFIG_AD5272 is not set
# CONFIG_DS1803 is not set
# CONFIG_MAX5432 is not set
# CONFIG_MAX5481 is not set
# CONFIG_MAX5487 is not set
# CONFIG_MCP4018 is not set
# CONFIG_MCP4131 is not set
# CONFIG_MCP4531 is not set
# CONFIG_MCP41010 is not set
# CONFIG_TPL0102 is not set
# CONFIG_X9250 is not set
# end of Digital potentiometers

#
# Digital potentiostats
#
# CONFIG_LMP91000 is not set
# end of Digital potentiostats

#
# Pressure sensors
#
# CONFIG_ABP060MG is not set
# CONFIG_ABP2030PA_I2C is not set
# CONFIG_ABP2030PA_SPI is not set
# CONFIG_ROHM_BM1390 is not set
# CONFIG_BMP280 is not set
# CONFIG_DLHL60D is not set
# CONFIG_DPS310 is not set
CONFIG_HID_SENSOR_PRESS=y
# CONFIG_HP03 is not set
# CONFIG_HSC030PA is not set
# CONFIG_ICP10100 is not set
# CONFIG_MPL115_I2C is not set
# CONFIG_MPL115_SPI is not set
# CONFIG_MPL3115 is not set
# CONFIG_MPRLS0025PA_I2C is not set
# CONFIG_MPRLS0025PA_SPI is not set
# CONFIG_MS5611 is not set
# CONFIG_MS5637 is not set
# CONFIG_SDP500 is not set
# CONFIG_IIO_ST_PRESS is not set
# CONFIG_T5403 is not set
# CONFIG_HP206C is not set
# CONFIG_ZPA2326 is not set
# CONFIG_ADP810 is not set
# end of Pressure sensors

#
# Lightning sensors
#
# CONFIG_AS3935 is not set
# end of Lightning sensors

#
# Proximity and distance sensors
#
# CONFIG_D3323AA is not set
# CONFIG_HX9023S is not set
# CONFIG_IRSD200 is not set
# CONFIG_ISL29501 is not set
# CONFIG_LIDAR_LITE_V2 is not set
# CONFIG_MB1232 is not set
# CONFIG_PING is not set
# CONFIG_RFD77402 is not set
# CONFIG_SRF04 is not set
# CONFIG_SX9310 is not set
# CONFIG_SX9324 is not set
# CONFIG_SX9360 is not set
# CONFIG_SX9500 is not set
# CONFIG_SRF08 is not set
# CONFIG_VCNL3020 is not set
# CONFIG_VL53L0X_I2C is not set
# CONFIG_VL53L1X_I2C is not set
# CONFIG_AW96103 is not set
# end of Proximity and distance sensors

#
# Resolver to digital converters
#
# CONFIG_AD2S90 is not set
# CONFIG_AD2S1200 is not set
# CONFIG_AD2S1210 is not set
# end of Resolver to digital converters

#
# Temperature sensors
#
# CONFIG_LTC2983 is not set
# CONFIG_MAXIM_THERMOCOUPLE is not set
CONFIG_HID_SENSOR_TEMP=y
# CONFIG_MLX90614 is not set
# CONFIG_MLX90632 is not set
# CONFIG_MLX90635 is not set
# CONFIG_TMP006 is not set
# CONFIG_TMP007 is not set
# CONFIG_TMP117 is not set
# CONFIG_TSYS01 is not set
# CONFIG_TSYS02D is not set
# CONFIG_MAX30208 is not set
# CONFIG_MAX31856 is not set
# CONFIG_MAX31865 is not set
# CONFIG_MCP9600 is not set
# end of Temperature sensors

# CONFIG_NTB is not set
# CONFIG_PWM is not set

#
# IRQ chip support
#
CONFIG_IRQCHIP=y
CONFIG_IRQ_MSI_LIB=y
# CONFIG_AL_FIC is not set
# CONFIG_XILINX_INTC is not set
# end of IRQ chip support

# CONFIG_IPACK_BUS is not set
CONFIG_RESET_CONTROLLER=y
# CONFIG_RESET_GPIO is not set
# CONFIG_RESET_INTEL_GW is not set
# CONFIG_RESET_SIMPLE is not set
# CONFIG_RESET_TI_SYSCON is not set
# CONFIG_RESET_TI_TPS380X is not set

#
# PHY Subsystem
#
CONFIG_GENERIC_PHY=y
# CONFIG_PHY_CAN_TRANSCEIVER is not set
CONFIG_PHY_GOOGLE_USB=y
CONFIG_USB_LGM_PHY=y
# CONFIG_PHY_NXP_PTN3222 is not set
# CONFIG_PHY_NXP_TJA1145 is not set

#
# PHY drivers for Broadcom platforms
#
# CONFIG_BCM_KONA_USB2_PHY is not set
# end of PHY drivers for Broadcom platforms

# CONFIG_PHY_CADENCE_TORRENT is not set
# CONFIG_PHY_CADENCE_DPHY is not set
# CONFIG_PHY_CADENCE_DPHY_RX is not set
# CONFIG_PHY_CADENCE_SIERRA is not set
# CONFIG_PHY_CADENCE_SALVO is not set
# CONFIG_PHY_INTEL_LGM_COMBO is not set
# CONFIG_PHY_INTEL_LGM_EMMC is not set
# CONFIG_PHY_PXA_28NM_HSIC is not set
# CONFIG_PHY_PXA_28NM_USB2 is not set
CONFIG_PHY_CPCAP_USB=y
# CONFIG_PHY_MAPPHONE_MDM6600 is not set
# CONFIG_PHY_OCELOT_SERDES is not set
CONFIG_PHY_QCOM_USB_HS=y
CONFIG_PHY_QCOM_USB_HSIC=y
CONFIG_PHY_SAMSUNG_USB2=y
# CONFIG_PHY_TI_DS125DF111 is not set
CONFIG_PHY_TUSB1210=y
# end of PHY Subsystem

# CONFIG_POWERCAP is not set
# CONFIG_MCB is not set

#
# Performance monitor support
#
# CONFIG_DWC_PCIE_PMU is not set
# end of Performance monitor support

CONFIG_RAS=y
CONFIG_USB4=y
CONFIG_USB4_CONFIGFS=y
# CONFIG_USB4_DEBUGFS_WRITE is not set
# CONFIG_USB4_DMA_TEST is not set
# CONFIG_USB4_STREAM is not set

#
# Android
#
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ANDROID_BINDERFS=y
CONFIG_ANDROID_BINDER_DEVICES="binder0,binder1"
# end of Android

CONFIG_LIBNVDIMM=y
CONFIG_BLK_DEV_PMEM=y
CONFIG_ND_CLAIM=y
CONFIG_ND_BTT=y
CONFIG_BTT=y
CONFIG_ND_PFN=y
CONFIG_NVDIMM_PFN=y
CONFIG_NVDIMM_DAX=y
CONFIG_OF_PMEM=y
# CONFIG_RAMDAX is not set
CONFIG_NVDIMM_KEYS=y
# CONFIG_NVDIMM_SECURITY_TEST is not set
CONFIG_DAX=y
CONFIG_NVMEM=y
CONFIG_NVMEM_SYSFS=y
CONFIG_NVMEM_LAYOUTS=y

#
# Layout Types
#
# CONFIG_NVMEM_LAYOUT_SL28_VPD is not set
# CONFIG_NVMEM_LAYOUT_ONIE_TLV is not set
# CONFIG_NVMEM_LAYOUT_U_BOOT_ENV is not set
# end of Layout Types

# CONFIG_NVMEM_RMEM is not set
# CONFIG_NVMEM_U_BOOT_ENV is not set

#
# HW tracing support
#
# CONFIG_STM is not set
# CONFIG_INTEL_TH is not set
# end of HW tracing support

# CONFIG_FPGA is not set
# CONFIG_FSI is not set
CONFIG_TEE=y
CONFIG_TEE_DMABUF_HEAPS=y
CONFIG_OPTEE_STATIC_PROTMEM_POOL=y
# CONFIG_MUX_CORE is not set
# CONFIG_SIOX is not set
# CONFIG_SLIMBUS is not set
# CONFIG_INTERCONNECT is not set
CONFIG_COUNTER=y
# CONFIG_INTEL_QEP is not set
# CONFIG_INTERRUPT_CNT is not set
CONFIG_MOST=y
CONFIG_MOST_USB_HDM=y
# CONFIG_MOST_CDEV is not set
# CONFIG_MOST_SND is not set
# CONFIG_PECI is not set
# CONFIG_HTE is not set
# end of Device Drivers

#
# File systems
#
CONFIG_DCACHE_WORD_ACCESS=y
CONFIG_VALIDATE_FS_PARSER=y
CONFIG_FS_IOMAP=y
CONFIG_FS_STACK=y
CONFIG_BUFFER_HEAD=y
CONFIG_LEGACY_DIRECT_IO=y
# CONFIG_EXT2_FS is not set
CONFIG_EXT4_FS=y
CONFIG_EXT4_USE_FOR_EXT2=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
# CONFIG_EXT4_DEBUG is not set
CONFIG_JBD2=y
# CONFIG_JBD2_DEBUG is not set
CONFIG_FS_MBCACHE=y
CONFIG_JFS_FS=y
CONFIG_JFS_POSIX_ACL=y
CONFIG_JFS_SECURITY=y
CONFIG_JFS_DEBUG=y
# CONFIG_JFS_STATISTICS is not set
CONFIG_XFS_FS=y
# CONFIG_XFS_SUPPORT_V4 is not set
# CONFIG_XFS_SUPPORT_ASCII_CI is not set
CONFIG_XFS_QUOTA=y
CONFIG_XFS_POSIX_ACL=y
CONFIG_XFS_RT=y
CONFIG_XFS_DRAIN_INTENTS=y
CONFIG_XFS_LIVE_HOOKS=y
CONFIG_XFS_MEMORY_BUFS=y
CONFIG_XFS_BTREE_IN_MEM=y
CONFIG_XFS_ONLINE_SCRUB=y
# CONFIG_XFS_ONLINE_SCRUB_STATS is not set
CONFIG_XFS_ONLINE_REPAIR=y
# CONFIG_XFS_WARN is not set
# CONFIG_XFS_DEBUG is not set
CONFIG_GFS2_FS=y
CONFIG_GFS2_FS_LOCKING_DLM=y
CONFIG_OCFS2_FS=y
CONFIG_OCFS2_FS_O2CB=y
CONFIG_OCFS2_FS_USERSPACE_CLUSTER=y
CONFIG_OCFS2_FS_STATS=y
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
CONFIG_OCFS2_DEBUG_FS=y
CONFIG_BTRFS_FS=y
CONFIG_BTRFS_FS_POSIX_ACL=y
# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set
# CONFIG_BTRFS_DEBUG is not set
CONFIG_BTRFS_ASSERT=y
# CONFIG_BTRFS_EXPERIMENTAL is not set
CONFIG_NILFS2_FS=y
CONFIG_F2FS_FS=y
CONFIG_F2FS_STAT_FS=y
CONFIG_F2FS_FS_XATTR=y
CONFIG_F2FS_FS_POSIX_ACL=y
CONFIG_F2FS_FS_SECURITY=y
CONFIG_F2FS_CHECK_FS=y
CONFIG_F2FS_FAULT_INJECTION=y
CONFIG_F2FS_FS_COMPRESSION=y
CONFIG_F2FS_FS_LZO=y
CONFIG_F2FS_FS_LZORLE=y
CONFIG_F2FS_FS_LZ4=y
CONFIG_F2FS_FS_LZ4HC=y
CONFIG_F2FS_FS_ZSTD=y
# CONFIG_F2FS_IOSTAT is not set
# CONFIG_F2FS_UNFAIR_RWSEM is not set
CONFIG_ZONEFS_FS=y
CONFIG_FS_DAX=y
CONFIG_FS_POSIX_ACL=y
CONFIG_EXPORTFS=y
CONFIG_EXPORTFS_BLOCK_OPS=y
CONFIG_FILE_LOCKING=y
CONFIG_FS_ENCRYPTION=y
CONFIG_FS_ENCRYPTION_ALGS=y
# CONFIG_FS_ENCRYPTION_INLINE_CRYPT is not set
CONFIG_FS_VERITY=y
CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y
CONFIG_FSNOTIFY=y
CONFIG_DNOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_FANOTIFY=y
CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_QUOTA_DEBUG is not set
CONFIG_QUOTA_TREE=y
# CONFIG_QFMT_V1 is not set
CONFIG_QFMT_V2=y
CONFIG_QUOTACTL=y
CONFIG_AUTOFS_FS=y
CONFIG_FUSE_FS=y
CONFIG_CUSE=y
CONFIG_VIRTIO_FS=y
CONFIG_FUSE_DAX=y
# CONFIG_FUSE_PASSTHROUGH is not set
CONFIG_FUSE_IO_URING=y
CONFIG_OVERLAY_FS=y
CONFIG_OVERLAY_FS_REDIRECT_DIR=y
CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y
CONFIG_OVERLAY_FS_INDEX=y
# CONFIG_OVERLAY_FS_NFS_EXPORT is not set
# CONFIG_OVERLAY_FS_XINO_AUTO is not set
# CONFIG_OVERLAY_FS_METACOPY is not set
CONFIG_OVERLAY_FS_DEBUG=y

#
# Caches
#
CONFIG_NETFS_SUPPORT=y
# CONFIG_NETFS_STATS is not set
# CONFIG_NETFS_DEBUG is not set
CONFIG_FSCACHE=y
# CONFIG_FSCACHE_STATS is not set
CONFIG_CACHEFILES=y
# CONFIG_CACHEFILES_DEBUG is not set
# CONFIG_CACHEFILES_ERROR_INJECTION is not set
# CONFIG_CACHEFILES_ONDEMAND is not set
# end of Caches

#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
CONFIG_UDF_FS=y
# end of CD-ROM/DVD Filesystems

#
# DOS/FAT/EXFAT/NT Filesystems
#
CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_FAT_DEFAULT_CODEPAGE=437
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_FAT_DEFAULT_UTF8 is not set
CONFIG_EXFAT_FS=y
CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8"
# CONFIG_NTFS_FS is not set
CONFIG_NTFS3_FS=y
# CONFIG_NTFS3_64BIT_CLUSTER is not set
CONFIG_NTFS3_LZX_XPRESS=y
CONFIG_NTFS3_FS_POSIX_ACL=y
# end of DOS/FAT/EXFAT/NT Filesystems

#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_VMCORE=y
# CONFIG_PROC_VMCORE_DEVICE_DUMP is not set
CONFIG_PROC_SYSCTL=y
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_PROC_CHILDREN=y
CONFIG_PROC_PID_ARCH_STATUS=y
CONFIG_KERNFS=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_TMPFS_XATTR=y
# CONFIG_TMPFS_INODE64 is not set
CONFIG_TMPFS_QUOTA=y
CONFIG_ARCH_SUPPORTS_HUGETLBFS=y
CONFIG_HUGETLBFS=y
# CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON is not set
CONFIG_HUGETLB_PAGE=y
CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP=y
CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING=y
CONFIG_ARCH_HAS_GIGANTIC_PAGE=y
CONFIG_CONFIGFS_FS=y
# end of Pseudo filesystems

CONFIG_MISC_FILESYSTEMS=y
CONFIG_ORANGEFS_FS=y
CONFIG_ADFS_FS=y
# CONFIG_ADFS_FS_RW is not set
CONFIG_AFFS_FS=y
CONFIG_ECRYPT_FS=y
CONFIG_ECRYPT_FS_MESSAGING=y
CONFIG_HFS_FS=y
CONFIG_HFSPLUS_FS=y
CONFIG_BEFS_FS=y
# CONFIG_BEFS_DEBUG is not set
CONFIG_BFS_FS=y
CONFIG_EFS_FS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
CONFIG_JFFS2_FS_WRITEBUFFER=y
# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
CONFIG_JFFS2_SUMMARY=y
CONFIG_JFFS2_FS_XATTR=y
CONFIG_JFFS2_FS_POSIX_ACL=y
CONFIG_JFFS2_FS_SECURITY=y
CONFIG_JFFS2_COMPRESSION_OPTIONS=y
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_LZO=y
CONFIG_JFFS2_RTIME=y
CONFIG_JFFS2_RUBIN=y
# CONFIG_JFFS2_CMODE_NONE is not set
CONFIG_JFFS2_CMODE_PRIORITY=y
# CONFIG_JFFS2_CMODE_SIZE is not set
# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
CONFIG_UBIFS_FS=y
CONFIG_UBIFS_FS_ADVANCED_COMPR=y
CONFIG_UBIFS_FS_LZO=y
CONFIG_UBIFS_FS_ZLIB=y
CONFIG_UBIFS_FS_ZSTD=y
CONFIG_UBIFS_ATIME_SUPPORT=y
CONFIG_UBIFS_FS_XATTR=y
CONFIG_UBIFS_FS_SECURITY=y
# CONFIG_UBIFS_FS_AUTHENTICATION is not set
CONFIG_CRAMFS=y
CONFIG_CRAMFS_BLOCKDEV=y
CONFIG_CRAMFS_MTD=y
CONFIG_SQUASHFS=y
# CONFIG_SQUASHFS_FILE_CACHE is not set
CONFIG_SQUASHFS_FILE_DIRECT=y
CONFIG_SQUASHFS_DECOMP_MULTI=y
# CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT is not set
# CONFIG_SQUASHFS_COMPILE_DECOMP_SINGLE is not set
CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI=y
# CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI_PERCPU is not set
# CONFIG_SQUASHFS_MOUNT_DECOMP_THREADS is not set
CONFIG_SQUASHFS_XATTR=y
# CONFIG_SQUASHFS_COMP_CACHE_FULL is not set
CONFIG_SQUASHFS_ZLIB=y
CONFIG_SQUASHFS_LZ4=y
CONFIG_SQUASHFS_LZO=y
CONFIG_SQUASHFS_XZ=y
CONFIG_SQUASHFS_ZSTD=y
CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y
# CONFIG_SQUASHFS_EMBEDDED is not set
CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
CONFIG_VXFS_FS=y
CONFIG_MINIX_FS=y
CONFIG_OMFS_FS=y
CONFIG_HPFS_FS=y
CONFIG_QNX4FS_FS=y
CONFIG_QNX6FS_FS=y
# CONFIG_QNX6FS_DEBUG is not set
CONFIG_ROMFS_FS=y
# CONFIG_ROMFS_BACKED_BY_BLOCK is not set
# CONFIG_ROMFS_BACKED_BY_MTD is not set
CONFIG_ROMFS_BACKED_BY_BOTH=y
CONFIG_ROMFS_ON_BLOCK=y
CONFIG_ROMFS_ON_MTD=y
CONFIG_PSTORE=y
CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240
CONFIG_PSTORE_COMPRESS=y
# CONFIG_PSTORE_CONSOLE is not set
# CONFIG_PSTORE_PMSG is not set
# CONFIG_PSTORE_RAM is not set
# CONFIG_PSTORE_BLK is not set
CONFIG_UFS_FS=y
CONFIG_UFS_FS_WRITE=y
# CONFIG_UFS_DEBUG is not set
CONFIG_EROFS_FS=y
# CONFIG_EROFS_FS_DEBUG is not set
CONFIG_EROFS_FS_XATTR=y
CONFIG_EROFS_FS_POSIX_ACL=y
CONFIG_EROFS_FS_SECURITY=y
# CONFIG_EROFS_FS_BACKED_BY_FILE is not set
CONFIG_EROFS_FS_ZIP=y
# CONFIG_EROFS_FS_ZIP_LZMA is not set
# CONFIG_EROFS_FS_ZIP_DEFLATE is not set
# CONFIG_EROFS_FS_ZIP_ZSTD is not set
# CONFIG_EROFS_FS_ZIP_ACCEL is not set
# CONFIG_EROFS_FS_PCPU_KTHREAD is not set
# CONFIG_EROFS_FS_PAGE_CACHE_SHARE is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
# CONFIG_NFS_V2 is not set
CONFIG_NFS_V3=y
CONFIG_NFS_V3_ACL=y
CONFIG_NFS_V4=y
# CONFIG_NFS_SWAP is not set
CONFIG_NFS_V4_0=y
CONFIG_NFS_V4_2=y
CONFIG_PNFS_FILE_LAYOUT=y
CONFIG_PNFS_BLOCK=y
CONFIG_PNFS_FLEXFILE_LAYOUT=y
CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org"
# CONFIG_NFS_V4_1_MIGRATION is not set
CONFIG_NFS_V4_SECURITY_LABEL=y
CONFIG_ROOT_NFS=y
CONFIG_NFS_FSCACHE=y
# CONFIG_NFS_USE_LEGACY_DNS is not set
CONFIG_NFS_USE_KERNEL_DNS=y
# CONFIG_NFS_DISABLE_UDP_SUPPORT is not set
CONFIG_NFS_V4_2_READ_PLUS=y
CONFIG_NFSD=y
# CONFIG_NFSD_V2 is not set
CONFIG_NFSD_V3_ACL=y
CONFIG_NFSD_V4=y
CONFIG_NFSD_PNFS=y
CONFIG_NFSD_BLOCKLAYOUT=y
CONFIG_NFSD_SCSILAYOUT=y
CONFIG_NFSD_FLEXFILELAYOUT=y
CONFIG_NFSD_V4_2_INTER_SSC=y
CONFIG_NFSD_V4_SECURITY_LABEL=y
# CONFIG_NFSD_LEGACY_CLIENT_TRACKING is not set
# CONFIG_NFSD_V4_POSIX_ACLS is not set
CONFIG_GRACE_PERIOD=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_ACL_SUPPORT=y
CONFIG_NFS_COMMON=y
# CONFIG_NFS_LOCALIO is not set
CONFIG_NFS_V4_2_SSC_HELPER=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
CONFIG_SUNRPC_BACKCHANNEL=y
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_SUNRPC_DEBUG is not set
# CONFIG_SUNRPC_XPRT_RDMA is not set
CONFIG_CEPH_FS=y
CONFIG_CEPH_FSCACHE=y
CONFIG_CEPH_FS_POSIX_ACL=y
# CONFIG_CEPH_FS_SECURITY_LABEL is not set
CONFIG_CIFS=y
# CONFIG_CIFS_STATS2 is not set
CONFIG_CIFS_ALLOW_INSECURE_LEGACY=y
CONFIG_CIFS_UPCALL=y
CONFIG_CIFS_XATTR=y
CONFIG_CIFS_POSIX=y
CONFIG_CIFS_DEBUG=y
# CONFIG_CIFS_DEBUG2 is not set
# CONFIG_CIFS_DEBUG_DUMP_KEYS is not set
CONFIG_CIFS_DFS_UPCALL=y
CONFIG_CIFS_SWN_UPCALL=y
CONFIG_CIFS_SMB_DIRECT=y
CONFIG_CIFS_FSCACHE=y
# CONFIG_CIFS_ROOT is not set
# CONFIG_CIFS_COMPRESSION is not set
CONFIG_SMB_SERVER=y
# CONFIG_SMB_SERVER_SMBDIRECT is not set
# CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN is not set
# CONFIG_SMB_SERVER_KERBEROS5 is not set
CONFIG_SMBDIRECT=y
CONFIG_SMBFS=y
# CONFIG_CODA_FS is not set
CONFIG_AFS_FS=y
# CONFIG_AFS_DEBUG is not set
CONFIG_AFS_FSCACHE=y
# CONFIG_AFS_DEBUG_CURSOR is not set
CONFIG_9P_FS=y
CONFIG_9P_FSCACHE=y
CONFIG_9P_FS_POSIX_ACL=y
CONFIG_9P_FS_SECURITY=y
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_CODEPAGE_737=y
CONFIG_NLS_CODEPAGE_775=y
CONFIG_NLS_CODEPAGE_850=y
CONFIG_NLS_CODEPAGE_852=y
CONFIG_NLS_CODEPAGE_855=y
CONFIG_NLS_CODEPAGE_857=y
CONFIG_NLS_CODEPAGE_860=y
CONFIG_NLS_CODEPAGE_861=y
CONFIG_NLS_CODEPAGE_862=y
CONFIG_NLS_CODEPAGE_863=y
CONFIG_NLS_CODEPAGE_864=y
CONFIG_NLS_CODEPAGE_865=y
CONFIG_NLS_CODEPAGE_866=y
CONFIG_NLS_CODEPAGE_869=y
CONFIG_NLS_CODEPAGE_936=y
CONFIG_NLS_CODEPAGE_950=y
CONFIG_NLS_CODEPAGE_932=y
CONFIG_NLS_CODEPAGE_949=y
CONFIG_NLS_CODEPAGE_874=y
CONFIG_NLS_ISO8859_8=y
CONFIG_NLS_CODEPAGE_1250=y
CONFIG_NLS_CODEPAGE_1251=y
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_ISO8859_2=y
CONFIG_NLS_ISO8859_3=y
CONFIG_NLS_ISO8859_4=y
CONFIG_NLS_ISO8859_5=y
CONFIG_NLS_ISO8859_6=y
CONFIG_NLS_ISO8859_7=y
CONFIG_NLS_ISO8859_9=y
CONFIG_NLS_ISO8859_13=y
CONFIG_NLS_ISO8859_14=y
CONFIG_NLS_ISO8859_15=y
CONFIG_NLS_KOI8_R=y
CONFIG_NLS_KOI8_U=y
CONFIG_NLS_MAC_ROMAN=y
CONFIG_NLS_MAC_CELTIC=y
CONFIG_NLS_MAC_CENTEURO=y
CONFIG_NLS_MAC_CROATIAN=y
CONFIG_NLS_MAC_CYRILLIC=y
CONFIG_NLS_MAC_GAELIC=y
CONFIG_NLS_MAC_GREEK=y
CONFIG_NLS_MAC_ICELAND=y
CONFIG_NLS_MAC_INUIT=y
CONFIG_NLS_MAC_ROMANIAN=y
CONFIG_NLS_MAC_TURKISH=y
CONFIG_NLS_UTF8=y
CONFIG_NLS_UCS2_UTILS=y
CONFIG_DLM=y
# CONFIG_DLM_DEBUG is not set
CONFIG_UNICODE=y
CONFIG_IO_WQ=y
# end of File systems

#
# Security options
#
CONFIG_KEYS=y
CONFIG_KEYS_REQUEST_CACHE=y
CONFIG_PERSISTENT_KEYRINGS=y
CONFIG_BIG_KEYS=y
CONFIG_TRUSTED_KEYS=y
# CONFIG_TRUSTED_KEYS_TPM is not set
# CONFIG_TRUSTED_KEYS_TEE is not set

#
# No trust source selected!
#
CONFIG_ENCRYPTED_KEYS=y
# CONFIG_USER_DECRYPTED_DATA is not set
CONFIG_KEY_DH_OPERATIONS=y
CONFIG_KEY_NOTIFICATIONS=y
# CONFIG_SECURITY_DMESG_RESTRICT is not set
# CONFIG_PROC_MEM_ALWAYS_FORCE is not set
CONFIG_PROC_MEM_FORCE_PTRACE=y
# CONFIG_PROC_MEM_NO_FORCE is not set
CONFIG_SECURITY=y
CONFIG_HAS_SECURITY_AUDIT=y
CONFIG_SECURITYFS=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_INFINIBAND=y
CONFIG_SECURITY_NETWORK_XFRM=y
CONFIG_SECURITY_PATH=y
# CONFIG_INTEL_TXT is not set
# CONFIG_STATIC_USERMODEHELPER is not set
# CONFIG_SECURITY_SELINUX is not set
CONFIG_SECURITY_SMACK=y
# CONFIG_SECURITY_SMACK_BRINGUP is not set
CONFIG_SECURITY_SMACK_NETFILTER=y
# CONFIG_SECURITY_SMACK_APPEND_SIGNALS is not set
CONFIG_SECURITY_TOMOYO=y
CONFIG_SECURITY_TOMOYO_MAX_ACCEPT_ENTRY=64
CONFIG_SECURITY_TOMOYO_MAX_AUDIT_LOG=32
CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER=y
CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING=y
# CONFIG_SECURITY_APPARMOR is not set
# CONFIG_SECURITY_LOADPIN is not set
CONFIG_SECURITY_YAMA=y
CONFIG_SECURITY_SAFESETID=y
CONFIG_SECURITY_LOCKDOWN_LSM=y
CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y
CONFIG_LOCK_DOWN_KERNEL_FORCE_NONE=y
# CONFIG_LOCK_DOWN_KERNEL_FORCE_INTEGRITY is not set
# CONFIG_LOCK_DOWN_KERNEL_FORCE_CONFIDENTIALITY is not set
CONFIG_SECURITY_LANDLOCK=y
# CONFIG_SECURITY_IPE is not set
CONFIG_INTEGRITY=y
CONFIG_INTEGRITY_SIGNATURE=y
CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
CONFIG_INTEGRITY_TRUSTED_KEYRING=y
CONFIG_INTEGRITY_AUDIT=y
CONFIG_IMA=y
CONFIG_IMA_MEASURE_PCR_IDX=10
CONFIG_IMA_LSM_RULES=y
CONFIG_IMA_NG_TEMPLATE=y
# CONFIG_IMA_SIG_TEMPLATE is not set
CONFIG_IMA_DEFAULT_TEMPLATE="ima-ng"
# CONFIG_IMA_DEFAULT_HASH_SHA1 is not set
CONFIG_IMA_DEFAULT_HASH_SHA256=y
# CONFIG_IMA_DEFAULT_HASH_SHA512 is not set
# CONFIG_IMA_DEFAULT_HASH_WP512 is not set
CONFIG_IMA_DEFAULT_HASH="sha256"
CONFIG_IMA_WRITE_POLICY=y
CONFIG_IMA_READ_POLICY=y
CONFIG_IMA_APPRAISE=y
# CONFIG_IMA_ARCH_POLICY is not set
# CONFIG_IMA_APPRAISE_BUILD_POLICY is not set
# CONFIG_IMA_APPRAISE_BOOTPARAM is not set
CONFIG_IMA_APPRAISE_MODSIG=y
# CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY is not set
# CONFIG_IMA_BLACKLIST_KEYRING is not set
# CONFIG_IMA_LOAD_X509 is not set
CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS=y
CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS=y
# CONFIG_IMA_DISABLE_HTABLE is not set
# CONFIG_IMA_STAGING is not set
CONFIG_EVM=y
CONFIG_EVM_ATTR_FSUUID=y
CONFIG_EVM_EXTRA_SMACK_XATTRS=y
CONFIG_EVM_ADD_XATTRS=y
# CONFIG_EVM_LOAD_X509 is not set
CONFIG_DEFAULT_SECURITY_SMACK=y
# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
# CONFIG_DEFAULT_SECURITY_DAC is not set
CONFIG_LSM="landlock,lockdown,yama,safesetid,integrity,tomoyo,smack,bpf"

#
# Kernel hardening options
#

#
# Memory initialization
#
CONFIG_CC_HAS_AUTO_VAR_INIT_PATTERN=y
CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO_BARE=y
CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO=y
# CONFIG_INIT_STACK_NONE is not set
# CONFIG_INIT_STACK_ALL_PATTERN is not set
CONFIG_INIT_STACK_ALL_ZERO=y
CONFIG_CC_HAS_SANCOV_STACK_DEPTH_CALLBACK=y
# CONFIG_KSTACK_ERASE is not set
CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y
# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set
CONFIG_CC_HAS_ZERO_CALL_USED_REGS=y
# CONFIG_ZERO_CALL_USED_REGS is not set
# end of Memory initialization

#
# Bounds checking
#
CONFIG_FORTIFY_SOURCE=y
CONFIG_HARDENED_USERCOPY=y
# CONFIG_HARDENED_USERCOPY_DEFAULT_ON is not set
# end of Bounds checking

#
# Hardening of kernel data structures
#
CONFIG_LIST_HARDENED=y
CONFIG_BUG_ON_DATA_CORRUPTION=y
# end of Hardening of kernel data structures

CONFIG_CC_HAS_RANDSTRUCT=y
CONFIG_RANDSTRUCT_NONE=y
# CONFIG_RANDSTRUCT_FULL is not set
# end of Kernel hardening options
# end of Security options

CONFIG_ASYNC_CORE=y
CONFIG_ASYNC_MEMCPY=y
CONFIG_ASYNC_XOR=y
CONFIG_ASYNC_PQ=y
CONFIG_ASYNC_RAID6_RECOV=y
CONFIG_CRYPTO=y

#
# Crypto core or helper
#
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_SIG=y
CONFIG_CRYPTO_SIG2=y
CONFIG_CRYPTO_SKCIPHER=y
CONFIG_CRYPTO_SKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_AKCIPHER2=y
CONFIG_CRYPTO_AKCIPHER=y
CONFIG_CRYPTO_KPP2=y
CONFIG_CRYPTO_KPP=y
CONFIG_CRYPTO_ACOMP2=y
CONFIG_CRYPTO_ACOMP=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_USER=y
# CONFIG_CRYPTO_SELFTESTS is not set
# CONFIG_CRYPTO_NULL is not set
CONFIG_CRYPTO_PCRYPT=y
# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_AUTHENC=y
CONFIG_CRYPTO_KRB5ENC=y
# CONFIG_CRYPTO_BENCHMARK is not set
CONFIG_CRYPTO_ENGINE=y
# end of Crypto core or helper

#
# Public-key cryptography
#
CONFIG_CRYPTO_RSA=y
CONFIG_CRYPTO_DH=y
# CONFIG_CRYPTO_DH_RFC7919_GROUPS is not set
CONFIG_CRYPTO_ECC=y
CONFIG_CRYPTO_ECDH=y
# CONFIG_CRYPTO_ECDSA is not set
CONFIG_CRYPTO_ECRDSA=y
CONFIG_CRYPTO_MLDSA=y
# end of Public-key cryptography

#
# Block ciphers
#
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_ANUBIS=y
CONFIG_CRYPTO_ARIA=y
CONFIG_CRYPTO_BLOWFISH=y
CONFIG_CRYPTO_BLOWFISH_COMMON=y
CONFIG_CRYPTO_CAMELLIA=y
CONFIG_CRYPTO_CAST_COMMON=y
CONFIG_CRYPTO_CAST5=y
CONFIG_CRYPTO_CAST6=y
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_KHAZAD=y
CONFIG_CRYPTO_SEED=y
CONFIG_CRYPTO_SERPENT=y
CONFIG_CRYPTO_SM4=y
CONFIG_CRYPTO_SM4_GENERIC=y
CONFIG_CRYPTO_TEA=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRYPTO_TWOFISH_COMMON=y
# end of Block ciphers

#
# Length-preserving ciphers and modes
#
CONFIG_CRYPTO_ADIANTUM=y
CONFIG_CRYPTO_ARC4=y
CONFIG_CRYPTO_CHACHA20=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_CTR=y
CONFIG_CRYPTO_CTS=y
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_HCTR2=y
CONFIG_CRYPTO_LRW=y
CONFIG_CRYPTO_XCTR=y
CONFIG_CRYPTO_XTS=y
# end of Length-preserving ciphers and modes

#
# AEAD (authenticated encryption with associated data) ciphers
#
CONFIG_CRYPTO_AEGIS128=y
CONFIG_CRYPTO_CHACHA20POLY1305=y
CONFIG_CRYPTO_CCM=y
CONFIG_CRYPTO_GCM=y
CONFIG_CRYPTO_GENIV=y
CONFIG_CRYPTO_SEQIV=y
CONFIG_CRYPTO_ECHAINIV=y
CONFIG_CRYPTO_ESSIV=y
# end of AEAD (authenticated encryption with associated data) ciphers

#
# Hashes, digests, and MACs
#
# CONFIG_CRYPTO_BLAKE2B is not set
CONFIG_CRYPTO_CMAC=y
CONFIG_CRYPTO_HMAC=y
# CONFIG_CRYPTO_MD4 is not set
# CONFIG_CRYPTO_MD5 is not set
CONFIG_CRYPTO_RMD160=y
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_SHA3=y
# CONFIG_CRYPTO_SM3 is not set
CONFIG_CRYPTO_STREEBOG=y
CONFIG_CRYPTO_WP512=y
CONFIG_CRYPTO_XCBC=y
# CONFIG_CRYPTO_XXHASH is not set
# end of Hashes, digests, and MACs

#
# CRCs (cyclic redundancy checks)
#
# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_CRC32 is not set
# end of CRCs (cyclic redundancy checks)

#
# Compression
#
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_LZO=y
CONFIG_CRYPTO_842=y
CONFIG_CRYPTO_LZ4=y
CONFIG_CRYPTO_LZ4HC=y
CONFIG_CRYPTO_ZSTD=y
# end of Compression

#
# Random number generation
#
# CONFIG_CRYPTO_DRBG is not set
# CONFIG_CRYPTO_JITTERENTROPY is not set
CONFIG_CRYPTO_KDF800108_CTR=y
# end of Random number generation

#
# Userspace interface (deprecated)
#
CONFIG_CRYPTO_USER_API=y
CONFIG_CRYPTO_USER_API_HASH=y
CONFIG_CRYPTO_USER_API_SKCIPHER=y
CONFIG_CRYPTO_USER_API_RNG=y
CONFIG_CRYPTO_USER_API_AEAD=y
CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE=y
# end of Userspace interface (deprecated)

#
# Accelerated Cryptographic Algorithms for CPU (x86)
#
CONFIG_CRYPTO_AES_NI_INTEL=y
CONFIG_CRYPTO_BLOWFISH_X86_64=y
CONFIG_CRYPTO_CAMELLIA_X86_64=y
CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64=y
CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64=y
CONFIG_CRYPTO_CAST5_AVX_X86_64=y
CONFIG_CRYPTO_CAST6_AVX_X86_64=y
CONFIG_CRYPTO_SERPENT_SSE2_X86_64=y
CONFIG_CRYPTO_SERPENT_AVX_X86_64=y
CONFIG_CRYPTO_SERPENT_AVX2_X86_64=y
CONFIG_CRYPTO_SM4_AESNI_AVX_X86_64=y
CONFIG_CRYPTO_SM4_AESNI_AVX2_X86_64=y
CONFIG_CRYPTO_TWOFISH_X86_64=y
CONFIG_CRYPTO_TWOFISH_X86_64_3WAY=y
CONFIG_CRYPTO_TWOFISH_AVX_X86_64=y
CONFIG_CRYPTO_ARIA_AESNI_AVX_X86_64=y
# CONFIG_CRYPTO_ARIA_AESNI_AVX2_X86_64 is not set
# CONFIG_CRYPTO_ARIA_GFNI_AVX512_X86_64 is not set
CONFIG_CRYPTO_AEGIS128_AESNI_SSE2=y
# end of Accelerated Cryptographic Algorithms for CPU (x86)

CONFIG_CRYPTO_HW=y
CONFIG_CRYPTO_DEV_PADLOCK=y
CONFIG_CRYPTO_DEV_PADLOCK_AES=y
CONFIG_CRYPTO_DEV_PADLOCK_SHA=y
# CONFIG_CRYPTO_DEV_ATMEL_ECC is not set
# CONFIG_CRYPTO_DEV_ATMEL_SHA204A is not set
CONFIG_CRYPTO_DEV_CCP=y
CONFIG_CRYPTO_DEV_CCP_DD=y
# CONFIG_CRYPTO_DEV_SP_CCP is not set
# CONFIG_CRYPTO_DEV_SP_PSP is not set
# CONFIG_CRYPTO_DEV_NITROX_CNN55XX is not set
CONFIG_CRYPTO_DEV_QAT=y
CONFIG_CRYPTO_DEV_QAT_DH895xCC=y
CONFIG_CRYPTO_DEV_QAT_C3XXX=y
CONFIG_CRYPTO_DEV_QAT_C62X=y
# CONFIG_CRYPTO_DEV_QAT_4XXX is not set
# CONFIG_CRYPTO_DEV_QAT_420XX is not set
# CONFIG_CRYPTO_DEV_QAT_6XXX is not set
CONFIG_CRYPTO_DEV_QAT_DH895xCCVF=y
CONFIG_CRYPTO_DEV_QAT_C3XXXVF=y
CONFIG_CRYPTO_DEV_QAT_C62XVF=y
# CONFIG_CRYPTO_DEV_QAT_ERROR_INJECTION is not set
CONFIG_CRYPTO_DEV_VIRTIO=y
# CONFIG_CRYPTO_DEV_SAFEXCEL is not set
# CONFIG_CRYPTO_DEV_CCREE is not set
# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set
CONFIG_ASYMMETRIC_KEY_TYPE=y
CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
CONFIG_X509_CERTIFICATE_PARSER=y
CONFIG_PKCS8_PRIVATE_KEY_PARSER=y
CONFIG_PKCS7_MESSAGE_PARSER=y
# CONFIG_PKCS7_WAIVE_AUTHATTRS_REJECTION_FOR_MLDSA is not set
CONFIG_PKCS7_TEST_KEY=y
CONFIG_SIGNED_PE_FILE_VERIFICATION=y
# CONFIG_FIPS_SIGNATURE_SELFTEST is not set

#
# Certificates for signature checking
#
CONFIG_MODULE_SIG_KEY="certs/signing_key.pem"
# CONFIG_MODULE_SIG_KEY_TYPE_RSA is not set
CONFIG_MODULE_SIG_KEY_TYPE_MLDSA_44=y
# CONFIG_MODULE_SIG_KEY_TYPE_MLDSA_65 is not set
# CONFIG_MODULE_SIG_KEY_TYPE_MLDSA_87 is not set
CONFIG_SYSTEM_TRUSTED_KEYRING=y
CONFIG_SYSTEM_TRUSTED_KEYS=""
# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set
CONFIG_SECONDARY_TRUSTED_KEYRING=y
# CONFIG_SECONDARY_TRUSTED_KEYRING_SIGNED_BY_BUILTIN is not set
# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set
CONFIG_OPENSSL_SUPPORTS_ML_DSA=y
# end of Certificates for signature checking

CONFIG_CRYPTO_KRB5=y
# CONFIG_CRYPTO_KRB5_SELFTESTS is not set
CONFIG_BINARY_PRINTF=y

#
# Library routines
#
CONFIG_LINEAR_RANGES=y
# CONFIG_PACKING is not set
CONFIG_BITREVERSE=y
CONFIG_GENERIC_BITREVERSE=y
CONFIG_GENERIC_STRNCPY_FROM_USER=y
CONFIG_GENERIC_STRNLEN_USER=y
CONFIG_GENERIC_NET_UTILS=y
# CONFIG_CORDIC is not set
# CONFIG_PRIME_NUMBERS is not set
CONFIG_RATIONAL=y
CONFIG_GENERIC_IOMAP=y
CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
CONFIG_ARCH_HAS_FAST_MULTIPLIER=y
CONFIG_ARCH_USE_SYM_ANNOTATIONS=y
CONFIG_CRC8=y
CONFIG_CRC16=y
CONFIG_CRC_CCITT=y
CONFIG_CRC_ITU_T=y
CONFIG_CRC_T10DIF=y
CONFIG_CRC_T10DIF_ARCH=y
CONFIG_CRC32=y
CONFIG_CRC32_ARCH=y
CONFIG_CRC64=y
CONFIG_CRC64_ARCH=y
CONFIG_CRC_OPTIMIZATIONS=y
CONFIG_CRYPTO_HASH_INFO=y
CONFIG_CRYPTO_LIB_UTILS=y
CONFIG_CRYPTO_LIB_AES=y
CONFIG_CRYPTO_LIB_AES_ARCH=y
CONFIG_CRYPTO_LIB_AES_CBC_MACS=y
CONFIG_CRYPTO_LIB_ARC4=y
CONFIG_CRYPTO_LIB_GF128MUL=y
CONFIG_CRYPTO_LIB_BLAKE2B=y
CONFIG_CRYPTO_LIB_BLAKE2S_ARCH=y
CONFIG_CRYPTO_LIB_CHACHA=y
CONFIG_CRYPTO_LIB_CHACHA_ARCH=y
CONFIG_CRYPTO_LIB_CURVE25519=y
CONFIG_CRYPTO_LIB_CURVE25519_ARCH=y
CONFIG_CRYPTO_LIB_CURVE25519_GENERIC=y
CONFIG_CRYPTO_LIB_DES=y
CONFIG_CRYPTO_LIB_GF128HASH=y
CONFIG_CRYPTO_LIB_GF128HASH_ARCH=y
CONFIG_CRYPTO_LIB_MD5=y
CONFIG_CRYPTO_LIB_MLDSA=y
CONFIG_CRYPTO_LIB_NH=y
CONFIG_CRYPTO_LIB_NH_ARCH=y
CONFIG_CRYPTO_LIB_POLY1305=y
CONFIG_CRYPTO_LIB_POLY1305_ARCH=y
CONFIG_CRYPTO_LIB_POLY1305_GENERIC=y
CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11
CONFIG_CRYPTO_LIB_CHACHA20POLY1305=y
CONFIG_CRYPTO_LIB_SHA1=y
CONFIG_CRYPTO_LIB_SHA1_ARCH=y
CONFIG_CRYPTO_LIB_SHA256=y
CONFIG_CRYPTO_LIB_SHA256_ARCH=y
CONFIG_CRYPTO_LIB_SHA512=y
CONFIG_CRYPTO_LIB_SHA512_ARCH=y
CONFIG_CRYPTO_LIB_SHA3=y
CONFIG_XOR_BLOCKS=y
CONFIG_XOR_BLOCKS_ARCH=y
CONFIG_RAID6_PQ=y
CONFIG_RAID6_PQ_ARCH=y
# CONFIG_RAID6_PQ_BENCHMARK is not set
CONFIG_XXHASH=y
# CONFIG_RANDOM32_SELFTEST is not set
CONFIG_842_COMPRESS=y
CONFIG_842_DECOMPRESS=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_LZO_COMPRESS=y
CONFIG_LZO_DECOMPRESS=y
CONFIG_LZ4_COMPRESS=y
CONFIG_LZ4HC_COMPRESS=y
CONFIG_LZ4_DECOMPRESS=y
CONFIG_ZSTD_COMMON=y
CONFIG_ZSTD_COMPRESS=y
CONFIG_ZSTD_DECOMPRESS=y
CONFIG_XZ_DEC=y
CONFIG_XZ_DEC_X86=y
CONFIG_XZ_DEC_POWERPC=y
CONFIG_XZ_DEC_ARM=y
CONFIG_XZ_DEC_ARMTHUMB=y
CONFIG_XZ_DEC_ARM64=y
CONFIG_XZ_DEC_SPARC=y
CONFIG_XZ_DEC_RISCV=y
# CONFIG_XZ_DEC_MICROLZMA is not set
CONFIG_XZ_DEC_BCJ=y
# CONFIG_XZ_DEC_TEST is not set
CONFIG_DECOMPRESS_GZIP=y
CONFIG_DECOMPRESS_BZIP2=y
CONFIG_DECOMPRESS_LZMA=y
CONFIG_DECOMPRESS_XZ=y
CONFIG_DECOMPRESS_LZO=y
CONFIG_DECOMPRESS_LZ4=y
CONFIG_DECOMPRESS_ZSTD=y
CONFIG_GENERIC_ALLOCATOR=y
CONFIG_REED_SOLOMON=y
CONFIG_REED_SOLOMON_DEC8=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=y
CONFIG_TEXTSEARCH_BM=y
CONFIG_TEXTSEARCH_FSM=y
CONFIG_INTERVAL_TREE=y
CONFIG_INTERVAL_TREE_SPAN_ITER=y
CONFIG_XARRAY_MULTI=y
CONFIG_ASSOCIATIVE_ARRAY=y
CONFIG_CLOSURES=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_IOPORT_MAP=y
CONFIG_HAS_DMA=y
CONFIG_DMA_OPS_HELPERS=y
CONFIG_NEED_SG_DMA_FLAGS=y
CONFIG_NEED_SG_DMA_LENGTH=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_ARCH_DMA_ADDR_T_64BIT=y
CONFIG_DMA_DECLARE_COHERENT=y
CONFIG_SWIOTLB=y
# CONFIG_SWIOTLB_DYNAMIC is not set
CONFIG_DMA_NEED_SYNC=y
# CONFIG_DMA_RESTRICTED_POOL is not set
CONFIG_DMA_CMA=y
# CONFIG_DMA_NUMA_CMA is not set

#
# Default contiguous memory area size:
#
CONFIG_CMA_SIZE_MBYTES=0
CONFIG_CMA_SIZE_PERCENTAGE=0
# CONFIG_CMA_SIZE_SEL_MBYTES is not set
# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set
# CONFIG_CMA_SIZE_SEL_MIN is not set
CONFIG_CMA_SIZE_SEL_MAX=y
CONFIG_CMA_ALIGNMENT=8
# CONFIG_DMA_API_DEBUG is not set
# CONFIG_DMA_MAP_BENCHMARK is not set
CONFIG_SGL_ALLOC=y
CONFIG_CHECK_SIGNATURE=y
# CONFIG_CPUMASK_OFFSTACK is not set
CONFIG_CPU_RMAP=y
CONFIG_DQL=y
CONFIG_GLOB=y
CONFIG_NLATTR=y
CONFIG_CLZ_TAB=y
CONFIG_IRQ_POLL=y
CONFIG_MPILIB=y
CONFIG_SIGNATURE=y
CONFIG_DIMLIB=y
CONFIG_LIBFDT=y
CONFIG_OID_REGISTRY=y
CONFIG_HAVE_GENERIC_VDSO=y
CONFIG_GENERIC_GETTIMEOFDAY=y
CONFIG_GENERIC_VDSO_OVERFLOW_PROTECT=y
CONFIG_VDSO_GETRANDOM=y
CONFIG_FONT_SUPPORT=y
# CONFIG_FONTS is not set
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
CONFIG_SG_POOL=y
CONFIG_ARCH_HAS_PMEM_API=y
CONFIG_MEMREGION=y
CONFIG_ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION=y
CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE=y
CONFIG_ARCH_HAS_COPY_MC=y
CONFIG_ARCH_STACKWALK=y
CONFIG_STACKDEPOT=y
CONFIG_STACKDEPOT_ALWAYS_INIT=y
CONFIG_STACKDEPOT_MAX_FRAMES=64
CONFIG_REF_TRACKER=y
CONFIG_SBITMAP=y
# CONFIG_LWQ_TEST is not set
# end of Library routines

CONFIG_FIRMWARE_TABLE=y
CONFIG_UNION_FIND=y

#
# Kernel hacking
#

#
# printk and dmesg options
#
CONFIG_PRINTK_TIME=y
CONFIG_PRINTK_CALLER=y
# CONFIG_STACKTRACE_BUILD_ID is not set
CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7
CONFIG_CONSOLE_LOGLEVEL_QUIET=4
CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
# CONFIG_BOOT_PRINTK_DELAY is not set
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DYNAMIC_DEBUG_CORE=y
CONFIG_SYMBOLIC_ERRNAME=y
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_BUGVERBOSE_DETAILED=y
# end of printk and dmesg options

CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_MISC=y

#
# Compile-time checks and compiler options
#
CONFIG_DEBUG_INFO=y
CONFIG_AS_HAS_NON_CONST_ULEB128=y
# CONFIG_DEBUG_INFO_NONE is not set
# CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT is not set
CONFIG_DEBUG_INFO_DWARF4=y
# CONFIG_DEBUG_INFO_DWARF5 is not set
# CONFIG_DEBUG_INFO_REDUCED is not set
CONFIG_DEBUG_INFO_COMPRESSED_NONE=y
# CONFIG_DEBUG_INFO_COMPRESSED_ZLIB is not set
# CONFIG_DEBUG_INFO_COMPRESSED_ZSTD is not set
# CONFIG_DEBUG_INFO_SPLIT is not set
# CONFIG_DEBUG_INFO_BTF is not set
CONFIG_PAHOLE_HAS_BTF_TAG=y
CONFIG_PAHOLE_HAS_LANG_EXCLUDE=y
# CONFIG_GDB_SCRIPTS is not set
CONFIG_FRAME_WARN=2048
# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_HEADERS_INSTALL is not set
CONFIG_SECTION_MISMATCH_WARN_ONLY=y
# CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B is not set
CONFIG_OBJTOOL=y
# CONFIG_OBJTOOL_WERROR is not set
CONFIG_NOINSTR_VALIDATION=y
# CONFIG_VMLINUX_MAP is not set
# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
# end of Compile-time checks and compiler options

#
# Generic Kernel Debugging Instruments
#
# CONFIG_MAGIC_SYSRQ is not set
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_FS_ALLOW_ALL=y
# CONFIG_DEBUG_FS_ALLOW_NONE is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
CONFIG_ARCH_HAS_UBSAN=y
CONFIG_UBSAN=y
# CONFIG_UBSAN_TRAP is not set
CONFIG_CC_HAS_UBSAN_ARRAY_BOUNDS=y
CONFIG_UBSAN_BOUNDS=y
CONFIG_UBSAN_ARRAY_BOUNDS=y
CONFIG_UBSAN_SHIFT=y
# CONFIG_UBSAN_BOOL is not set
# CONFIG_UBSAN_ENUM is not set
# CONFIG_UBSAN_ALIGNMENT is not set
# CONFIG_TEST_UBSAN is not set
CONFIG_HAVE_ARCH_KCSAN=y
CONFIG_HAVE_KCSAN_COMPILER=y
# end of Generic Kernel Debugging Instruments

#
# Networking Debugging
#
CONFIG_NET_DEV_REFCNT_TRACKER=y
CONFIG_NET_NS_REFCNT_TRACKER=y
CONFIG_DEBUG_NET=y
# CONFIG_DEBUG_NET_SMALL_RTNL is not set
# end of Networking Debugging

#
# Memory Debugging
#
CONFIG_PAGE_EXTENSION=y
# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_SLUB_DEBUG=y
# CONFIG_SLUB_DEBUG_ON is not set
CONFIG_SLUB_RCU_DEBUG=y
CONFIG_PAGE_OWNER=y
CONFIG_PAGE_TABLE_CHECK=y
CONFIG_PAGE_TABLE_CHECK_ENFORCED=y
CONFIG_PAGE_POISONING=y
# CONFIG_DEBUG_PAGE_REF is not set
# CONFIG_DEBUG_RODATA_TEST is not set
CONFIG_ARCH_HAS_DEBUG_WX=y
CONFIG_DEBUG_WX=y
CONFIG_ARCH_HAS_PTDUMP=y
CONFIG_PTDUMP=y
CONFIG_PTDUMP_DEBUGFS=y
CONFIG_HAVE_DEBUG_KMEMLEAK=y
# CONFIG_DEBUG_KMEMLEAK is not set
# CONFIG_PER_VMA_LOCK_STATS is not set
CONFIG_DEBUG_OBJECTS=y
# CONFIG_DEBUG_OBJECTS_SELFTEST is not set
CONFIG_DEBUG_OBJECTS_FREE=y
CONFIG_DEBUG_OBJECTS_TIMERS=y
CONFIG_DEBUG_OBJECTS_WORK=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1
# CONFIG_SHRINKER_DEBUG is not set
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_SCHED_STACK_END_CHECK=y
CONFIG_ARCH_HAS_DEBUG_VM_PGTABLE=y
CONFIG_DEBUG_VFS=y
CONFIG_DEBUG_VM=y
CONFIG_DEBUG_VM_MAPLE_TREE=y
CONFIG_DEBUG_VM_RB=y
CONFIG_DEBUG_VM_PGFLAGS=y
CONFIG_DEBUG_VM_PGTABLE=y
CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
CONFIG_DEBUG_VIRTUAL=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_DEBUG_PER_CPU_MAPS=y
CONFIG_DEBUG_KMAP_LOCAL=y
CONFIG_ARCH_SUPPORTS_KMAP_LOCAL_FORCE_MAP=y
CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP=y
# CONFIG_MEM_ALLOC_PROFILING is not set
CONFIG_HAVE_ARCH_KASAN=y
CONFIG_HAVE_ARCH_KASAN_VMALLOC=y
CONFIG_CC_HAS_KASAN_GENERIC=y
CONFIG_CC_HAS_KASAN_SW_TAGS=y
CONFIG_CC_HAS_WORKING_NOSANITIZE_ADDRESS=y
CONFIG_KASAN=y
CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX=y
CONFIG_KASAN_GENERIC=y
# CONFIG_KASAN_OUTLINE is not set
CONFIG_KASAN_INLINE=y
CONFIG_KASAN_STACK=y
CONFIG_KASAN_VMALLOC=y
# CONFIG_KASAN_EXTRA_INFO is not set
CONFIG_HAVE_ARCH_KFENCE=y
CONFIG_KFENCE=y
CONFIG_KFENCE_SAMPLE_INTERVAL=100
CONFIG_KFENCE_NUM_OBJECTS=255
# CONFIG_KFENCE_DEFERRABLE is not set
CONFIG_KFENCE_STATIC_KEYS=y
CONFIG_KFENCE_STRESS_TEST_FAULTS=0
CONFIG_HAVE_ARCH_KMSAN=y
CONFIG_HAVE_KMSAN_COMPILER=y
# end of Memory Debugging

# CONFIG_DEBUG_SHIRQ is not set

#
# Debug Oops, Lockups and Hangs
#
CONFIG_PANIC_ON_OOPS=y
CONFIG_PANIC_TIMEOUT=86400
CONFIG_LOCKUP_DETECTOR=y
CONFIG_SOFTLOCKUP_DETECTOR=y
# CONFIG_SOFTLOCKUP_DETECTOR_INTR_STORM is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=1
CONFIG_HAVE_HARDLOCKUP_DETECTOR_BUDDY=y
CONFIG_HARDLOCKUP_DETECTOR=y
# CONFIG_HARDLOCKUP_DETECTOR_PREFER_BUDDY is not set
CONFIG_HARDLOCKUP_DETECTOR_PERF=y
# CONFIG_HARDLOCKUP_DETECTOR_BUDDY is not set
# CONFIG_HARDLOCKUP_DETECTOR_ARCH is not set
CONFIG_HARDLOCKUP_DETECTOR_COUNTS_HRTIMER=y
CONFIG_HARDLOCKUP_CHECK_TIMESTAMP=y
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=140
CONFIG_BOOTPARAM_HUNG_TASK_PANIC=1
CONFIG_WQ_WATCHDOG=y
CONFIG_BOOTPARAM_WQ_STALL_PANIC=0
# CONFIG_WQ_CPU_INTENSIVE_REPORT is not set
# CONFIG_TEST_LOCKUP is not set
# end of Debug Oops, Lockups and Hangs

#
# Scheduler Debugging
#
CONFIG_SCHED_INFO=y
CONFIG_SCHEDSTATS=y
# end of Scheduler Debugging

CONFIG_DEBUG_PREEMPT=y
# CONFIG_DEBUG_ATOMIC is not set

#
# Lock Debugging (spinlocks, mutexes, etc...)
#
CONFIG_LOCK_DEBUGGING_SUPPORT=y
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RAW_LOCK_NESTING=y
# CONFIG_LOCK_STAT is not set
CONFIG_DEBUG_RT_MUTEXES=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_LOCKDEP=y
CONFIG_LOCKDEP_BITS=20
CONFIG_LOCKDEP_CHAINS_BITS=20
CONFIG_LOCKDEP_STACK_TRACE_BITS=20
CONFIG_LOCKDEP_STACK_TRACE_HASH_BITS=14
CONFIG_LOCKDEP_CIRCULAR_QUEUE_BITS=12
# CONFIG_DEBUG_LOCKDEP is not set
CONFIG_DEBUG_ATOMIC_SLEEP=y
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_LOCK_TORTURE_TEST is not set
# CONFIG_WW_MUTEX_SELFTEST is not set
# CONFIG_SCF_TORTURE_TEST is not set
CONFIG_CSD_LOCK_WAIT_DEBUG=y
# CONFIG_CSD_LOCK_WAIT_DEBUG_DEFAULT is not set
# end of Lock Debugging (spinlocks, mutexes, etc...)

CONFIG_TRACE_IRQFLAGS=y
CONFIG_TRACE_IRQFLAGS_NMI=y
CONFIG_NMI_CHECK_CPU=y
CONFIG_DEBUG_IRQFLAGS=y
CONFIG_STACKTRACE=y
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_KOBJECT_RELEASE is not set

#
# Debug kernel data structures
#
CONFIG_DEBUG_LIST=y
CONFIG_DEBUG_PLIST=y
CONFIG_DEBUG_SG=y
CONFIG_DEBUG_NOTIFIERS=y
# CONFIG_DEBUG_CLOSURES is not set
CONFIG_DEBUG_MAPLE_TREE=y
# end of Debug kernel data structures

#
# RCU Debugging
#
CONFIG_PROVE_RCU=y
# CONFIG_RCU_SCALE_TEST is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_REF_SCALE_TEST is not set
CONFIG_RCU_CPU_STALL_TIMEOUT=100
CONFIG_RCU_EXP_CPU_STALL_TIMEOUT=0
# CONFIG_RCU_CPU_STALL_CPUTIME is not set
# CONFIG_RCU_TRACE is not set
CONFIG_RCU_EQS_DEBUG=y
# end of RCU Debugging

# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set
# CONFIG_LATENCYTOP is not set
CONFIG_USER_STACKTRACE_SUPPORT=y
CONFIG_NOP_TRACER=y
CONFIG_HAVE_RETHOOK=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS=y
CONFIG_HAVE_FTRACE_REGS_HAVING_PT_REGS=y
CONFIG_HAVE_DYNAMIC_FTRACE_NO_PATCHABLE=y
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_JMP=y
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
CONFIG_HAVE_FENTRY=y
CONFIG_HAVE_OBJTOOL_MCOUNT=y
CONFIG_HAVE_OBJTOOL_NOP_MCOUNT=y
CONFIG_HAVE_C_RECORDMCOUNT=y
CONFIG_HAVE_BUILDTIME_MCOUNT_SORT=y
CONFIG_TRACE_CLOCK=y
CONFIG_RING_BUFFER=y
CONFIG_EVENT_TRACING=y
CONFIG_CONTEXT_SWITCH_TRACER=y
CONFIG_PREEMPTIRQ_TRACEPOINTS=y
CONFIG_TRACING=y
CONFIG_GENERIC_TRACER=y
CONFIG_TRACING_SUPPORT=y
CONFIG_FTRACE=y
CONFIG_TRACEFS_AUTOMOUNT_DEPRECATED=y
# CONFIG_BOOTTIME_TRACING is not set
# CONFIG_FUNCTION_TRACER is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_HWLAT_TRACER is not set
# CONFIG_OSNOISE_TRACER is not set
# CONFIG_TIMERLAT_TRACER is not set
# CONFIG_MMIOTRACE is not set
# CONFIG_FTRACE_SYSCALLS is not set
# CONFIG_TRACER_SNAPSHOT is not set
CONFIG_BRANCH_PROFILE_NONE=y
# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_UPROBE_EVENTS=y
CONFIG_EPROBE_EVENTS=y
CONFIG_BPF_EVENTS=y
CONFIG_DYNAMIC_EVENTS=y
CONFIG_PROBE_EVENTS=y
# CONFIG_SYNTH_EVENTS is not set
# CONFIG_USER_EVENTS is not set
# CONFIG_HIST_TRIGGERS is not set
CONFIG_TRACE_EVENT_INJECT=y
# CONFIG_TRACEPOINT_BENCHMARK is not set
# CONFIG_RING_BUFFER_BENCHMARK is not set
# CONFIG_TRACE_EVAL_MAP_FILE is not set
# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_RING_BUFFER_STARTUP_TEST is not set
CONFIG_RING_BUFFER_VALIDATE_TIME_DELTAS=y
# CONFIG_RING_BUFFER_PERSISTENT_INJECT is not set
# CONFIG_PREEMPTIRQ_DELAY_TEST is not set
# CONFIG_RV is not set
# CONFIG_TRACE_REMOTE_TEST is not set
CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
# CONFIG_SAMPLES is not set
CONFIG_HAVE_SAMPLE_FTRACE_DIRECT=y
CONFIG_HAVE_SAMPLE_FTRACE_DIRECT_MULTI=y
CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
# CONFIG_STRICT_DEVMEM is not set

#
# x86 Debugging
#
CONFIG_EARLY_PRINTK_USB=y
CONFIG_X86_VERBOSE_BOOTUP=y
CONFIG_EARLY_PRINTK=y
CONFIG_EARLY_PRINTK_DBGP=y
# CONFIG_EARLY_PRINTK_USB_XDBC is not set
# CONFIG_DEBUG_TLBFLUSH is not set
CONFIG_HAVE_MMIOTRACE_SUPPORT=y
# CONFIG_X86_DECODER_SELFTEST is not set
CONFIG_IO_DELAY_0X80=y
# CONFIG_IO_DELAY_0XED is not set
# CONFIG_IO_DELAY_UDELAY is not set
# CONFIG_IO_DELAY_NONE is not set
CONFIG_DEBUG_BOOT_PARAMS=y
# CONFIG_CPA_DEBUG is not set
CONFIG_DEBUG_ENTRY=y
# CONFIG_DEBUG_NMI_SELFTEST is not set
CONFIG_X86_DEBUG_FPU=y
# CONFIG_PUNIT_ATOM_DEBUG is not set
CONFIG_UNWINDER_ORC=y
# CONFIG_UNWINDER_FRAME_POINTER is not set
# end of x86 Debugging

#
# Kernel Testing and Coverage
#
# CONFIG_KUNIT is not set
# CONFIG_NOTIFIER_ERROR_INJECTION is not set
CONFIG_FAULT_INJECTION=y
CONFIG_FAILSLAB=y
CONFIG_FAIL_PAGE_ALLOC=y
CONFIG_FAULT_INJECTION_USERCOPY=y
CONFIG_FAIL_MAKE_REQUEST=y
CONFIG_FAIL_IO_TIMEOUT=y
CONFIG_FAIL_FUTEX=y
CONFIG_FAULT_INJECTION_DEBUG_FS=y
# CONFIG_FAIL_MMC_REQUEST is not set
# CONFIG_FAIL_SKB_REALLOC is not set
CONFIG_FAULT_INJECTION_CONFIGFS=y
# CONFIG_FAULT_INJECTION_STACKTRACE_FILTER is not set
CONFIG_ARCH_HAS_KCOV=y
CONFIG_KCOV=y
CONFIG_KCOV_ENABLE_COMPARISONS=y
CONFIG_KCOV_INSTRUMENT_ALL=y
CONFIG_KCOV_IRQ_AREA_SIZE=0x40000
# CONFIG_KCOV_SELFTEST is not set
CONFIG_RUNTIME_TESTING_MENU=y
# CONFIG_TEST_DHRY is not set
# CONFIG_LKDTM is not set
# CONFIG_TEST_DIV64 is not set
# CONFIG_TEST_MULDIV64 is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
# CONFIG_TEST_REF_TRACKER is not set
# CONFIG_RBTREE_TEST is not set
# CONFIG_REED_SOLOMON_TEST is not set
# CONFIG_INTERVAL_TREE_TEST is not set
# CONFIG_PERCPU_TEST is not set
# CONFIG_ATOMIC64_SELFTEST is not set
# CONFIG_ASYNC_RAID6_TEST is not set
# CONFIG_TEST_HEXDUMP is not set
# CONFIG_TEST_KSTRTOX is not set
# CONFIG_TEST_BITMAP is not set
# CONFIG_TEST_XARRAY is not set
# CONFIG_TEST_MAPLE_TREE is not set
# CONFIG_TEST_RHASHTABLE is not set
# CONFIG_TEST_IDA is not set
# CONFIG_TEST_LKM is not set
# CONFIG_TEST_BITOPS is not set
# CONFIG_TEST_VMALLOC is not set
# CONFIG_TEST_WORKQUEUE is not set
# CONFIG_TEST_BPF is not set
# CONFIG_FIND_BIT_BENCHMARK is not set
# CONFIG_TEST_FIRMWARE is not set
# CONFIG_TEST_SYSCTL is not set
# CONFIG_CONTEXT_ANALYSIS_TEST is not set
# CONFIG_TEST_UDELAY is not set
# CONFIG_TEST_STATIC_KEYS is not set
# CONFIG_TEST_DYNAMIC_DEBUG is not set
# CONFIG_TEST_KMOD is not set
# CONFIG_TEST_KALLSYMS is not set
# CONFIG_TEST_DEBUG_VIRTUAL is not set
# CONFIG_TEST_MEMCAT_P is not set
# CONFIG_TEST_MEMINIT is not set
# CONFIG_TEST_FREE_PAGES is not set
# CONFIG_TEST_CLOCKSOURCE_WATCHDOG is not set
# CONFIG_TEST_OBJPOOL is not set
CONFIG_ARCH_USE_MEMTEST=y
# CONFIG_MEMTEST is not set
# end of Kernel Testing and Coverage

#
# Rust hacking
#
# end of Rust hacking
# end of Kernel hacking

CONFIG_IO_URING_BPF=y
KernelRepo git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
ReproCID 0
ReproOpts
ReproSyzID 0
SyzkallerCommit cb1587ea08e5a1a12acb4372efe923e2308effdb
TargetArch amd64
TargetOS linux

Error:
log-in to see details

Outputs:

Crash report:
==================================================================
BUG: KASAN: slab-use-after-free in i2c_adapter_depth drivers/i2c/i2c-core-base.c:1243 [inline]
BUG: KASAN: slab-use-after-free in i2c_adapter_lock_bus+0x5e/0xf0 drivers/i2c/i2c-core-base.c:849
Read of size 8 at addr ffff8880270b4108 by task syz.4.7872/28255

CPU: 0 UID: 0 PID: 28255 Comm: syz.4.7872 Tainted: G             L      syzkaller #0 PREEMPT_{RT,(full)} 
Tainted: [L]=SOFTLOCKUP
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/16/2026
Call Trace:
 <TASK>
 dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
 print_address_description+0x55/0x1e0 mm/kasan/report.c:378
 print_address_description+0x55/0x1e0 mm/kasan/report.c:378
 print_report+0x58/0x70 mm/kasan/report.c:482
 kasan_report+0x117/0x150 mm/kasan/report.c:595
 i2c_adapter_depth drivers/i2c/i2c-core-base.c:1243 [inline]
 i2c_adapter_lock_bus+0x5e/0xf0 drivers/i2c/i2c-core-base.c:849
 i2c_lock_bus include/linux/i2c.h:809 [inline]
 __i2c_lock_bus_helper drivers/i2c/i2c-core.h:47 [inline]
 i2c_smbus_xfer+0xd5/0x310 drivers/i2c/i2c-core-smbus.c:543
 i2cdev_ioctl_smbus+0x407/0x700 drivers/i2c/i2c-dev.c:389
 i2cdev_ioctl+0x618/0x890 drivers/i2c/i2c-dev.c:478
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:597 [inline]
 __se_sys_ioctl+0xff/0x170 fs/ioctl.c:583
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0x174/0x580 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f0b2cb8de99
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f0b2ade6028 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00007f0b2ce15fa0 RCX: 00007f0b2cb8de99
RDX: 0000200000000080 RSI: 0000000000000720 RDI: 0000000000000003
RBP: 00007f0b2cc23eaf R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f0b2ce16038 R14: 00007f0b2ce15fa0 R15: 00007ffe659b19a8
 </TASK>

Allocated by task 1326:
 kasan_save_stack mm/kasan/common.c:57 [inline]
 kasan_save_track+0x3e/0x80 mm/kasan/common.c:78
 poison_kmalloc_redzone mm/kasan/common.c:398 [inline]
 __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:415
 kasan_kmalloc include/linux/kasan.h:263 [inline]
 __do_kmalloc_node mm/slub.c:5334 [inline]
 __kmalloc_node_track_caller_noprof+0x57f/0x7c0 mm/slub.c:5471
 kmalloc_reserve net/core/skbuff.c:637 [inline]
 __alloc_skb+0x2bd/0x7a0 net/core/skbuff.c:715
 alloc_skb include/linux/skbuff.h:1384 [inline]
 nsim_dev_trap_skb_build drivers/net/netdevsim/dev.c:819 [inline]
 nsim_dev_trap_report drivers/net/netdevsim/dev.c:876 [inline]
 nsim_dev_trap_report_work+0x2b1/0xcb0 drivers/net/netdevsim/dev.c:922
 process_one_work kernel/workqueue.c:3322 [inline]
 process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
 worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486
 kthread+0x388/0x470 kernel/kthread.c:436
 ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

Freed by task 1326:
 kasan_save_stack mm/kasan/common.c:57 [inline]
 kasan_save_track+0x3e/0x80 mm/kasan/common.c:78
 kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:584
 poison_slab_object mm/kasan/common.c:253 [inline]
 __kasan_slab_free+0x5c/0x80 mm/kasan/common.c:285
 kasan_slab_free include/linux/kasan.h:235 [inline]
 slab_free_hook mm/slub.c:2677 [inline]
 slab_free mm/slub.c:6377 [inline]
 kfree+0x1c5/0x6c0 mm/slub.c:6692
 skb_kfree_head net/core/skbuff.c:1077 [inline]
 skb_free_head net/core/skbuff.c:1089 [inline]
 skb_release_data+0x85e/0xab0 net/core/skbuff.c:1116
 skb_release_all net/core/skbuff.c:1191 [inline]
 __kfree_skb+0x5d/0x210 net/core/skbuff.c:1205
 nsim_dev_trap_report drivers/net/netdevsim/dev.c:892 [inline]
 nsim_dev_trap_report_work+0x879/0xcb0 drivers/net/netdevsim/dev.c:922
 process_one_work kernel/workqueue.c:3322 [inline]
 process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
 worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486
 kthread+0x388/0x470 kernel/kthread.c:436
 ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

The buggy address belongs to the object at ffff8880270b4000
 which belongs to the cache kmalloc-4k of size 4096
The buggy address is located 264 bytes inside of
 freed 4096-byte region [ffff8880270b4000, ffff8880270b5000)

The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x270b0
head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
flags: 0x80000000000040(head|node=0|zone=1)
page_type: f5(slab)
raw: 0080000000000040 ffff88813ffb2140 dead000000000100 dead000000000122
raw: 0000000000000000 0000000800040004 00000000f5000000 0000000000000000
head: 0080000000000040 ffff88813ffb2140 dead000000000100 dead000000000122
head: 0000000000000000 0000000800040004 00000000f5000000 0000000000000000
head: 0080000000000003 fffffffffffffe01 00000000ffffffff 00000000ffffffff
head: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000008
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 3, migratetype Unmovable, gfp_mask 0xd20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 1, tgid 1 (swapper/0), ts 13082770889, free_ts 13069657874
 set_page_owner include/linux/page_owner.h:32 [inline]
 post_alloc_hook+0x1f9/0x250 mm/page_alloc.c:1859
 prep_new_page mm/page_alloc.c:1867 [inline]
 get_page_from_freelist+0x262a/0x26a0 mm/page_alloc.c:3946
 __alloc_frozen_pages_noprof+0x18d/0x380 mm/page_alloc.c:5304
 alloc_slab_page mm/slub.c:3266 [inline]
 allocate_slab+0x79/0x5e0 mm/slub.c:3380
 new_slab mm/slub.c:3426 [inline]
 refill_objects+0x2d8/0x350 mm/slub.c:7310
 refill_sheaf mm/slub.c:2804 [inline]
 __pcs_replace_empty_main+0x330/0x690 mm/slub.c:4675
 alloc_from_pcs mm/slub.c:4773 [inline]
 slab_alloc_node mm/slub.c:4905 [inline]
 __kmalloc_cache_noprof+0x468/0x6b0 mm/slub.c:5485
 _kmalloc_noprof include/linux/slab.h:988 [inline]
 _kzalloc_noprof include/linux/slab.h:1309 [inline]
 kobject_uevent_env+0x28c/0x9e0 lib/kobject_uevent.c:543
 device_add+0x544/0xb80 drivers/base/core.c:3738
 device_create_groups_vargs drivers/base/core.c:4454 [inline]
 device_create+0x269/0x300 drivers/base/core.c:4493
 mon_bin_add+0xb6/0x130 drivers/usb/mon/mon_bin.c:1371
 mon_bus_init+0x173/0x2b0 drivers/usb/mon/mon_main.c:291
 mon_bus_add drivers/usb/mon/mon_main.c:188 [inline]
 mon_notify+0x10c/0x3f0 drivers/usb/mon/mon_main.c:219
 notifier_call_chain+0x1a5/0x3d0 kernel/notifier.c:85
 blocking_notifier_call_chain+0x6a/0x90 kernel/notifier.c:380
 usb_register_bus+0xcf/0x150 drivers/usb/core/hcd.c:904
page last free pid 10 tgid 10 stack trace:
 reset_page_owner include/linux/page_owner.h:25 [inline]
 __free_pages_prepare mm/page_alloc.c:1406 [inline]
 free_pages_prepare+0x946/0xa40 mm/page_alloc.c:1451
 __free_contig_range_common+0x174/0x340 mm/page_alloc.c:6897
 __free_contig_range mm/page_alloc.c:6942 [inline]
 free_pages_bulk+0x48/0x120 mm/page_alloc.c:5257
 vm_area_free_pages mm/vmalloc.c:3439 [inline]
 vfree+0x26f/0x510 mm/vmalloc.c:3488
 delayed_vfree_work+0x55/0x80 mm/vmalloc.c:3392
 process_one_work kernel/workqueue.c:3322 [inline]
 process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
 worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486
 kthread+0x388/0x470 kernel/kthread.c:436
 ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

Memory state around the buggy address:
 ffff8880270b4000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff8880270b4080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff8880270b4100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                      ^
 ffff8880270b4180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff8880270b4200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================

Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/07/30 11:51 flow repro
1h44m Error:
log-in to see details

1/1 2026/07/30 11:51 action kernel-checkouter
0m Results:
map[KernelSrc:/app/workdir/cache/src/a43694d4bed4bc357b0c64e52341ff394417331e]

2/1 2026/07/30 11:51 action kernel-builder
15m Results:
map[KernelObj:/app/workdir/cache/build/787006d70b5d139dff241ae139a6dba39841260e]

3/1 2026/07/30 12:07 action codesearch-prepare
10m Results:
map[Index:codesearch-index]

4/1 2026/07/30 12:17 agent crash-repro-finder
1h18m Model:
best-expensive

Error:
log-in to see details

Instruction:
You are an expert in Linux kernel fuzzing. Your goal is to write a syzkaller program to trigger a specific bug.

Execution sandboxes ('Sandbox' output field):
- "none": Runs test processes as root without Linux namespace isolation (PID, Net, IPC, User).
- "setuid": Runs test processes under unprivileged user accounts (drops root privileges and capabilities).
- "namespace": Runs test processes inside isolated Linux namespaces
  (CLONE_NEWNS, CLONE_NEWUTS, CLONE_NEWIPC, CLONE_NEWPID, CLONE_NEWNET,
  CLONE_NEWUSER) with isolated network devices (loopback, tun, etc.).
  Use this for network, IPC, or namespace bugs.
- "android": Simulates Android application privilege and SELinux restrictions (drops privileges to Android UIDs/GIDs).

Document about syzkaller program syntax:
===
# Program syntax

Syzkaller uses a compact domain-specific language (DSL) for programs
to log executed programs, test its code, and persist programs in the
corpus. This page provides a brief description of the corresponding
syntax. Some useful information can also be found in the
[existing examples](/sys/linux/test) and in the program
[deserialization code](/prog/encoding.go).

Together with execution options, the DSL provides everything that
syz-executor needs to run a program.

For example, consider the program:
```
r0 = syz_open_dev$loop(&(0x7f00000011c0), 0x0, 0x0)
r1 = openat$6lowpan_control(0xffffffffffffff9c, &(0x7f00000000c0), 0x2, 0x0)
ioctl$LOOP_SET_FD(r0, 0x4c00, r1)
```

Each line in this program describes a particular syscall invocation,
with the first two calls saving the result in temporary variables `r0`
and `r1`, which are passed to the third call.

```
line = assignment | call
assignment = variable " = " call
call = syscall-name "(" [arg ["," arg]*] ")"  ["(" [call-prop ["," call-prop*] ")"]
arg = "nil" | "AUTO" | const-arg | resource-arg | result-arg | pointer-arg | string-arg | struct-arg | array-arg | union-arg
const-arg = integer
resource-arg = variable ["/" hex-integer] ["+" hex-integer]
result-arg = "<" variable "=>" arg
pointer-arg = "&" pointer-arg-addr ["=ANY"] "=" arg
pointer-arg-addr = "AUTO" | "(" pointer-addr ["/" region-size] ")"
string-arg = "'" escaped-string "'" | "\"" escaped-string "\"" | "\"$" escaped-string "\""
struct-arg =  "{" [arg ["," arg]*] "}"
array-arg = "[" [arg ["," arg]*] "]"
union-arg = "@" field-name ["=" arg]
call-prop = prop-name ": " prop-value
variable = "r" dec-integer
pointer-addr = integer
region-size = integer
integer = dec-integer | oct-integer | "0x" hex-integer
```

Programs may also contain blank lines and comments.
```
# Obtain a file handle
r0 = openat(0xffffffffffffff9c, &AUTO='./file1\x00', 0x42, 0x1ff)

# Perform a write operation
write(r0, &AUTO="01010101", 0x4)
```

### Memory management

Memory management is performed by syzkaller itself. It will allocate
virtual memory regions of the necessary size and set the final values
of pointer arguments.

By using the `AUTO` keyword, programs can give syzkaller the full
control over storing the data. This may be convenient e.g. when a
parameter must be passed by reference, but the exact location of its
value is not of particular importance.

```
r1 = syz_genetlink_get_family_id$nl80211(&AUTO='nl80211\x00', 0xffffffffffffffff)
ioctl$sock_SIOCGIFINDEX_80211(r0, 0x8933, &AUTO={'wlan0\x00', <r2=>0x0})
```

Alternatively, some data can be "anchored" to specific addresses. It
may be especially important when a memory region must be shared
between multiple calls.  In this case, pointer addresses must be given
at the 0x7f0000000000 offset. Before the actual execution, syzkaller
will adjust pointers to the start of the actual mmap'ed region.

### Call properties

Call properties specify extra information about how a specific call
must be executed. Each call within a program has its own set of call
properties. If no properties are provided, syzkaller takes the default
ones.

Currently, syzkaller supports the following call properties.

#### Fault injection
Syntax: `fail_nth: N`.

It takes an integer (base 10) argument `N`. If the argument is
non-negative, a fault will be injected into the `N`-th occasion.

```
r0 = openat$6lowpan_control(0xffffffffffffff9c, &(0x7f00000000c0), 0x2, 0x0)
ioctl$LOOP_SET_FD(r0, 0x4c00, r0) (fail_nth: 5)
```

#### Async
Syntax: `async`.

Instructs `syz-executor` not to wait until the call completes and
to proceed immediately to the next call.

```
r0 = openat(0xffffffffffffff9c, &AUTO='./file1\x00', 0x42, 0x1ff)
write(r0, &AUTO="01010101", 0x4) (async)
read(r0, &AUTO=""/4, 0x4)
close(r0)
```

When setting `async` flags be aware of the following considerations:
* Such programs should only be executed in threaded mode (i.e. `-threaded`
flag must be passed to `syz-executor`.
* Each `async` call is executed in a separate thread and there's a
limited number of available threads (`kMaxThreads = 16`).
* If an `async` call produces a resource, keep in mind that some other call
might take it as input and `syz-executor` will just pass 0 if the resource-
producing call has not finished by that time.

===

Document about syzlang system call descriptions syntax:
===
# Syscall description language

aka `syzlang` (`[siːzˈlΓ¦Ε‹g]`)

Pseudo-formal grammar of syscall description:

```
syscallname "(" [arg ["," arg]*] ")" [type] ["(" attribute* ")"]
arg = argname type
argname = identifier
type = typename [ "[" type-options "]" ]
typename = "const" | "intN" | "intptr" | "flags" | "array" | "ptr" |
	   "string" | "filename" | "glob" | "len" |
	   "bytesize" | "bytesizeN" | "bitsize" | "vma" | "proc" |
	   "compressed_image"
type-options = [type-opt ["," type-opt]]
```

common type-options include:

```
"opt" - the argument is optional (like mmap fd argument, or accept peer argument)
```

rest of the type-options are type-specific:

```
"const": integer constant, type-options:
	value, underlying type (one of "intN", "intptr")
"intN"/"intptr": an integer without a particular meaning, type-options:
	either an optional range of values (e.g. "5:10", or "100:200")
	or a reference to flags description (see below),
	or a single value
	optionally followed by an alignment parameter if using a range
"flags": a set of values, type-options:
	reference to flags description (see below), underlying int type (e.g. "int32")
"array": a variable/fixed-length array, type-options:
	type of elements, optional size (fixed "5", or ranged "5:10", boundaries inclusive)
"ptr"/"ptr64": a pointer to an object, type-options:
	direction (in/out/inout); type of the object
	ptr64 has size of 8 bytes regardless of target pointer size
"string": a zero-terminated memory buffer (no pointer indirection implied), type-options:
	either a string value in quotes for constant strings (e.g. "foo" or `deadbeef` for hex literal),
	or a reference to string flags (special value `filename` produces file names),
	optionally followed by a buffer size (string values will be padded with \x00 to that size)
"stringnoz": a non-zero-terminated memory buffer (no pointer indirection implied), type-options:
	either a string value in quotes for constant strings (e.g. "foo" or `deadbeef` for hex literal),
	or a reference to string flags,
"glob": glob pattern to match on the target files, type-options:
	a pattern string in quotes (syntax: https://golang.org/pkg/path/filepath/#Match)
	(e.g. "/sys/" or "/sys/**/*"),
	or include exclude glob too (e.g. "/sys/**/*:-/sys/power/state")
"fmt": a string representation of an integer (not zero-terminated), type-options:
	format (one of "dec", "hex", "oct") and the value (a resource, int, flags or proc)
	the resulting data is always fixed-size (formatted as "%020llu", "0x%016llx" or "%023llo", respectively)
"len": length of another field (for array it is number of elements), type-options:
	argname of the object
"bytesize": similar to "len", but always denotes the size in bytes, type-options:
	argname of the object
"bitsize": similar to "len", but always denotes the size in bits, type-options:
	argname of the object
"offsetof": offset of the field from the beginning of the parent struct, type-options:
	field
"vma"/"vma64": a pointer to a set of pages (used as input for mmap/munmap/mremap/madvise), type-options:
	optional number of pages (e.g. vma[7]), or a range of pages (e.g. vma[2-4])
	vma64 has size of 8 bytes regardless of target pointer size
"proc": per process int (see description below), type-options:
	value range start, how many values per process, underlying type
"compressed_image": zlib-compressed disk image
	syscalls accepting compressed images must be marked with `no_generate`
	and `no_minimize` call attributes. if the content of the decompressed image
	can be checked by a `fsck`-like command, use the `fsck` syscall attribute
"text": machine code of the specified type, type-options:
	text type (x86_real, x86_16, x86_32, x86_64, arm64)
"void": type with static size 0
	mostly useful inside of templates and varlen unions, can't be syscall argument
```

flags/len/flags also have trailing underlying type type-option when used in structs/unions/pointers.

Flags are described as:

```
flagname = const ["," const]*
```

or for string flags as:

```
flagname = "\"" literal "\"" ["," "\"" literal "\""]*
```

Call attributes are:

```
"disabled": the call will not be used in fuzzing; useful to temporary disable some calls
	or prohibit particular argument combinations.
"timeout[N]": additional execution timeout (in ms) for the call on top of some default value.
"prog_timeout[N]": additional execution timeout (in ms) for the whole program if it contains this call;
	if a program contains several such calls, the max value is used.
"ignore_return": ignore return value of this syscall in fallback feedback; need to be used for calls
	that don't return fixed error codes but rather something else (e.g. the current time).
"breaks_returns": ignore return values of all subsequent calls in the program in fallback feedback (can't be trusted).
"no_generate": do not try to generate this syscall, i.e. use only seed descriptions to produce it.
"no_minimize": do not modify instances of this syscall when trying to minimize a crashing program.
"no_squash": do not attempt to pass squashed arguments to this syscall.
	Without that, the fuzzer will sometimes attempt to replace complex structures with arrays of bytes,
	possibly triggering interesting mutations, but also making programs hard to reason about.
"fsck": the content of the compressed buffer argument for this syscall is a file system and the
	string argument is a fsck-like command that will be called to verify the filesystem.
"remote_cover": wait longer to collect remote coverage for this call.
"kfuzz_test": the call is a kfuzztest target.
"snapshot": the call is enabled by default only in snapshot fuzzing mode, but can also be enabled in
    the non-snasphot mode when listed in "enable_syscalls" with its full name (as opposed to a wildcard match).
    It can also always be disabled via "disable_syscalls".
    The attribute is generally used to mark calls that are not safe to execute in non-snapshot mode
	(can lead to false positives, or lost connections to test machines.
```

## Ints

`int8`, `int16`, `int32` and `int64` denote an integer of the corresponding size.
`intptr` denotes a pointer-sized integer, i.e. C `long` type.

By appending `be` suffix (e.g. `int16be`) integers become big-endian.

It's possible to specify a range of values for an integer in the format of `int32[0:100]` or `int32[0:4096, 512]` for a 512-aligned int.

Integers can also take a reference to flags description or a value as its first type-option.
In that case, the alignment parameter is not supported.

To denote a bitfield of size N use `int64:N`.

It's possible to use these various kinds of ints as base types for `const`, `flags`, `len` and `proc`.

```
example_struct {
	f0	int8			# random 1-byte integer
	f1	const[0x42, int16be]	# const 2-byte integer with value 0x4200 (big-endian 0x42)
	f2	int32[0:100]		# random 4-byte integer with values from 0 to 100 inclusive
	f3	int32[1:10, 2]		# random 4-byte integer with values {1, 3, 5, 7, 9}
	f4	int64:20		# random 20-bit bitfield
	f5	int8[10]		# const 1-byte integer with value 10
	f6	int32[flagname]		# random 4-byte integer from the set of values referenced by flagname
}
```

## Structs

Structs are described as:

```
structname "{" "\n"
	(fieldname type ("(" fieldattribute* ")")? (if[expression])? "\n")+
"}" ("[" attribute* "]")?
```

Fields can have attributes specified in parentheses after the field, independent
of their type. `in/out/inout` attribute specify per-field direction, for example:

```
foo {
	field0	const[1, int32]	(in)
	field1	int32		(inout)
	field2	fd		(out)
}
```

You may specify conditions that determine whether a field will be included:

```
foo {
	field0	int32
	field1	int32 (if[value[field0] == 0x1])
}
```

See [the corresponding section](syscall_descriptions_syntax.md#conditional-fields)
for more details.

`out_overlay` attribute allows to have separate input and output layouts for the struct.
Fields before the `out_overlay` field are input, fields starting from `out_overlay` are output.
Input and output fields overlap in memory (both start from the beginning of the struct in memory).
For example:

```
foo {
	in0	const[1, int32]
	in1	flags[bar, int8]
	in2	ptr[in, string]
	out0	fd	(out_overlay)
	out1	int32
}
```

Structs can have attributes specified in square brackets after the struct.
Attributes are:

- `packed`: the struct does not have paddings between fields and has alignment 1; this is similar to GNU C `__attribute__((packed))`; struct alignment can be overridden with `align` attribute
- `align[N]`: the struct has alignment N and padded up to multiple of `N`; contents of the padding are unspecified (though, frequently are zeros); similar to GNU C `__attribute__((aligned(N)))`
- `size[N]`: the struct is padded up to the specified size `N`; contents of the padding are unspecified (though, frequently are zeros)

## Unions

Unions are described as:

```
unionname "[" "\n"
	(fieldname type (if[expression])? "\n")+
"]" ("[" attribute* "]")?
```

During fuzzing, syzkaller randomly picks one of the union options.

You may also specify conditions that determine whether the corresponding
option may or may not be selected, depending on values of other fields. See
[the corresponding section](syscall_descriptions_syntax.md#conditional-fields)
for more details.

Unions can have attributes specified in square brackets after the union.
Attributes are:

- `varlen`: union size is the size of the particular chosen option (not statically known); without this attribute unions are statically sized as maximum of all options (similar to C unions)
- `size[N]`: the union is padded up to the specified size `N`; contents of the padding are unspecified (though, frequently are zeros)

## Resources

Resources represent values that need to be passed from output of one syscall to input of another syscall. For example, `close` syscall requires an input value (fd) previously returned by `open` or `pipe` syscall. To achieve this, `fd` is declared as a resource. This is a way of modelling dependencies between syscalls, as defining a syscall as the producer of a resource and another syscall as the consumer defines a loose sense of ordering between them. Resources are described as:

```
"resource" identifier "[" underlying_type "]" [ ":" const ("," const)* ]
```

`underlying_type` is either one of `int8`, `int16`, `int32`, `int64`, `intptr` or another resource (which models inheritance, for example, a socket is a subtype of fd). The optional set of constants represent resource special values, for example, `0xffffffffffffffff` (-1) for "no fd", or `AT_FDCWD` for "the current dir". Special values are used once in a while as resource values. If no special values specified, special value of `0` is used. Resources can then be used as types, for example:

```
resource fd[int32]: 0xffffffffffffffff, AT_FDCWD, 1000000
resource sock[fd]
resource sock_unix[sock]

socket(...) sock
accept(fd sock, ...) sock
listen(fd sock, backlog int32)
```

Resources don't have to be necessarily returned by a syscall. They can be used as any other data type. For example:

```
resource my_resource[int32]

request_producer(..., arg ptr[out, my_resource])
request_consumer(..., arg ptr[inout, test_struct])

test_struct {
	...
	attr	my_resource
}
```

For more complex producer/consumer scenarios, field attributes can be utilized.
For example:

```
resource my_resource_1[int32]
resource my_resource_2[int32]

request_produce1_consume2(..., arg ptr[inout, test_struct])

test_struct {
	...
	field0	my_resource_1	(out)
	field1	my_resource_2	(in)
}
```

Each resource type must be "produced" (used as an output) by at least one syscall
(outside of unions and optional pointers) and "consumed" (used as an input)
by at least one syscall.

## Type Aliases

Complex types that are often repeated can be given short type aliases using the
following syntax:

```
type identifier underlying_type
```

For example:

```
type signalno int32[0:65]
type net_port proc[20000, 4, int16be]
```

Then, type alias can be used instead of the underlying type in any contexts.
Underlying type needs to be described as if it's a struct field, that is,
with the base type if it's required. However, type alias can be used as syscall
arguments as well. Underlying types are currently restricted to integer types,
`ptr`, `ptr64`, `const`, `flags` and `proc` types.

There are some builtin type aliases:

```
type bool8	int8[0:1]
type bool16	int16[0:1]
type bool32	int32[0:1]
type bool64	int64[0:1]
type boolptr	intptr[0:1]

type fileoff[BASE] BASE

type filename string[filename]

type buffer[DIR] ptr[DIR, array[int8]]
```

## Type Templates

Type templates can be declared as follows:

```
type buffer[DIR] ptr[DIR, array[int8]]
type fileoff[BASE] BASE
type nlattr[TYPE, PAYLOAD] {
	nla_len		len[parent, int16]
	nla_type	const[TYPE, int16]
	payload		PAYLOAD
} [align_4]
```

and later used as follows:

```
syscall(a buffer[in], b fileoff[int64], c ptr[in, nlattr[FOO, int32]])
```

There is builtin type template `optional` defined as:

```
type optional[T] [
	val	T
	void	void
] [varlen]
```

## Length

You can specify length of a particular field in struct or a named argument by
using `len`, `bytesize` and `bitsize` types, for example:

```
write(fd fd, buf ptr[in, array[int8]], count len[buf])

sock_fprog {
	len	len[filter, int16]
	filter	ptr[in, array[sock_filter]]
}
```

If `len`'s argument is a pointer, then the length of the pointee argument is used.

To denote the length of a field in N-byte words use `bytesizeN`, possible values
for N are 1, 2, 4 and 8.

To denote the length of the parent struct, you can use `len[parent, int8]`.
To denote the length of the higher level parent when structs are embedded into
one another, you can specify the type name of the particular parent:

```
s1 {
    f0      len[s2]  # length of s2
}

s2 {
    f0      s1
    f1      array[int32]
    f2      len[parent, int32]
}
```

`len` argument can also be a path expression which allows more complex
addressing. Path expressions are similar to C field references, but also allow
referencing parent and sibling elements. A special reference `syscall` used
in the beginning of the path allows to refer directly to the syscall arguments.
For example:

```
s1 {
	a	ptr[in, s2]
	b	ptr[in, s3]
	c	array[int8]
}

s2 {
	d	array[int8]
}

s3 {
# This refers to the array c in the parent s1.
	e	len[s1:c, int32]
# This refers to the array d in the sibling s2.
	f	len[s1:a:d, int32]
# This refers to the array k in the child s4.
	g	len[i:j, int32]
# This refers to syscall argument l.
	h	len[syscall:l, int32]
	i	ptr[in, s4]
}

s4 {
	j	array[int8]
}

foo(k ptr[in, s1], l ptr[in, array[int8]])
```

## Proc

The `proc` type can be used to denote per process integers.
The idea is to have a separate range of values for each executor, so they don't interfere.

The simplest example is a port number.
The `proc[20000, 4, int16be]` type means that we want to generate an `int16be`
integer starting from `20000` and assign `4` values for each process.
As a result the executor number `n` will get values in the `[20000 + n * 4, 20000 + (n + 1) * 4)` range.

## Integer Constants

Integer constants can be specified as decimal literals, as `0x`-prefixed
hex literals, as `'`-surrounded char literals, or as symbolic constants
extracted from kernel headers or defined by `define` directives. For example:

```
foo(a const[10], b const[-10])
foo(a const[0xabcd])
foo(a int8['a':'z'])
foo(a const[PATH_MAX])
foo(a int32[PATH_MAX])
foo(a ptr[in, array[int8, MY_PATH_MAX]])
define MY_PATH_MAX	PATH_MAX + 2
```

## Conditional fields

### In structures

In syzlang, it's possible to specify a condition for every struct field that
determines whether the field should be included or omitted:

```
header_fields {
  magic       const[0xabcd, int16]
  haveInteger int8
} [packed]

packet {
  header  header_fields
  integer int64  (if[value[header:haveInteger] == 0x1])
  body    array[int8]
} [packed]

some_call(a ptr[in, packet])
```

In this example, the `packet` structure will include the field `integer` only
if `header.haveInteger == 1`. In memory, `packet` will have the following
layout:

| header.magic = 0xabcd | header.haveInteger = 0x1 | integer | body |
| --------------------- | ------------------------ | ------- | ---- |

That corresponds to e.g. the following program:

```
some_call(&AUTO={{AUTO, 0x1}, @value=0xabcd, []})
```

If `header.haveInteger` is not `1`, syzkaller will just pretend that the field
`integer` does not exist.

```
some_call(&AUTO={{AUTO, 0x0}, @void, []})
```

| header.magic = 0xabcd | header.haveInteger = 0x0 | body |
| --------------------- | ------------------------ | ---- |

Every conditional field is assumed to be of variable length and so is the struct
to which this field belongs.

When a variable length field appears in the middle of a structure, the structure
must be marked with `[packed].`

Conditions on bitfields are prohibited:

```
struct {
  f0 int
  f1 int:3 (if[value[f0] == 0x1])  # It will not compile.
}
```

But you may reference bitfields in your conditions:

```
struct {
  f0 int:1
  f1 int:7
  f2 int   (if[value[f0] == value[f1]])
} [packed]
```

### In unions

Let's consider the following example.

```
struct {
  type int
  body alternatives
}

alternatives [
  int     int64 (if[value[struct:type] == 0x1])
  arr     array[int64, 5] (if[value[struct:type] == 0x2])
  default int32
] [varlen]

some_call(a ptr[in, struct])
```

In this case, the union option will be selected depending on the value of the
`type` field. For example, if `type` is `0x1`, then it can be either `int` or
`default`:

```
some_call(&AUTO={0x1, @int=0x123})
some_call(&AUTO={0x1, @default=0x123})
```

If `type` is `0x2`, it can be either `arr` or `default`.

If `type` is neither `0x1` nor `0x2`, syzkaller may only select `default`:

```
some_call(&AUTO={0x0, @default=0xabcd})
```

To ensure that a union can always be constructed, the last union field **must always
have no condition**.

Thus, the following definition would fail to compile:

```
alternatives [
  int int64 (if[value[struct:type] == 0x1])
  arr array[int64, 5] (if[value[struct:type] == 0x1])
] [varlen]
```

During prog mutation and generation syzkaller will select a random union field
whose condition is satisfied.

### Expression syntax

Currently, only `==`, `!=`, `&` and `||` operators are supported. However, the
functionality was designed in such a way that adding more operators is easy.
Feel free to file a GitHub issue or write us an email in case it's needed.

Expressions are evaluated as `int64` values. If the final result of an
expression is not 0, it's assumed to be satisfied.

If you want to reference a field's value, you can do it via
`value[path:to:field]`, which is similar to the `len[]` argument.

```
sub_struct {
  f0 int
  # Reference a field in a parent struct.
  f1 int (if[value[struct:f2]]) # Same as if[value[struct:f2] != 0].
}

struct {
  f2 int
  f3 sub_struct
  f4 int (if[value[f2] == 0x2]) # Reference a sibling field.
  f5 int (if[value[f3:f0] == 0x1]) # Reference a nested field.
  f6 int (if[value[f3:f0] == 0x1 || value[f3:f0] == 0x2]) # Reference a nested field which either equals to 0x1 or 0x2.
} [packed]

call(a ptr[in, struct])
```

The referenced field must be of integer type and there must be no
conditional fields in the path to it. For example, the following
descriptions will not compile.

```
struct {
  f0 int
  f1 int (if[value[f0] == 0x1])
  f2 int (if[value[f1] == 0x1])
}
```

You may also reference constants in expressions:

```
struct {
  f0 int
  f1 int
  f2 int (if[value[f0] & SOME_CONST == OTHER_CONST])
}
```

## Meta

Description files can also contain `meta` directives that specify meta-information for the whole file.

```
meta noextract
```

Tells `make extract` to not extract constants for this file.
Though, `syz-extract` can still be invoked manually on this file.

```
meta arches["arch1", "arch2"]
```

Restricts this file only to the given set of architectures.
`make extract` and `make generate` will not use it on other architectures.

## Misc

Description files also contain `include` directives that refer to Linux kernel header files,
`incdir` directives that refer to custom Linux kernel header directories
and `define` directives that define symbolic constant values.

The syzkaller executor defines some [pseudo system calls](./pseudo_syscalls.md)
that can be used as any other syscall in a description file. These pseudo
system calls expand to literal C code and can perform user-defined
custom actions. You can find some examples in
[executor/common_linux.h](../executor/common_linux.h).

Also see [tips](syscall_descriptions.md#tips) on writing good descriptions.

===

Don't make assumptions about the kernel source code (it may be different from what you assume it is).
Extensively use the provided code access tools (codesearch-*, git-*, grepper, etc)
to examine the actual source code, and confirm any assumptions.

Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
Bug title: KASAN: slab-use-after-free Read in i2c_adapter_lock_bus

The bug report to reproduce:
==================================================================
BUG: KASAN: slab-use-after-free in i2c_adapter_depth drivers/i2c/i2c-core-base.c:1243 [inline]
BUG: KASAN: slab-use-after-free in i2c_adapter_lock_bus+0x5e/0xf0 drivers/i2c/i2c-core-base.c:849
Read of size 8 at addr ffff8880270b4108 by task syz.4.7872/28255

CPU: 0 UID: 0 PID: 28255 Comm: syz.4.7872 Tainted: G             L      syzkaller #0 PREEMPT_{RT,(full)} 
Tainted: [L]=SOFTLOCKUP
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/16/2026
Call Trace:
 <TASK>
 dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
 print_address_description+0x55/0x1e0 mm/kasan/report.c:378
 print_address_description+0x55/0x1e0 mm/kasan/report.c:378
 print_report+0x58/0x70 mm/kasan/report.c:482
 kasan_report+0x117/0x150 mm/kasan/report.c:595
 i2c_adapter_depth drivers/i2c/i2c-core-base.c:1243 [inline]
 i2c_adapter_lock_bus+0x5e/0xf0 drivers/i2c/i2c-core-base.c:849
 i2c_lock_bus include/linux/i2c.h:809 [inline]
 __i2c_lock_bus_helper drivers/i2c/i2c-core.h:47 [inline]
 i2c_smbus_xfer+0xd5/0x310 drivers/i2c/i2c-core-smbus.c:543
 i2cdev_ioctl_smbus+0x407/0x700 drivers/i2c/i2c-dev.c:389
 i2cdev_ioctl+0x618/0x890 drivers/i2c/i2c-dev.c:478
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:597 [inline]
 __se_sys_ioctl+0xff/0x170 fs/ioctl.c:583
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0x174/0x580 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f0b2cb8de99
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f0b2ade6028 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00007f0b2ce15fa0 RCX: 00007f0b2cb8de99
RDX: 0000200000000080 RSI: 0000000000000720 RDI: 0000000000000003
RBP: 00007f0b2cc23eaf R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f0b2ce16038 R14: 00007f0b2ce15fa0 R15: 00007ffe659b19a8
 </TASK>

Allocated by task 1326:
 kasan_save_stack mm/kasan/common.c:57 [inline]
 kasan_save_track+0x3e/0x80 mm/kasan/common.c:78
 poison_kmalloc_redzone mm/kasan/common.c:398 [inline]
 __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:415
 kasan_kmalloc include/linux/kasan.h:263 [inline]
 __do_kmalloc_node mm/slub.c:5334 [inline]
 __kmalloc_node_track_caller_noprof+0x57f/0x7c0 mm/slub.c:5471
 kmalloc_reserve net/core/skbuff.c:637 [inline]
 __alloc_skb+0x2bd/0x7a0 net/core/skbuff.c:715
 alloc_skb include/linux/skbuff.h:1384 [inline]
 nsim_dev_trap_skb_build drivers/net/netdevsim/dev.c:819 [inline]
 nsim_dev_trap_report drivers/net/netdevsim/dev.c:876 [inline]
 nsim_dev_trap_report_work+0x2b1/0xcb0 drivers/net/netdevsim/dev.c:922
 process_one_work kernel/workqueue.c:3322 [inline]
 process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
 worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486
 kthread+0x388/0x470 kernel/kthread.c:436
 ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

Freed by task 1326:
 kasan_save_stack mm/kasan/common.c:57 [inline]
 kasan_save_track+0x3e/0x80 mm/kasan/common.c:78
 kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:584
 poison_slab_object mm/kasan/common.c:253 [inline]
 __kasan_slab_free+0x5c/0x80 mm/kasan/common.c:285
 kasan_slab_free include/linux/kasan.h:235 [inline]
 slab_free_hook mm/slub.c:2677 [inline]
 slab_free mm/slub.c:6377 [inline]
 kfree+0x1c5/0x6c0 mm/slub.c:6692
 skb_kfree_head net/core/skbuff.c:1077 [inline]
 skb_free_head net/core/skbuff.c:1089 [inline]
 skb_release_data+0x85e/0xab0 net/core/skbuff.c:1116
 skb_release_all net/core/skbuff.c:1191 [inline]
 __kfree_skb+0x5d/0x210 net/core/skbuff.c:1205
 nsim_dev_trap_report drivers/net/netdevsim/dev.c:892 [inline]
 nsim_dev_trap_report_work+0x879/0xcb0 drivers/net/netdevsim/dev.c:922
 process_one_work kernel/workqueue.c:3322 [inline]
 process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
 worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486
 kthread+0x388/0x470 kernel/kthread.c:436
 ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

The buggy address belongs to the object at ffff8880270b4000
 which belongs to the cache kmalloc-4k of size 4096
The buggy address is located 264 bytes inside of
 freed 4096-byte region [ffff8880270b4000, ffff8880270b5000)

The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x270b0
head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
flags: 0x80000000000040(head|node=0|zone=1)
page_type: f5(slab)
raw: 0080000000000040 ffff88813ffb2140 dead000000000100 dead000000000122
raw: 0000000000000000 0000000800040004 00000000f5000000 0000000000000000
head: 0080000000000040 ffff88813ffb2140 dead000000000100 dead000000000122
head: 0000000000000000 0000000800040004 00000000f5000000 0000000000000000
head: 0080000000000003 fffffffffffffe01 00000000ffffffff 00000000ffffffff
head: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000008
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 3, migratetype Unmovable, gfp_mask 0xd20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 1, tgid 1 (swapper/0), ts 13082770889, free_ts 13069657874
 set_page_owner include/linux/page_owner.h:32 [inline]
 post_alloc_hook+0x1f9/0x250 mm/page_alloc.c:1859
 prep_new_page mm/page_alloc.c:1867 [inline]
 get_page_from_freelist+0x262a/0x26a0 mm/page_alloc.c:3946
 __alloc_frozen_pages_noprof+0x18d/0x380 mm/page_alloc.c:5304
 alloc_slab_page mm/slub.c:3266 [inline]
 allocate_slab+0x79/0x5e0 mm/slub.c:3380
 new_slab mm/slub.c:3426 [inline]
 refill_objects+0x2d8/0x350 mm/slub.c:7310
 refill_sheaf mm/slub.c:2804 [inline]
 __pcs_replace_empty_main+0x330/0x690 mm/slub.c:4675
 alloc_from_pcs mm/slub.c:4773 [inline]
 slab_alloc_node mm/slub.c:4905 [inline]
 __kmalloc_cache_noprof+0x468/0x6b0 mm/slub.c:5485
 _kmalloc_noprof include/linux/slab.h:988 [inline]
 _kzalloc_noprof include/linux/slab.h:1309 [inline]
 kobject_uevent_env+0x28c/0x9e0 lib/kobject_uevent.c:543
 device_add+0x544/0xb80 drivers/base/core.c:3738
 device_create_groups_vargs drivers/base/core.c:4454 [inline]
 device_create+0x269/0x300 drivers/base/core.c:4493
 mon_bin_add+0xb6/0x130 drivers/usb/mon/mon_bin.c:1371
 mon_bus_init+0x173/0x2b0 drivers/usb/mon/mon_main.c:291
 mon_bus_add drivers/usb/mon/mon_main.c:188 [inline]
 mon_notify+0x10c/0x3f0 drivers/usb/mon/mon_main.c:219
 notifier_call_chain+0x1a5/0x3d0 kernel/notifier.c:85
 blocking_notifier_call_chain+0x6a/0x90 kernel/notifier.c:380
 usb_register_bus+0xcf/0x150 drivers/usb/core/hcd.c:904
page last free pid 10 tgid 10 stack trace:
 reset_page_owner include/linux/page_owner.h:25 [inline]
 __free_pages_prepare mm/page_alloc.c:1406 [inline]
 free_pages_prepare+0x946/0xa40 mm/page_alloc.c:1451
 __free_contig_range_common+0x174/0x340 mm/page_alloc.c:6897
 __free_contig_range mm/page_alloc.c:6942 [inline]
 free_pages_bulk+0x48/0x120 mm/page_alloc.c:5257
 vm_area_free_pages mm/vmalloc.c:3439 [inline]
 vfree+0x26f/0x510 mm/vmalloc.c:3488
 delayed_vfree_work+0x55/0x80 mm/vmalloc.c:3392
 process_one_work kernel/workqueue.c:3322 [inline]
 process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405
 worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486
 kthread+0x388/0x470 kernel/kthread.c:436
 ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

Memory state around the buggy address:
 ffff8880270b4000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff8880270b4080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff8880270b4100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                      ^
 ffff8880270b4180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff8880270b4200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================


The list of existing description files:
acpi_thermal_rel.txt
aio.txt
auto.txt
binfmt.txt
bpf.txt
bpf_prog.txt
bpf_trace.txt
cgroup.txt
damon.txt
dev_ashmem.txt
dev_bifrost.txt
dev_binder.txt
dev_binderfs.txt
dev_block.txt
dev_bsg.txt
dev_bus_usb.txt
dev_camx.txt
dev_cdrom.txt
dev_cec.txt
dev_char_usb.txt
dev_comedi.txt
dev_dma_heap.txt
dev_dri.txt
dev_dsp.txt
dev_dvb_demux.txt
dev_dvb_dvr.txt
dev_dvb_frontend.txt
dev_fb.txt
dev_floppy.txt
dev_hidraw.txt
dev_i2c.txt
dev_i915.txt
dev_img_rogue.txt
dev_infiniband_rdma.txt
dev_infiniband_rdma_cm.txt
dev_input.txt
dev_iommu.txt
dev_kvm.txt
dev_kvm_amd64.txt
dev_kvm_arm64.txt
dev_kvm_extra.txt
dev_kvm_riscv64.txt
dev_loop.txt
dev_mali.txt
dev_media.txt
dev_msm.txt
dev_msr.txt
dev_mtd.txt
dev_nbd.txt
dev_net_tun.txt
dev_panthor.txt
dev_ppp.txt
dev_ptmx.txt
dev_ptp.txt
dev_qat_adf_ctl.txt
dev_qrtr_tun.txt
dev_random.txt
dev_rfkill.txt
dev_rtc.txt
dev_sequencer.txt
dev_sg.txt
dev_snapshot.txt
dev_snd_control.txt
dev_snd_hw.txt
dev_snd_midi.txt
dev_snd_pcm.txt
dev_snd_seq.txt
dev_snd_timer.txt
dev_sr.txt
dev_sw_sync.txt
dev_tee.txt
dev_tlk_device.txt
dev_trusty.txt
dev_udmabuf.txt
dev_uhid.txt
dev_uinput.txt
dev_usb_hiddev.txt
dev_usbmon.txt
dev_userio.txt
dev_vfio.txt
dev_vga_arbiter.txt
dev_vhci.txt
dev_video4linux.txt
dev_video4linux_vim2m.txt
dev_virtual_nci.txt
dev_vtpm.txt
fanotify.txt
filesystem.txt
fs_9p.txt
fs_fuse.txt
fs_incfs.txt
fs_ioctl.txt
fs_ioctl_autofs.txt
fs_ioctl_btrfs.txt
fs_ioctl_ext4.txt
fs_ioctl_f2fs.txt
fs_ioctl_fat.txt
fs_ioctl_fscrypt.txt
fs_ioctl_fsverity.txt
fs_ioctl_nilfs2.txt
fs_ioctl_ocfs2.txt
fs_ioctl_xfs.txt
futex.txt
hafnium.txt
inotify.txt
io_uring.txt
ipc.txt
key.txt
kfuzztest.txt
l2cap.txt
landlock.txt
lsm.txt
namespaces.txt
net_80211.txt
netfilter.txt
netfilter_arp.txt
netfilter_bridge.txt
netfilter_ipv4.txt
netfilter_ipv6.txt
netfilter_ipvs.txt
netfilter_targets.txt
pagemap_ioctl.txt
perf.txt
prctl.txt
quotactl.txt
seccomp.txt
security_apparmor.txt
security_selinux.txt
security_smack.txt
socket.txt
socket_alg.txt
socket_ax25.txt
socket_bluetooth.txt
socket_bluetooth_defs_default.txt
socket_bluetooth_defs_mips.txt
socket_caif.txt
socket_can.txt
socket_ieee802154.txt
socket_inet.txt
socket_inet6.txt
socket_inet_dccp.txt
socket_inet_icmp.txt
socket_inet_igmp.txt
socket_inet_l2tp.txt
socket_inet_sctp.txt
socket_inet_tcp.txt
socket_inet_udp.txt
socket_ip_tunnel.txt
socket_isdn.txt
socket_isdn_defs_386_arm.txt
socket_isdn_defs_cmd_default.txt
socket_isdn_defs_common_default.txt
socket_isdn_defs_mips.txt
socket_kcm.txt
socket_key.txt
socket_llc.txt
socket_netlink.txt
socket_netlink_audit.txt
socket_netlink_crypto.txt
socket_netlink_generic.txt
socket_netlink_generic_80211.txt
socket_netlink_generic_batadv.txt
socket_netlink_generic_devlink.txt
socket_netlink_generic_ethtool.txt
socket_netlink_generic_fou.txt
socket_netlink_generic_gtp.txt
socket_netlink_generic_mptcp.txt
socket_netlink_generic_net_dm.txt
socket_netlink_generic_netlabel.txt
socket_netlink_generic_nfc.txt
socket_netlink_generic_seg6.txt
socket_netlink_generic_smc.txt
socket_netlink_generic_team.txt
socket_netlink_generic_wireguard.txt
socket_netlink_netfilter.txt
socket_netlink_netfilter_acct.txt
socket_netlink_netfilter_conntrack.txt
socket_netlink_netfilter_conntrack_exp.txt
socket_netlink_netfilter_conntrack_helper.txt
socket_netlink_netfilter_ipset.txt
socket_netlink_netfilter_log.txt
socket_netlink_netfilter_nft_compat.txt
socket_netlink_netfilter_nftables.txt
socket_netlink_netfilter_osf.txt
socket_netlink_netfilter_queue.txt
socket_netlink_netfilter_timeout.txt
socket_netlink_rdma.txt
socket_netlink_route.txt
socket_netlink_route_sched.txt
socket_netlink_route_sched_retired.txt
socket_netlink_sock_diag.txt
socket_netlink_xfrm.txt
socket_netrom.txt
socket_nfc.txt
socket_nvme_of_tcp.txt
socket_packet.txt
socket_phonet.txt
socket_pppox.txt
socket_pppox_defs_386_arm.txt
socket_pppox_defs_default.txt
socket_pppox_defs_mips.txt
socket_qipcrtr.txt
socket_rds.txt
socket_rose.txt
socket_rxrpc.txt
socket_tipc.txt
socket_tipc_netlink.txt
socket_unix.txt
socket_vnet.txt
socket_x25.txt
socket_xdp.txt
sys.txt
ublk.txt
uffd.txt
usbip.txt
vmw_vmci.txt
vnet.txt
vnet_mptcp.txt
vusb.txt
watch_queue.txt
xattr.txt


5/2 2026/07/30 12:17 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 18818
							output: 24
							thoughts: 1397
						

Thoughts:
**KASAN Slab-Use-After-Free Deep Dive**

Okay, so I've got a KASAN slab-use-after-free in `i2c_adapter_lock_bus`. The crash occurs at `drivers/i2c/i2c-core-base.c:849`. The stack trace shows the call path: `i2c_adapter_lock_bus` -> `i2c_smbus_xfer` -> `i2cdev_ioctl_smbus` -> `i2cdev_ioctl`. It looks like it's on something related to an `i2c_adapter` or `i2c_client`.

The initial allocation happens within `nsim_dev_trap_report_work` in `netdevsim`. Huh, that's interesting. Then I see the freed object is actually an `sk_buff` of size 4096 bytes. The buggy address is 264 bytes into this 4096-byte region, so it's a memory region within the buffer. Now, wait a minute... an `skb` is 4096 bytes, but the kernel uses the `kmalloc-4k` cache, right? The `skb->head` is what's allocated from `kmalloc-4k`.

But how could an `i2c_adapter` end up inside `skb->head`?  Could it be that the `i2c_adapter` was allocated in the `kmalloc-4k` region, freed, and *then* that same region was re-allocated as `skb->head` and subsequently freed again? That's the most likely scenario given the KASAN report, which doesn't explicitly show the `i2c_adapter` allocation.

Let's look at the free stack trace now. It's freed as `skb->head`, via `skb_release_data`, `__kfree_skb`, and finally back to `nsim_dev_trap_report_work`. Okay, that confirms that the problematic memory region was associated with the `sk_buff` when the UAF happened.

The page itself was last allocated by `kobject_uevent_env` via `usb_register_bus` – no that is not correct. The relevant allocation is hidden by `skb->head` allocations.

So, let's now investigate the `i2cdev_ioctl_smbus` and `i2c_smbus_xfer` functions. In `i2cdev_ioctl_smbus`, it uses `client->adapter`. Where does `client` come from? It's `file->private_data` in `i2cdev_ioctl`. That means that the `file->private_data` must be an `i2c_client`. Ah, right, when you open `/dev/i2c-X`, the kernel creates an `i2c_client` and assigns it to `file->private_data`. So, the `i2c_client` must be allocated during the `i2cdev_open` call. Now to review `drivers/i2c/i2c-dev.c` in detail to determine the memory management.



6/2 2026/07/30 12:18 tool codesearch-definition-source
0m Args:
map[Name:i2cdev_open]

Results:
map[SourceCode: 598:	static int i2cdev_open(struct inode *inode, struct file *file)
 599:	{
 600:		unsigned int minor = iminor(inode);
 601:		struct i2c_client *client;
 602:		struct i2c_adapter *adap;
 603:	
 604:		adap = i2c_get_adapter(minor);
 605:		if (!adap)
 606:			return -ENODEV;
 607:	
 608:		/* This creates an anonymous i2c_client, which may later be
 609:		 * pointed to some address using I2C_SLAVE or I2C_SLAVE_FORCE.
 610:		 *
 611:		 * This client is ** NEVER REGISTERED ** with the driver model
 612:		 * or I2C core code!!  It just holds private copies of addressing
 613:		 * information and maybe a PEC flag.
 614:		 */
 615:		client = kzalloc_obj(*client);
 616:		if (!client) {
 617:			i2c_put_adapter(adap);
 618:			return -ENOMEM;
 619:		}
 620:		snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);
 621:	
 622:		client->adapter = adap;
 623:		file->private_data = client;
 624:	
 625:		return 0;
 626:	}
 SourceFile:drivers/i2c/i2c-dev.c]

7/2 2026/07/30 12:18 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 21409
							output: 25
							thoughts: 59
						

Thoughts:
**Dissecting the I2C Adapter Retrieval**

Okay, so I'm looking at this code and trying to trace how the I2C adapter is being accessed. My initial impression is that the `client->adapter` is going to be assigned the variable `adap`. That looks like it comes from calling `i2c_get_adapter(minor)`. That means I'm going to want to check that method out.

It's clear that `i2c_get_adapter` is the crucial piece here, and that it is taking a `minor` argument. Importantly, it's also taking a reference to the adapter, whatever that turns out to mean in practice. Time to dive into the implementation of `i2c_get_adapter` and see how it works!



8/2 2026/07/30 12:18 tool codesearch-definition-source
0m Args:
map[Name:i2c_get_adapter]

Results:
map[SourceCode:2628:	struct i2c_adapter *i2c_get_adapter(int nr)
2629:	{
2630:		struct i2c_adapter *adapter;
2631:	
2632:		mutex_lock(&core_lock);
2633:		adapter = idr_find(&i2c_adapter_idr, nr);
2634:		if (!adapter)
2635:			goto exit;
2636:	
2637:		if (try_module_get(adapter->owner))
2638:			get_device(&adapter->dev);
2639:		else
2640:			adapter = NULL;
2641:	
2642:	 exit:
2643:		mutex_unlock(&core_lock);
2644:		return adapter;
2645:	}
 SourceFile:drivers/i2c/i2c-core-base.c]

9/2 2026/07/30 12:18 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 21924
							output: 24
							thoughts: 39
						

Thoughts:
Okay, here's my interpretation of that thought process, from an expert's perspective:

**Diving into the I2C Adapter Lifecycle**

Right, so I'm tracing the flow of events when an I2C device is handled, and I'm focusing on the adapter itself. First, I see `i2c_get_adapter` being called, which then immediately calls `get_device(&adapter->dev)`. I know that `get_device` is the foundational function for device registration in the kernel. So, I'm thinking about the implications of that adapter device struct, and how this initial call sets the stage for future operations. Then, when the file representing that I2C device is closed, that's when `i2cdev_release` gets called. Now, I'm thinking about the resource management implications here and how the closing of the device file signals the kernel that the resources associated with it are no longer needed, and this function handles the necessary cleanup process, including releasing any hold on the adapter resources. I'm imagining how that's all tied together with the broader framework of device discovery, resource allocation, and, importantly, the kernel's way of gracefully handling the life cycle of the I2C bus.



10/2 2026/07/30 12:18 tool codesearch-definition-source
0m Args:
map[Name:i2cdev_release]

Results:
map[SourceCode: 628:	static int i2cdev_release(struct inode *inode, struct file *file)
 629:	{
 630:		struct i2c_client *client = file->private_data;
 631:	
 632:		i2c_put_adapter(client->adapter);
 633:		kfree(client);
 634:		file->private_data = NULL;
 635:	
 636:		return 0;
 637:	}
 SourceFile:drivers/i2c/i2c-dev.c]

11/2 2026/07/30 12:18 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 22422
							output: 23
							thoughts: 255
						

Thoughts:
**Debugging an I2C Adapter Release**

Okay, so `i2c_put_adapter` calls `put_device` on the adapter's device. That seems standard. But here's the kicker: if the adapter is freed while a file is still open, that implies `get_device` somehow *failed* to prevent the adapter from being released prematurely. That makes no sense. Hold on... `get_device` is supposed to increment the reference count of `adapter->dev`, right? So the adapter shouldn't be released until that count hits zero. If the adapter *is* freed, then its reference count must have dropped to zero. But `i2cdev_open` increments the count, so that *shouldn't* happen.

Alright, so this points to a few possibilities: either someone called `put_device` too many times and decremented it below zero – which is really bad and should have been caught – or, the adapter is being freed without properly waiting for its `adapter->dev` reference count to actually reach zero.

Let's dig deeper. How are these `i2c_adapter` structures allocated and freed in the first place? Usually, it's either embedded within another struct, or it's dynamically allocated. If it's embedded, and that containing struct is freed *without* waiting for the `adapter->dev` refcount to be zero, that's a classic memory management bug right there.

Wait a second, the KASAN report specifies an address, 264 bytes into a 4096-byte region, that's a really useful clue. Let's see how that relates to the size of the `i2c_adapter` struct; that should tell me more about how this is being allocated.



12/2 2026/07/30 12:18 tool codesearch-struct-layout
0m Args:
map[Name:i2c_adapter]

Results:
map[Fields:[map[Name:owner OffsetBits:0 SizeBits:64] map[Name:class OffsetBits:64 SizeBits:32] map[Name:algo OffsetBits:128 SizeBits:64] map[Name:algo_data OffsetBits:192 SizeBits:64] map[Name:lock_ops OffsetBits:256 SizeBits:64] map[Name:bus_lock OffsetBits:320 SizeBits:1024] map[Name:mux_lock OffsetBits:1344 SizeBits:1024] map[Name:timeout OffsetBits:2368 SizeBits:32] map[Name:retries OffsetBits:2400 SizeBits:32] map[Name:dev OffsetBits:2432 SizeBits:11776] map[Name:locked_flags OffsetBits:14208 SizeBits:64] map[Name:nr OffsetBits:14272 SizeBits:32] map[Name:name OffsetBits:14304 SizeBits:384] map[Name:dev_released OffsetBits:14720 SizeBits:704] map[Name:userspace_clients_lock OffsetBits:15424 SizeBits:1024] map[Name:userspace_clients OffsetBits:16448 SizeBits:128] map[Name:bus_recovery_info OffsetBits:16576 SizeBits:64] map[Name:quirks OffsetBits:16640 SizeBits:64] map[Name:host_notify_domain OffsetBits:16704 SizeBits:64] map[Name:bus_regulator OffsetBits:16768 SizeBits:64] map[Name:debugfs OffsetBits:16832 SizeBits:64] map[Name:addrs_in_instantiation OffsetBits:16896 SizeBits:128]]]

13/2 2026/07/30 12:18 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 23590
							output: 27
							thoughts: 189
						

Thoughts:
**Analyzing a KASAN Report and I2C Bus Locking**

Okay, the KASAN report is screaming about a read of size 8 at address `ffff8880270b4108`. The system says this buggy address is 264 bytes into a freed 4096-byte region. 264 bytes is 2112 bits, that makes sense. Let's see... the report mentions `bus_lock`. I know from experience that the `bus_lock` is at offset 320 bits (40 bytes), or is it? Let me confirm that again, 40 bytes.

The `i2c_adapter_lock_bus` function is accessing `adapter->bus_lock`. Ah, right, that function calls `rt_mutex_lock(&adapter->bus_lock)`. That makes sense. Wait, I remember `bus_lock` is a `struct rt_mutex`.

Okay, I need to get the source code for `i2c_adapter_lock_bus` to understand how that mutex is being used within the I2C bus locking mechanism. Let's dig in and see what's going on there.



14/2 2026/07/30 12:18 tool codesearch-definition-source
0m Args:
map[Name:i2c_adapter_lock_bus]

Results:
map[SourceCode: 840:	/**
 841:	 * i2c_adapter_lock_bus - Get exclusive access to an I2C bus segment
 842:	 * @adapter: Target I2C bus segment
 843:	 * @flags: I2C_LOCK_ROOT_ADAPTER locks the root i2c adapter, I2C_LOCK_SEGMENT
 844:	 *	locks only this branch in the adapter tree
 845:	 */
 846:	static void i2c_adapter_lock_bus(struct i2c_adapter *adapter,
 847:					 unsigned int flags)
 848:	{
 849:		rt_mutex_lock_nested(&adapter->bus_lock, i2c_adapter_depth(adapter));
 850:	}
 SourceFile:drivers/i2c/i2c-core-base.c]

15/2 2026/07/30 12:18 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 24305
							output: 25
							thoughts: 17
						

Thoughts:
Here's my thought process, as if I were the one thinking it:

**Digging into that `i2c_adapter_depth` Function...**

Okay, so I'm looking at this `i2c_adapter_depth` function, and something just clicked. I see it's trying to figure out the nesting depth of an I2C adapter. But hold on a second... it's also directly accessing the `adapter` itself within the function. I initially glazed over it, but that's a key detail I almost missed. I need to keep that relationship in mind as I keep going.



16/2 2026/07/30 12:18 tool codesearch-definition-source
0m Args:
map[Name:i2c_adapter_depth]

Results:
map[SourceCode:1237:	unsigned int i2c_adapter_depth(struct i2c_adapter *adapter)
1238:	{
1239:		unsigned int depth = 0;
1240:		struct device *parent;
1241:	
1242:		for (parent = adapter->dev.parent; parent; parent = parent->parent)
1243:			if (parent->type == &i2c_adapter_type)
1244:				depth++;
1245:	
1246:		WARN_ONCE(depth >= MAX_LOCKDEP_SUBCLASSES,
1247:			  "adapter depth exceeds lockdep subclass limit\n");
1248:	
1249:		return depth;
1250:	}
 SourceFile:drivers/i2c/i2c-core-base.c]

17/2 2026/07/30 12:18 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 24712
							output: 19
							thoughts: 72
						

Thoughts:
**Dissecting the Memory Layout**

Okay, so I'm tracing through this code and I see an access to `adapter->dev.parent`. Right, `adapter->dev.parent` is the thing that triggered the alert. Let's see... `adapter->dev` is accessed. I need to figure out the offset of `dev` within the `adapter` structure. Let me see... 2432 bits equals 304 bytes. Okay, so `dev` is 304 bytes into the `adapter` structure. Since the issue is at `adapter->dev.parent`, I am now sure the offset of `dev` is actually at 304 bytes into the `adapter` struct. Excellent, `parent` is a field *within* the `struct device`. Now, I need to understand the layout of `struct device` to properly diagnose this. I am going to examine the `struct device` definition right away. Let's check the `struct device` layout to see what `parent` is.



18/2 2026/07/30 12:18 tool codesearch-struct-layout
0m Args:
map[Name:device]

Results:
map[Fields:[map[Name:kobj OffsetBits:0 SizeBits:512] map[Name:parent OffsetBits:512 SizeBits:64] map[Name:p OffsetBits:576 SizeBits:64] map[Name:init_name OffsetBits:640 SizeBits:64] map[Name:type OffsetBits:704 SizeBits:64] map[Name:bus OffsetBits:768 SizeBits:64] map[Name:driver OffsetBits:832 SizeBits:64] map[Name:platform_data OffsetBits:896 SizeBits:64] map[Name:driver_data OffsetBits:960 SizeBits:64] map[Name:driver_override OffsetBits:1024 SizeBits:1088] map[Name:mutex OffsetBits:2112 SizeBits:1024] map[Name:links OffsetBits:3136 SizeBits:448] map[Name:power OffsetBits:3584 SizeBits:5440] map[Name:pm_domain OffsetBits:9024 SizeBits:64] map[Name:msi OffsetBits:9088 SizeBits:128] map[Name:dma_mask OffsetBits:9216 SizeBits:64] map[Name:coherent_dma_mask OffsetBits:9280 SizeBits:64] map[Name:bus_dma_limit OffsetBits:9344 SizeBits:64] map[Name:dma_range_map OffsetBits:9408 SizeBits:64] map[Name:dma_parms OffsetBits:9472 SizeBits:64] map[Name:dma_pools OffsetBits:9536 SizeBits:128] map[Name:dma_mem OffsetBits:9664 SizeBits:64] map[Name:cma_area OffsetBits:9728 SizeBits:64] map[Name:dma_io_tlb_mem OffsetBits:9792 SizeBits:64] map[Name:archdata OffsetBits:9856 SizeBits:0] map[Name:of_node OffsetBits:9856 SizeBits:64] map[Name:fwnode OffsetBits:9920 SizeBits:64] map[Name:numa_node OffsetBits:9984 SizeBits:32] map[Name:devt OffsetBits:10016 SizeBits:32] map[Name:id OffsetBits:10048 SizeBits:32] map[Name:devres_lock OffsetBits:10112 SizeBits:1024] map[Name:devres_head OffsetBits:11136 SizeBits:128] map[Name:class OffsetBits:11264 SizeBits:64] map[Name:groups OffsetBits:11328 SizeBits:64] map[Name:release OffsetBits:11392 SizeBits:64] map[Name:iommu_group OffsetBits:11456 SizeBits:64] map[Name:iommu OffsetBits:11520 SizeBits:64] map[Name:physical_location OffsetBits:11584 SizeBits:64] map[Name:removable OffsetBits:11648 SizeBits:32] map[Name:flags OffsetBits:11712 SizeBits:64]]]

19/2 2026/07/30 12:18 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 25925
							output: 21
							thoughts: 690
						

Thoughts:
**Debugging a KASAN Report: Unraveling the Memory Access**

Okay, so I'm digging into this KASAN report, and it looks like we have a problem with memory access in an `i2c_adapter`. The report is pointing to a read of size 8 at a specific address, and it's flagged as being inside a freed region.  The buggy address is at a 264-byte offset within that region.

My initial thought was to find the `parent` pointer of the `device` struct, which resides inside the `i2c_adapter`. I figured it would be an offset of 64 bytes inside of the `device` struct.  Thus, the offset of `adapter->dev.parent` is 304 + 64 = 368 bytes inside the `i2c_adapter`. But, the buggy address is at 264 bytes into the region!

I re-checked the `i2c_adapter` layout, double-checking the offset of `dev`, which is at 304 bytes. Then it hit me: 264 bytes is 2112 bits, which is more directly useful to look at with regards to the bitfield layout of the structure! So what's at 2112 bits within the `i2c_adapter`?

I started tracing down the structure's layout again. `mux_lock` is at 1344 bits with a size of 1024 bits. So it ends at 2368 bits. Wait, 2112 bits is inside the `mux_lock`? No, no, `mux_lock` is a `struct rt_mutex`.

Okay, the `bus_lock` is at 320 bits with a size of 1024 bits. It ends at 1344 bits. And here's where it clicks – `i2c_adapter_lock_bus` calls `rt_mutex_lock_nested` on `adapter->bus_lock`.

I recall that `bus_lock` is at offset 40 bytes (320 bits). If the buggy address is 264 bytes, that's 264 - 40 = 224 bytes inside the `bus_lock` memory region, which is the `rt_mutex`!

Wait, I need to know the size of `rt_mutex`. It's 1024 bits = 128 bytes. So `bus_lock` would end at 40 + 128 = 168 bytes. So I am still looking past the `bus_lock` structure. What IS at 264 bytes?

Let's look at `i2c_adapter_depth` again, because it accesses `adapter->dev.parent`.

The KASAN report says it's a read of size 8 at address `ffff8880270b4108`. The buggy address is located 264 bytes inside of the freed region [ffff8880270b4000, ffff8880270b5000). So, 0x108 = 264 bytes.

So, if `adapter` is at `ffff8880270b4000`, `adapter->dev.parent` should be at `ffff8880270b4170` (304 + 64). But the buggy address is `ffff8880270b4108`. I'm off by 104 bytes in my calculations. What's at 264 bytes (0x108) again?

I'm getting closer, let's go back and check the layout of `struct rt_mutex` again. I need to understand what's actually located at this offset.



20/2 2026/07/30 12:18 tool codesearch-struct-layout
0m Args:
map[Name:rt_mutex]

Results:
map[Fields:[map[Name:rtmutex OffsetBits:0 SizeBits:704] map[Name:dep_map OffsetBits:704 SizeBits:320]]]

21/2 2026/07/30 12:18 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 27552
							output: 31
							thoughts: 434
						

Thoughts:
**Analyzing a KASAN Report and Memory Offsets**

Okay, let's break this down. First, I'm noting that the `struct rt_mutex` definition has its `dep_map` member starting at an offset of 88 bytes. I also know that `bus_lock` is at offset 40 bytes. This means `bus_lock.dep_map` should start at 40 + 88 = 128 bytes. The real question is, what's at 264 bytes? I need to check the `i2c_adapter` structure again. Let me quickly refresh my memory of the layout; `lock_ops` is at 32 bytes, `bus_lock` at 40 bytes, `mux_lock` at 168 bytes, and `timeout` is at 296 bytes. So 264 bytes falls within `mux_lock`, specifically!

But wait, I need to be more precise. If `mux_lock` is at 168 bytes, then `mux_lock.dep_map` should be at 168 + 88 = 256 bytes. And `mux_lock.dep_map` takes up 40 bytes. So 264 bytes *is* inside `mux_lock.dep_map`. This is where it gets interesting: why would `i2c_adapter_lock_bus` be accessing `mux_lock.dep_map`? Ah, I remember, the call to `rt_mutex_lock_nested` passes `&adapter->bus_lock`.

Ok, `bus_lock` is at 40 bytes. But here's the kicker: the KASAN report is screaming about a read of size 8 at `ffff8880270b4108`. That address looks familiar! Let me compute the offset. `ffff8880270b4108` is `ffff8880270b4000` + 0x108. And 0x108 is, yes, 264 in decimal. So that matches the offset I was trying to find, it is accessing `mux_lock.dep_map`. I need to now check the `rt_mutex_lock_nested` macro to understand this better.



22/2 2026/07/30 12:18 tool codesearch-find-references
0m Args:
map[IncludeSnippetLines:5 Name:rt_mutex_lock_nested]

Results:
map[References:[map[ReferenceKind:calls ReferencingEntityKind:function ReferencingEntityName:i2c_adapter_lock_bus SourceFile:drivers/i2c/i2c-core-base.c SourceLine:849 SourceSnippet: 844:	 *	locks only this branch in the adapter tree
 845:	 */
 846:	static void i2c_adapter_lock_bus(struct i2c_adapter *adapter,
 847:					 unsigned int flags)
 848:	{
 849:		rt_mutex_lock_nested(&adapter->bus_lock, i2c_adapter_depth(adapter));
 850:	}
] map[ReferenceKind:calls ReferencingEntityKind:function ReferencingEntityName:i2c_mux_lock_bus SourceFile:drivers/i2c/i2c-mux.c SourceLine:135 SourceSnippet: 130:	static void i2c_mux_lock_bus(struct i2c_adapter *adapter, unsigned int flags)
 131:	{
 132:		struct i2c_mux_priv *priv = adapter->algo_data;
 133:		struct i2c_adapter *parent = priv->muxc->parent;
 134:	
 135:		rt_mutex_lock_nested(&parent->mux_lock, i2c_adapter_depth(adapter));
 136:		if (!(flags & I2C_LOCK_ROOT_ADAPTER))
 137:			return;
 138:		i2c_lock_bus(parent, flags);
 139:	}
] map[ReferenceKind:calls ReferencingEntityKind:function ReferencingEntityName:i2c_parent_lock_bus SourceFile:drivers/i2c/i2c-mux.c SourceLine:172 SourceSnippet: 167:					unsigned int flags)
 168:	{
 169:		struct i2c_mux_priv *priv = adapter->algo_data;
 170:		struct i2c_adapter *parent = priv->muxc->parent;
 171:	
 172:		rt_mutex_lock_nested(&parent->mux_lock, i2c_adapter_depth(adapter));
 173:		i2c_lock_bus(parent, flags);
 174:	}
] map[ReferenceKind:takes-address-of ReferencingEntityKind:global_variable ReferencingEntityName:__UNIQUE_ID_addressable_rt_mutex_lock_nested_817 SourceFile:kernel/locking/rtmutex_api.c SourceLine:80 SourceSnippet:  80:	EXPORT_SYMBOL_GPL(rt_mutex_lock_nested);
] map[ReferenceKind:takes-address-of ReferencingEntityKind:global_variable ReferencingEntityName:__gendwarfksyms_ptr_rt_mutex_lock_nested SourceFile:kernel/locking/rtmutex_api.c SourceLine:80 SourceSnippet:  80:	EXPORT_SYMBOL_GPL(rt_mutex_lock_nested);
] map[ReferenceKind:takes-address-of ReferencingEntityKind:global_variable ReferencingEntityName:__gendwarfksyms_ptr_rt_mutex_lock_nested SourceFile:kernel/locking/rtmutex_api.c SourceLine:80 SourceSnippet:  80:	EXPORT_SYMBOL_GPL(rt_mutex_lock_nested);
]] TruncatedOutput:false]

23/2 2026/07/30 12:18 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 29461
							output: 23
							thoughts: 873
						

Thoughts:
**Debugging a KASAN Report: Unraveling a Use-After-Free in i2c_adapter_depth**

Okay, first things first, `rt_mutex_lock_nested` isn't a macro, it's an exported function, so that's not the issue. Let's get back to `i2c_adapter_depth` and refresh my memory. Right, it's about checking the nesting depth of i2c adapters, pretty straightforward.

Now, let's look closely at the crash reported by KASAN, and the code line where it's happening, which is `i2c_adapter_depth` at `drivers/i2c/i2c-core-base.c:1243`. Line 1243 is the conditional check `if (parent->type == &i2c_adapter_type)`. Wait a minute, what is the type of `parent`? Oh right, it's `struct device *`.

Now, if I remember correctly, `adapter->dev.parent` is at offset 304 + 64 = 368 bytes. The KASAN report is referencing line 1243 which accesses `parent->type`. I know the type member is at offset 88 bytes within `struct device`. I need to track down the address that's causing the access violation, this should be fun.

The report says the crash is at `i2c_adapter_depth` reading `parent->type`, so the crash address is an offset to `parent`. The KASAN report states that we have `ffff8880270b4000` + 0x108 - 88 = `ffff8880270b4000` + 176 = `ffff8880270b40b0`. So, if `parent` is this address, then `parent->type` will be at `ffff8880270b40b0` + 88 = `ffff8880270b4108`. And there it is, the address `ffff8880270b4108`! The report is correct!

So, the faulty `parent` pointer is `ffff8880270b40b0`. The pointer is pointing inside a freed 4096-byte region, [ffff8880270b4000, ffff8880270b5000), which is a clear sign of use-after-free. If `parent` points inside the freed region, then its `struct device` instance was freed.

Since `parent` is `adapter->dev.parent`, it seems the parent device was freed. So, the `parent` device is at `ffff8880270b40b0` within `[ffff8880270b4000, ffff8880270b5000)`. Wait, could `ffff8880270b40b0` be the start of an i2c adapter, and not a `struct device`? Well, the dev member is at offset 304 in the i2c adapter. Let's see, if this were an `i2c_adapter` then the `parent` device would be at offset 304 bytes. Then it would be `ffff8880270b4000` + 304 = `ffff8880270b4130`. But the crash is happening on `ffff8880270b40b0`.

Okay, so we know `ffff8880270b40b0` is `ffff8880270b4000` + 176. Now, what's at offset 176? The struct layout is where the money is at... Is it a `struct i2c_client`? Looks like we have some homework.



24/2 2026/07/30 12:19 tool codesearch-struct-layout
0m Args:
map[Name:i2c_client]

Results:
map[Fields:[map[Name:flags OffsetBits:0 SizeBits:16] map[Name:addr OffsetBits:16 SizeBits:16] map[Name:name OffsetBits:32 SizeBits:160] map[Name:adapter OffsetBits:192 SizeBits:64] map[Name:dev OffsetBits:256 SizeBits:11776] map[Name:init_irq OffsetBits:12032 SizeBits:32] map[Name:irq OffsetBits:12064 SizeBits:32] map[Name:detected OffsetBits:12096 SizeBits:128] map[Name:slave_cb OffsetBits:12224 SizeBits:64] map[Name:devres_group_id OffsetBits:12288 SizeBits:64] map[Name:debugfs OffsetBits:12352 SizeBits:64]]]

25/2 2026/07/30 12:19 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 31511
							output: 21
							thoughts: 365
						

Thoughts:
**Deconstructing the KASAN Report**

Okay, let's break this down. From the initial clues, it looked like `i2c_client->dev` was the key. We figured that if the `parent` pointer was equal to that device, then we could calculate the address of `i2c_client`. However, that assumption seems wrong.

The KASAN report clarifies things considerably. It tells us the problematic memory address lies within a 4K object located at `ffff8880270b4000`. The error is happening 264 bytes into this object, at address `ffff8880270b4108`. We know the code is accessing `parent->type`, and `type` is at offset 88 in `struct device`. This is useful. This tells us `parent` must be at `ffff8880270b4108 - 88 = ffff8880270b40b0`, which is 176 bytes into this freed 4KB region. The bug is caused by accessing an invalid `parent` pointer and dereferencing the `type` field, which we know is at offset 88 in `struct device`, so `parent` must be the start of `struct device`. So, we're looking for a structure that contains a `struct device` at offset 176. Time to start checking likely suspects of size 4096. My immediate thought is `struct usb_interface`. Let's see if that's the culprit.



26/2 2026/07/30 12:19 tool codesearch-struct-layout
0m Args:
map[Name:usb_interface]

Results:
map[Fields:[map[Name:altsetting OffsetBits:0 SizeBits:64] map[Name:cur_altsetting OffsetBits:64 SizeBits:64] map[Name:num_altsetting OffsetBits:128 SizeBits:32] map[Name:intf_assoc OffsetBits:192 SizeBits:64] map[Name:minor OffsetBits:256 SizeBits:32] map[Name:condition OffsetBits:288 SizeBits:32] map[Name:sysfs_files_created OffsetBits:320 SizeBits:1] map[Name:ep_devs_created OffsetBits:321 SizeBits:1] map[Name:unregistering OffsetBits:322 SizeBits:1] map[Name:needs_remote_wakeup OffsetBits:323 SizeBits:1] map[Name:needs_altsetting0 OffsetBits:324 SizeBits:1] map[Name:needs_binding OffsetBits:325 SizeBits:1] map[Name:resetting_device OffsetBits:326 SizeBits:1] map[Name:authorized OffsetBits:327 SizeBits:1] map[Name:wireless_status OffsetBits:352 SizeBits:32] map[Name:wireless_status_work OffsetBits:384 SizeBits:576] map[Name:dev OffsetBits:960 SizeBits:11776] map[Name:usb_dev OffsetBits:12736 SizeBits:64] map[Name:reset_ws OffsetBits:12800 SizeBits:576]]]

27/2 2026/07/30 12:19 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 32657
							output: 21
							thoughts: 67
						

Thoughts:
**Dissecting the Memory Layout**

Okay, so I'm looking at this memory layout, specifically within this USB interface structure. I see that `usb_interface->dev` sits at an offset of 960 bits, which translates to a clean 120 bytes. Now, I'm trying to figure out the relationship between `usb_interface->dev` and `parent`.  Logically, if `parent` *was* `usb_interface->dev`, it should also be at offset 120, right? But that's not what I'm seeing. `parent` is actually at offset 176. That discrepancy throws a red flag. I need to understand why. This likely points to the way the net device is set up. Time to check the structure definition for `struct net_device` to see what fields are defined within. This should clear up the misalignment.



28/2 2026/07/30 12:19 tool codesearch-struct-layout
0m Args:
map[Name:net_device]

Results:
map[Fields:[map[Name:__cacheline_group_begin__net_device_read_tx OffsetBits:0 SizeBits:0] map[Name: OffsetBits:0 SizeBits:64] map[Name:netdev_ops OffsetBits:64 SizeBits:64] map[Name:header_ops OffsetBits:128 SizeBits:64] map[Name:_tx OffsetBits:192 SizeBits:64] map[Name:gso_partial_features OffsetBits:256 SizeBits:64] map[Name:real_num_tx_queues OffsetBits:320 SizeBits:32] map[Name:gso_max_size OffsetBits:352 SizeBits:32] map[Name:gso_ipv4_max_size OffsetBits:384 SizeBits:32] map[Name:gso_max_segs OffsetBits:416 SizeBits:16] map[Name:num_tc OffsetBits:432 SizeBits:16] map[Name:mtu OffsetBits:448 SizeBits:32] map[Name:needed_headroom OffsetBits:480 SizeBits:16] map[Name:tc_to_txq OffsetBits:496 SizeBits:512] map[Name:xps_maps OffsetBits:1024 SizeBits:128] map[Name:nf_hooks_egress OffsetBits:1152 SizeBits:64] map[Name:tcx_egress OffsetBits:1216 SizeBits:64] map[Name:__cacheline_group_end__net_device_read_tx OffsetBits:1280 SizeBits:0] map[Name:__cacheline_group_begin__net_device_read_txrx OffsetBits:1280 SizeBits:0] map[Name: OffsetBits:1280 SizeBits:64] map[Name:state OffsetBits:1344 SizeBits:64] map[Name:flags OffsetBits:1408 SizeBits:32] map[Name:hard_header_len OffsetBits:1440 SizeBits:16] map[Name:pcpu_stat_type OffsetBits:1456 SizeBits:8] map[Name:features OffsetBits:1472 SizeBits:64] map[Name:ip6_ptr OffsetBits:1536 SizeBits:64] map[Name:__cacheline_group_end__net_device_read_txrx OffsetBits:1600 SizeBits:0] map[Name:__cacheline_group_begin__net_device_read_rx OffsetBits:1600 SizeBits:0] map[Name:xdp_prog OffsetBits:1600 SizeBits:64] map[Name:ptype_specific OffsetBits:1664 SizeBits:128] map[Name:ifindex OffsetBits:1792 SizeBits:32] map[Name:real_num_rx_queues OffsetBits:1824 SizeBits:32] map[Name:_rx OffsetBits:1856 SizeBits:64] map[Name:gro_max_size OffsetBits:1920 SizeBits:32] map[Name:gro_ipv4_max_size OffsetBits:1952 SizeBits:32] map[Name:rx_handler OffsetBits:1984 SizeBits:64] map[Name:rx_handler_data OffsetBits:2048 SizeBits:64] map[Name:nd_net OffsetBits:2112 SizeBits:64] map[Name:npinfo OffsetBits:2176 SizeBits:64] map[Name:tcx_ingress OffsetBits:2240 SizeBits:64] map[Name:__cacheline_group_end__net_device_read_rx OffsetBits:2304 SizeBits:0] map[Name:name OffsetBits:2304 SizeBits:128] map[Name:name_node OffsetBits:2432 SizeBits:64] map[Name:ifalias OffsetBits:2496 SizeBits:64] map[Name:mem_end OffsetBits:2560 SizeBits:64] map[Name:mem_start OffsetBits:2624 SizeBits:64] map[Name:base_addr OffsetBits:2688 SizeBits:64] map[Name:dev_list OffsetBits:2752 SizeBits:128] map[Name:napi_list OffsetBits:2880 SizeBits:128] map[Name:unreg_list OffsetBits:3008 SizeBits:128] map[Name:close_list OffsetBits:3136 SizeBits:128] map[Name:ptype_all OffsetBits:3264 SizeBits:128] map[Name:adj_list OffsetBits:3392 SizeBits:256] map[Name:xdp_features OffsetBits:3648 SizeBits:32] map[Name:xdp_metadata_ops OffsetBits:3712 SizeBits:64] map[Name:xsk_tx_metadata_ops OffsetBits:3776 SizeBits:64] map[Name:gflags OffsetBits:3840 SizeBits:16] map[Name:needed_tailroom OffsetBits:3856 SizeBits:16] map[Name:hw_features OffsetBits:3904 SizeBits:64] map[Name:wanted_features OffsetBits:3968 SizeBits:64] map[Name:vlan_features OffsetBits:4032 SizeBits:64] map[Name:hw_enc_features OffsetBits:4096 SizeBits:64] map[Name:mpls_features OffsetBits:4160 SizeBits:64] map[Name:mangleid_features OffsetBits:4224 SizeBits:64] map[Name:min_mtu OffsetBits:4288 SizeBits:32] map[Name:max_mtu OffsetBits:4320 SizeBits:32] map[Name:type OffsetBits:4352 SizeBits:16] map[Name:min_header_len OffsetBits:4368 SizeBits:8] map[Name:name_assign_type OffsetBits:4376 SizeBits:8] map[Name:group OffsetBits:4384 SizeBits:32] map[Name:stats OffsetBits:4416 SizeBits:1472] map[Name:core_stats OffsetBits:5888 SizeBits:64] map[Name:carrier_up_count OffsetBits:5952 SizeBits:32] map[Name:carrier_down_count OffsetBits:5984 SizeBits:32] map[Name:ethtool_ops OffsetBits:6016 SizeBits:64] map[Name:l3mdev_ops OffsetBits:6080 SizeBits:64] map[Name:ndisc_ops OffsetBits:6144 SizeBits:64] map[Name:xfrmdev_ops OffsetBits:6208 SizeBits:64] map[Name:tlsdev_ops OffsetBits:6272 SizeBits:64] map[Name:operstate OffsetBits:6336 SizeBits:32] map[Name:link_mode OffsetBits:6368 SizeBits:8] map[Name:if_port OffsetBits:6376 SizeBits:8] map[Name:dma OffsetBits:6384 SizeBits:8] map[Name:perm_addr OffsetBits:6392 SizeBits:256] map[Name:addr_assign_type OffsetBits:6648 SizeBits:8] map[Name:addr_len OffsetBits:6656 SizeBits:8] map[Name:upper_level OffsetBits:6664 SizeBits:8] map[Name:lower_level OffsetBits:6672 SizeBits:8] map[Name:threaded OffsetBits:6680 SizeBits:8] map[Name:neigh_priv_len OffsetBits:6688 SizeBits:16] map[Name:dev_id OffsetBits:6704 SizeBits:16] map[Name:dev_port OffsetBits:6720 SizeBits:16] map[Name:irq OffsetBits:6752 SizeBits:32] map[Name:priv_len OffsetBits:6784 SizeBits:32] map[Name:addr_list_lock OffsetBits:6848 SizeBits:1024] map[Name:uc OffsetBits:7872 SizeBits:256] map[Name:mc OffsetBits:8128 SizeBits:256] map[Name:dev_addrs OffsetBits:8384 SizeBits:256] map[Name:queues_kset OffsetBits:8640 SizeBits:64] map[Name:unlink_list OffsetBits:8704 SizeBits:128] map[Name:promiscuity OffsetBits:8832 SizeBits:32] map[Name:allmulti OffsetBits:8864 SizeBits:32] map[Name:uc_promisc OffsetBits:8896 SizeBits:8] map[Name:work_node OffsetBits:8960 SizeBits:128] map[Name:work_tracker OffsetBits:9088 SizeBits:64] map[Name:work_pending OffsetBits:9152 SizeBits:64] map[Name:work_core_pending OffsetBits:9216 SizeBits:64] map[Name:rx_mode_addr_cache OffsetBits:9280 SizeBits:256] map[Name:rx_mode_retry_timer OffsetBits:9536 SizeBits:640] map[Name:rx_mode_retry_count OffsetBits:10176 SizeBits:32] map[Name:nested_level OffsetBits:10208 SizeBits:8] map[Name:ip_ptr OffsetBits:10240 SizeBits:64] map[Name:fib_nh_head OffsetBits:10304 SizeBits:64] map[Name:vlan_info OffsetBits:10368 SizeBits:64] map[Name:dsa_ptr OffsetBits:10432 SizeBits:64] map[Name:tipc_ptr OffsetBits:10496 SizeBits:64] map[Name:ieee80211_ptr OffsetBits:10560 SizeBits:64] map[Name:ieee802154_ptr OffsetBits:10624 SizeBits:64] map[Name:mpls_ptr OffsetBits:10688 SizeBits:64] map[Name:mctp_ptr OffsetBits:10752 SizeBits:64] map[Name:psp_dev OffsetBits:10816 SizeBits:64] map[Name:dev_addr OffsetBits:10880 SizeBits:64] map[Name:num_rx_queues OffsetBits:10944 SizeBits:32] map[Name:xdp_zc_max_segs OffsetBits:10976 SizeBits:32] map[Name:ingress_queue OffsetBits:11008 SizeBits:64] map[Name:nf_hooks_ingress OffsetBits:11072 SizeBits:64] map[Name:broadcast OffsetBits:11136 SizeBits:256] map[Name:rx_cpu_rmap OffsetBits:11392 SizeBits:64] map[Name:index_hlist OffsetBits:11456 SizeBits:128] map[Name:num_tx_queues OffsetBits:11584 SizeBits:32] map[Name:qdisc OffsetBits:11648 SizeBits:64] map[Name:tx_queue_len OffsetBits:11712 SizeBits:32] map[Name:tx_global_lock OffsetBits:11776 SizeBits:1024] map[Name:xdp_bulkq OffsetBits:12800 SizeBits:64] map[Name:qdisc_hash OffsetBits:12864 SizeBits:1024] map[Name:watchdog_timer OffsetBits:13888 SizeBits:640] map[Name:watchdog_timeo OffsetBits:14528 SizeBits:32] map[Name:watchdog_lock OffsetBits:14592 SizeBits:1024] map[Name:watchdog_ref_held OffsetBits:15616 SizeBits:8] map[Name:proto_down_reason OffsetBits:15648 SizeBits:32] map[Name:todo_list OffsetBits:15680 SizeBits:128] map[Name:dev_refcnt OffsetBits:15808 SizeBits:32] map[Name:refcnt_tracker OffsetBits:15872 SizeBits:1472] map[Name:link_watch_list OffsetBits:17344 SizeBits:128] map[Name:reg_state OffsetBits:17472 SizeBits:8] map[Name:dismantle OffsetBits:17480 SizeBits:8] map[Name:moving_ns OffsetBits:17488 SizeBits:8] map[Name:rtnl_link_initializing OffsetBits:17496 SizeBits:8] map[Name:needs_free_netdev OffsetBits:17504 SizeBits:8] map[Name:priv_destructor OffsetBits:17536 SizeBits:64] map[Name:ml_priv OffsetBits:17600 SizeBits:64] map[Name:ml_priv_type OffsetBits:17664 SizeBits:32] map[Name:garp_port OffsetBits:17728 SizeBits:64] map[Name:mrp_port OffsetBits:17792 SizeBits:64] map[Name:dm_private OffsetBits:17856 SizeBits:64] map[Name:dev OffsetBits:17920 SizeBits:11776] map[Name:sysfs_groups OffsetBits:29696 SizeBits:320] map[Name:sysfs_rx_queue_group OffsetBits:30016 SizeBits:64] map[Name:rtnl_link_ops OffsetBits:30080 SizeBits:64] map[Name:stat_ops OffsetBits:30144 SizeBits:64] map[Name:queue_mgmt_ops OffsetBits:30208 SizeBits:64] map[Name:tso_max_size OffsetBits:30272 SizeBits:32] map[Name:tso_max_segs OffsetBits:30304 SizeBits:16] map[Name:dcbnl_ops OffsetBits:30336 SizeBits:64] map[Name:prio_tc_map OffsetBits:30400 SizeBits:128] map[Name:priomap OffsetBits:30528 SizeBits:64] map[Name:link_topo OffsetBits:30592 SizeBits:64] map[Name:phydev OffsetBits:30656 SizeBits:64] map[Name:sfp_bus OffsetBits:30720 SizeBits:64] map[Name:qdisc_tx_busylock OffsetBits:30784 SizeBits:64] map[Name:proto_down OffsetBits:30848 SizeBits:8] map[Name:irq_affinity_auto OffsetBits:30856 SizeBits:8] map[Name:rx_cpu_rmap_auto OffsetBits:30864 SizeBits:8] map[Name:see_all_hwtstamp_requests OffsetBits:30872 SizeBits:1] map[Name:change_proto_down OffsetBits:30873 SizeBits:1] map[Name:netns_immutable OffsetBits:30874 SizeBits:1] map[Name:fcoe_mtu OffsetBits:30875 SizeBits:1] map[Name:net_notifier_list OffsetBits:30912 SizeBits:128] map[Name:macsec_ops OffsetBits:31040 SizeBits:64] map[Name:udp_tunnel_nic_info OffsetBits:31104 SizeBits:64] map[Name:udp_tunnel_nic OffsetBits:31168 SizeBits:64] map[Name:cfg OffsetBits:31232 SizeBits:64] map[Name:cfg_pending OffsetBits:31296 SizeBits:64] map[Name:ethtool OffsetBits:31360 SizeBits:64] map[Name:xdp_state OffsetBits:31424 SizeBits:384] map[Name:dev_addr_shadow OffsetBits:31808 SizeBits:256] map[Name:linkwatch_dev_tracker OffsetBits:32064 SizeBits:64] map[Name:watchdog_dev_tracker OffsetBits:32128 SizeBits:64] map[Name:dev_registered_tracker OffsetBits:32192 SizeBits:64] map[Name:offload_xstats_l3 OffsetBits:32256 SizeBits:64] map[Name:devlink_port OffsetBits:32320 SizeBits:64] map[Name:page_pools OffsetBits:32384 SizeBits:64] map[Name:irq_moder OffsetBits:32448 SizeBits:64] map[Name:max_pacing_offload_horizon OffsetBits:32512 SizeBits:64] map[Name:napi_config OffsetBits:32576 SizeBits:64] map[Name:num_napi_configs OffsetBits:32640 SizeBits:32] map[Name:napi_defer_hard_irqs OffsetBits:32672 SizeBits:32] map[Name:gro_flush_timeout OffsetBits:32704 SizeBits:64] map[Name:up OffsetBits:32768 SizeBits:8] map[Name:request_ops_lock OffsetBits:32776 SizeBits:8] map[Name:lock OffsetBits:32832 SizeBits:1024] map[Name:net_shaper_hierarchy OffsetBits:33856 SizeBits:64] map[Name:neighbours OffsetBits:33920 SizeBits:128] map[Name:hwprov OffsetBits:34048 SizeBits:64] map[Name:priv OffsetBits:34304 SizeBits:0]]]

29/2 2026/07/30 12:19 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 37852
							output: 21
							thoughts: 357
						

Thoughts:
**Deconstructing the KASAN Report**

Okay, let's break this down. KASAN is flagging an issue, and I need to trace the pointer. First, the report says the bug involves accessing `net_device->dev` at offset 2240 bytes. Then I remember we are dealing with `i2c_adapter` and `i2c_adapter->dev` is at offset 304 bytes. But, wait, the crucial part is `parent`. If `parent` is actually `adapter->dev.parent`, then `parent` is a pointer to `struct device`.

Now, the KASAN report specifies the buggy address is `ffff8880270b4108`, which corresponds to `parent->type`. I know from the structure definition that `parent->type` is at offset 88 bytes within `struct device`. Therefore, I can calculate that the `parent` itself is located at address `ffff8880270b40b0`. So, `ffff8880270b40b0` is the actual address of the `parent` device, and crucially it is the value stored in the `adapter->dev.parent` pointer.

The report also indicates that the entire memory region from `ffff8880270b4000` to `ffff8880270b5000` (a 4096-byte region) has been freed. The address of `parent` (`ffff8880270b40b0`) is inside this freed region. This means the `parent` device itself must have been allocated somewhere *within* that 4096-byte block. Now the question is what is the object that has a `struct device` at offset 176? Let me check `struct usb_device`.



30/2 2026/07/30 12:19 tool codesearch-struct-layout
0m Args:
map[Name:usb_device]

Results:
map[Fields:[map[Name:devnum OffsetBits:0 SizeBits:32] map[Name:devpath OffsetBits:32 SizeBits:128] map[Name:route OffsetBits:160 SizeBits:32] map[Name:state OffsetBits:192 SizeBits:32] map[Name:speed OffsetBits:224 SizeBits:32] map[Name:rx_lanes OffsetBits:256 SizeBits:32] map[Name:tx_lanes OffsetBits:288 SizeBits:32] map[Name:ssp_rate OffsetBits:320 SizeBits:32] map[Name:tt OffsetBits:384 SizeBits:64] map[Name:ttport OffsetBits:448 SizeBits:32] map[Name:toggle OffsetBits:480 SizeBits:64] map[Name:parent OffsetBits:576 SizeBits:64] map[Name:bus OffsetBits:640 SizeBits:64] map[Name:ep0 OffsetBits:704 SizeBits:704] map[Name:dev OffsetBits:1408 SizeBits:11776] map[Name:descriptor OffsetBits:13184 SizeBits:144] map[Name:bos OffsetBits:13376 SizeBits:64] map[Name:config OffsetBits:13440 SizeBits:64] map[Name:actconfig OffsetBits:13504 SizeBits:64] map[Name:ep_in OffsetBits:13568 SizeBits:1024] map[Name:ep_out OffsetBits:14592 SizeBits:1024] map[Name:rawdescriptors OffsetBits:15616 SizeBits:64] map[Name:bus_mA OffsetBits:15680 SizeBits:16] map[Name:portnum OffsetBits:15696 SizeBits:8] map[Name:level OffsetBits:15704 SizeBits:8] map[Name:devaddr OffsetBits:15712 SizeBits:8] map[Name:can_submit OffsetBits:15720 SizeBits:1] map[Name:persist_enabled OffsetBits:15721 SizeBits:1] map[Name:reset_in_progress OffsetBits:15722 SizeBits:1] map[Name:have_langid OffsetBits:15723 SizeBits:1] map[Name:authorized OffsetBits:15724 SizeBits:1] map[Name:authenticated OffsetBits:15725 SizeBits:1] map[Name:lpm_capable OffsetBits:15726 SizeBits:1] map[Name:lpm_devinit_allow OffsetBits:15727 SizeBits:1] map[Name:usb2_hw_lpm_capable OffsetBits:15728 SizeBits:1] map[Name:usb2_hw_lpm_besl_capable OffsetBits:15729 SizeBits:1] map[Name:usb2_hw_lpm_enabled OffsetBits:15730 SizeBits:1] map[Name:usb2_hw_lpm_allowed OffsetBits:15731 SizeBits:1] map[Name:usb3_lpm_u1_enabled OffsetBits:15732 SizeBits:1] map[Name:usb3_lpm_u2_enabled OffsetBits:15733 SizeBits:1] map[Name:string_langid OffsetBits:15744 SizeBits:32] map[Name:product OffsetBits:15808 SizeBits:64] map[Name:manufacturer OffsetBits:15872 SizeBits:64] map[Name:serial OffsetBits:15936 SizeBits:64] map[Name:filelist OffsetBits:16000 SizeBits:128] map[Name:maxchild OffsetBits:16128 SizeBits:32] map[Name:quirks OffsetBits:16160 SizeBits:32] map[Name:urbnum OffsetBits:16192 SizeBits:32] map[Name:active_duration OffsetBits:16256 SizeBits:64] map[Name:connect_time OffsetBits:16320 SizeBits:64] map[Name:do_remote_wakeup OffsetBits:16384 SizeBits:1] map[Name:reset_resume OffsetBits:16385 SizeBits:1] map[Name:port_is_suspended OffsetBits:16386 SizeBits:1] map[Name:offload_pm_locked OffsetBits:16387 SizeBits:1] map[Name:offload_usage OffsetBits:16416 SizeBits:32] map[Name:offload_lock OffsetBits:16448 SizeBits:1024] map[Name:tunnel_mode OffsetBits:17472 SizeBits:32] map[Name:usb4_link OffsetBits:17536 SizeBits:64] map[Name:slot_id OffsetBits:17600 SizeBits:32] map[Name:l1_params OffsetBits:17632 SizeBits:64] map[Name:u1_params OffsetBits:17696 SizeBits:128] map[Name:u2_params OffsetBits:17824 SizeBits:128] map[Name:lpm_disable_count OffsetBits:17952 SizeBits:32] map[Name:hub_delay OffsetBits:17984 SizeBits:16] map[Name:use_generic_driver OffsetBits:18000 SizeBits:1]]]

31/2 2026/07/30 12:19 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 40132
							output: 21
							thoughts: 540
						

Thoughts:
**Analyzing a Potential Use-After-Free Vulnerability**

Okay, let's break this down. First, I've got confirmation: `usb_device->dev` is indeed at an offset of 176 bytes. This means the `parent` pointer of something else is referencing it. I quickly deduce that `parent` must be pointing to the `usb_device->dev` member itself. Therefore, the parent device is a `usb_device`, and I've identified the memory region where that `usb_device` was allocated as `[ffff8880270b4000, ffff8880270b5000)`.  The size of the `usb_device` structure is about 2251 bytes, so it fits nicely in a `kmalloc-4k` allocation.

So, the next thing I realize is that the freed object is a `struct usb_device`. Now, the crucial connection: an `i2c_adapter`'s `adapter->dev.parent` is pointing to `&usb_device->dev`. This establishes that the `i2c_adapter` is a child of the `usb_device`. But the real question is how the adapter is being kept alive in spite of the free.

The next thought is to figure out why the `i2c_adapter` continues to be accessed even after the parent `usb_device` is freed. Aha! `/dev/i2c-X`! I see now that `i2cdev_open` is called, and that retrieves the `i2c_adapter` via `i2c_get_adapter`. Then, I remember that `i2c_get_adapter` increments the refcount of `adapter->dev`, not the refcount of the `adapter->dev.parent`!  This seems significant.

Then the key pieces fall into place:  `device_add` *does* increment the parent's refcount. During `i2c_adapter` registration, `device_add(&adapter->dev)` is called, so this must happen. Crucially, `device_add` calls `get_device(dev->parent)`. This means that as long as the `adapter->dev` is registered, the parent's refcount is kept alive.

Then when I think about unregistration: When the `i2c_adapter` is unregistered (e.g., during USB device disconnection), `device_unregister(&adapter->dev)` is called. That call drops the parent's refcount! But, `i2c_get_adapter` is keeping `adapter->dev` alive, even after unregistration. I see that this is a conflict, that I have to think about now:  If the adapter is unregistered, its `dev` is kept alive by `i2c_get_adapter` and so its parent could be freed. But `device_del` *drops* the parent's refcount! So, I need to check `device_del` to confirm all this!



32/2 2026/07/30 12:19 tool codesearch-definition-source
0m Args:
map[Name:device_del]

Results:
map[SourceCode:3902:	/**
3903:	 * device_del - delete device from system.
3904:	 * @dev: device.
3905:	 *
3906:	 * This is the first part of the device unregistration
3907:	 * sequence. This removes the device from the lists we control
3908:	 * from here, has it removed from the other driver model
3909:	 * subsystems it was added to in device_add(), and removes it
3910:	 * from the kobject hierarchy.
3911:	 *
3912:	 * NOTE: this should be called manually _iff_ device_add() was
3913:	 * also called manually.
3914:	 */
3915:	void device_del(struct device *dev)
3916:	{
3917:		struct subsys_private *sp;
3918:		struct device *parent = dev->parent;
3919:		struct kobject *glue_dir = NULL;
3920:		struct class_interface *class_intf;
3921:		unsigned int noio_flag;
3922:	
3923:		device_lock(dev);
3924:		kill_device(dev);
3925:		device_unlock(dev);
3926:	
3927:		if (dev->fwnode && dev->fwnode->dev == dev)
3928:			dev->fwnode->dev = NULL;
3929:	
3930:		/* Notify clients of device removal.  This call must come
3931:		 * before dpm_sysfs_remove().
3932:		 */
3933:		noio_flag = memalloc_noio_save();
3934:		bus_notify(dev, BUS_NOTIFY_DEL_DEVICE);
3935:	
3936:		dpm_sysfs_remove(dev);
3937:		if (parent)
3938:			klist_del(&dev->p->knode_parent);
3939:		if (MAJOR(dev->devt)) {
3940:			devtmpfs_delete_node(dev);
3941:			device_remove_sys_dev_entry(dev);
3942:			device_remove_file(dev, &dev_attr_dev);
3943:		}
3944:	
3945:		sp = class_to_subsys(dev->class);
3946:		if (sp) {
3947:			device_remove_class_symlinks(dev);
3948:	
3949:			mutex_lock(&sp->mutex);
3950:			/* notify any interfaces that the device is now gone */
3951:			list_for_each_entry(class_intf, &sp->interfaces, node)
3952:				if (class_intf->remove_dev)
3953:					class_intf->remove_dev(dev);
3954:			/* remove the device from the class list */
3955:			klist_del(&dev->p->knode_class);
3956:			mutex_unlock(&sp->mutex);
3957:			subsys_put(sp);
3958:		}
3959:		device_remove_file(dev, &dev_attr_uevent);
3960:		device_remove_attrs(dev);
3961:		bus_remove_device(dev);
3962:		device_pm_remove(dev);
3963:		driver_deferred_probe_del(dev);
3964:		device_platform_notify_remove(dev);
3965:		device_links_purge(dev);
3966:	
3967:		/*
3968:		 * If a device does not have a driver attached, we need to clean
3969:		 * up any managed resources. We do this in device_release(), but
3970:		 * it's never called (and we leak the device) if a managed
3971:		 * resource holds a reference to the device. So release all
3972:		 * managed resources here, like we do in driver_detach(). We
3973:		 * still need to do so again in device_release() in case someone
3974:		 * adds a new resource after this point, though.
3975:		 */
3976:		devres_release_all(dev);
3977:	
3978:		bus_notify(dev, BUS_NOTIFY_REMOVED_DEVICE);
3979:		kobject_uevent(&dev->kobj, KOBJ_REMOVE);
3980:		glue_dir = get_glue_dir(dev);
3981:		kobject_del(&dev->kobj);
3982:		cleanup_glue_dir(dev, glue_dir);
3983:		memalloc_noio_restore(noio_flag);
3984:		put_device(parent);
3985:	}
 SourceFile:drivers/base/core.c]

33/2 2026/07/30 12:19 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 42684
							output: 31
							thoughts: 478
						

Thoughts:
**Use-After-Free Vulnerability in I2C Adapter Handling**

Okay, so here's what I've figured out. `device_del` calls `put_device(parent)`. That's the key. If an `i2c_adapter` is unregistered – say, the USB device it's attached to is disconnected – then `device_del(&adapter->dev)` gets called. This *should* decrement the reference count of the adapter's parent, which in this case is a `usb_device`. And if that `usb_device` was only being held by this reference, boom, it's freed. No surprises there.

But here's the kicker: `i2c_get_adapter` *holds* a reference to the `adapter->dev`, so the `i2c_adapter` itself doesn't get freed. Makes sense.

Then, here's where it all goes sideways. An `i2cdev_ioctl_smbus` call eventually leads to `i2c_adapter_depth`. And guess what `i2c_adapter_depth` does? It accesses `adapter->dev.parent->type`. But *that* `adapter->dev.parent` is now pointing to freed memory, the previously freed `usb_device`! It's a textbook use-after-free, plain and simple.

The real problem seems to be the assumption that the `adapter->dev.parent` will remain valid after `device_del` is called. It *traverses* that pointer. I see. Accessing `adapter->dev.parent` after `device_del` is not safe, and the `dev->parent` pointer is not set to NULL upon deletion, it just gets left pointing at the freed memory.

So, how can we trigger this? Here's my reproduction plan:

1.  We need a USB device that registers an I2C adapter.
2.  Then, open the corresponding `/dev/i2c-X` device file.
3.  Unplug the USB device. This'll trigger the unregistration of the I2C adapter and the freeing of the `usb_device`.
4.  Finally, call the `I2C_SMBUS` ioctl on that open file descriptor.
5.  This ioctl should execute `i2c_adapter_depth` and trigger the use-after-free.

Now I need to find which USB driver is registering these I2C adapters... time to search the source!



34/2 2026/07/30 12:19 tool grepper
0m Error:
log-in to see details

Args:
map[Expression:i2c_add_adapter PathPrefix:drivers/usb/]

Results:
map[Output:]

35/2 2026/07/30 12:19 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 43747
							output: 33
							thoughts: 31
						

Thoughts:
Here's my attempt at summarizing that thought process, tailored for an expert audience:

**Considering the I2C Adapter Addition**

Okay, so I'm thinking about how an I2C adapter is actually integrated, and I'm realizing `i2c_add_adapter` isn't necessarily the only entry point. There's a decent chance that it could be called indirectly through some abstraction layer or wrapper function. I'm wondering if there are any other possible paths to consider, like a function such as `i2c_bit_add_bus` might be involved instead. I'll need to remember that when I'm assessing the entire integration path, there might be some less obvious places where the adapter initialization happens, perhaps hidden within some higher-level abstraction. I need to keep that in mind when I dig through the code.



36/2 2026/07/30 12:19 tool grepper
0m Error:
log-in to see details

Args:
map[Expression:i2c_.*add_.*adapter PathPrefix:drivers/usb/]

Results:
map[Output:]

37/2 2026/07/30 12:19 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 44003
							output: 30
							thoughts: 19
						

Thoughts:
Okay, here's my summarized thought process, presented as if I were thinking it:

**Digging into the USB Driver Landscape**

Alright, time to get my hands dirty. I need to find the relevant USB driver code for I2C adapters. First, a targeted approach is the best way to start, so let's use a straightforward search. Let's see, the driver is likely within the `drivers/usb/` directory. That's the logical starting point. Now, to zero in on the I2C part, I need to look for `i2c_adapter` within that USB directory. That should lead me to the USB driver files dealing with I2C devices. From there, I can analyze the driver's implementation. Let's see what we come up with.



38/2 2026/07/30 12:19 tool grepper
0m Args:
map[Expression:struct i2c_adapter PathPrefix:drivers/usb/]

Results:
map[Output:drivers/usb/misc/usb251xb.c=243=static int usb251x_check_gpio_chip(struct usb251xb *hub)
--
drivers/usb/misc/usb251xb.c-245-	struct gpio_chip *gc = gpiod_to_chip(hub->gpio_reset);
drivers/usb/misc/usb251xb.c:246:	struct i2c_adapter *adap;
drivers/usb/misc/usb251xb.c-247-	int ret;
--
drivers/usb/typec/tcpm/fusb302.c=1689=static int fusb302_probe(struct i2c_client *client)
--
drivers/usb/typec/tcpm/fusb302.c-1691-	struct fusb302_chip *chip;
drivers/usb/typec/tcpm/fusb302.c:1692:	struct i2c_adapter *adapter = client->adapter;
drivers/usb/typec/tcpm/fusb302.c-1693-	struct auxiliary_device *bridge_dev;
--
drivers/usb/typec/ucsi/ucsi_ccg.c=238=static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
--
drivers/usb/typec/ucsi/ucsi_ccg.c-240-	struct i2c_client *client = uc->client;
drivers/usb/typec/ucsi/ucsi_ccg.c:241:	const struct i2c_adapter_quirks *quirks = client->adapter->quirks;
drivers/usb/typec/ucsi/ucsi_ccg.c-242-	unsigned char buf[2];
]

39/2 2026/07/30 12:19 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 44696
							output: 33
							thoughts: 34
						

Thoughts:
Here's my summary, as the thought process of a media expert:

**Investigating the I2C Adapter Registration**

Okay, hold on a second. That `i2c_adapter`... I recall seeing it registered by something within the USB media driver space. That's unusual, but my intuition says that's where I need to look. Alright, time to dive into `drivers/media/usb/`. Let's see what's happening in there. I'm going to carefully review the code base in that specific area to understand this, and the context of that I2C adapter registration. I'll need to remember all the various USB devices and interfaces that have I2C dependencies and look to how the registration process is implemented.



40/2 2026/07/30 12:20 tool grepper
0m Args:
map[Expression:i2c_add_adapter PathPrefix:drivers/media/usb/]

Results:
map[Output:drivers/media/usb/au0828/au0828-i2c.c=354=int au0828_i2c_register(struct au0828_dev *dev)
--
drivers/media/usb/au0828/au0828-i2c.c-373-#endif
drivers/media/usb/au0828/au0828-i2c.c:374:	i2c_add_adapter(&dev->i2c_adap);
drivers/media/usb/au0828/au0828-i2c.c-375-
--
drivers/media/usb/cx231xx/cx231xx-i2c.c=514=int cx231xx_i2c_register(struct cx231xx_i2c *bus)
--
drivers/media/usb/cx231xx/cx231xx-i2c.c-527-	i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
drivers/media/usb/cx231xx/cx231xx-i2c.c:528:	bus->i2c_rc = i2c_add_adapter(&bus->i2c_adap);
drivers/media/usb/cx231xx/cx231xx-i2c.c-529-
--
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c=56=static int dvb_usbv2_i2c_init(struct dvb_usb_device *d)
--
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c-68-
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c:69:	ret = i2c_add_adapter(&d->i2c_adap);
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c-70-	if (ret < 0) {
--
drivers/media/usb/dvb-usb/dvb-usb-i2c.c=11=int dvb_usb_i2c_init(struct dvb_usb_device *d)
--
drivers/media/usb/dvb-usb/dvb-usb-i2c.c-30-
drivers/media/usb/dvb-usb/dvb-usb-i2c.c:31:	ret = i2c_add_adapter(&d->i2c_adap);
drivers/media/usb/dvb-usb/dvb-usb-i2c.c-32-	if (ret < 0) {
--
drivers/media/usb/em28xx/em28xx-i2c.c=970=int em28xx_i2c_register(struct em28xx *dev, unsigned int bus,
--
drivers/media/usb/em28xx/em28xx-i2c.c-991-
drivers/media/usb/em28xx/em28xx-i2c.c:992:	retval = i2c_add_adapter(&dev->i2c_adap[bus]);
drivers/media/usb/em28xx/em28xx-i2c.c-993-	if (retval < 0) {
drivers/media/usb/em28xx/em28xx-i2c.c-994-		dev_err(&dev->intf->dev,
drivers/media/usb/em28xx/em28xx-i2c.c:995:			"%s: i2c_add_adapter failed! retval [%d]\n",
drivers/media/usb/em28xx/em28xx-i2c.c-996-			__func__, retval);
--
drivers/media/usb/go7007/go7007-i2c.c=204=int go7007_i2c_init(struct go7007 *go)
--
drivers/media/usb/go7007/go7007-i2c.c-209-	i2c_set_adapdata(&go->i2c_adapter, go);
drivers/media/usb/go7007/go7007-i2c.c:210:	if (i2c_add_adapter(&go->i2c_adapter) < 0) {
drivers/media/usb/go7007/go7007-i2c.c-211-		dev_err(go->dev,
drivers/media/usb/go7007/go7007-i2c.c:212:			"go7007-i2c: error: i2c_add_adapter failed\n");
drivers/media/usb/go7007/go7007-i2c.c-213-		return -1;
--
drivers/media/usb/go7007/go7007-usb.c=1040=static int go7007_usb_probe(struct usb_interface *intf,
--
drivers/media/usb/go7007/go7007-usb.c-1171-		i2c_set_adapdata(&go->i2c_adapter, go);
drivers/media/usb/go7007/go7007-usb.c:1172:		if (i2c_add_adapter(&go->i2c_adapter) < 0) {
drivers/media/usb/go7007/go7007-usb.c:1173:			dev_err(go->dev, "error: i2c_add_adapter failed\n");
drivers/media/usb/go7007/go7007-usb.c-1174-			goto allocfail;
--
drivers/media/usb/hdpvr/hdpvr-i2c.c=180=int hdpvr_register_i2c_adapter(struct hdpvr_device *dev)
--
drivers/media/usb/hdpvr/hdpvr-i2c.c-188-
drivers/media/usb/hdpvr/hdpvr-i2c.c:189:	return i2c_add_adapter(&dev->i2c_adapter);
drivers/media/usb/hdpvr/hdpvr-i2c.c-190-}
--
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c=591=void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
--
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c-627-	i2c_set_adapdata(&hdw->i2c_adap, &hdw->v4l2_dev);
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c:628:	i2c_add_adapter(&hdw->i2c_adap);
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c-629-	if (hdw->i2c_func[0x18] == i2c_24xxx_ir) {
--
drivers/media/usb/stk1160/stk1160-i2c.c=247=int stk1160_i2c_register(struct stk1160 *dev)
--
drivers/media/usb/stk1160/stk1160-i2c.c-257-
drivers/media/usb/stk1160/stk1160-i2c.c:258:	rc = i2c_add_adapter(&dev->i2c_adap);
drivers/media/usb/stk1160/stk1160-i2c.c-259-	if (rc < 0) {
--
drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c=1597=static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
--
drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c-1655-
drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c:1656:	result = i2c_add_adapter(&ttusb->i2c_adap);
drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c-1657-	if (result)
]

41/2 2026/07/30 12:20 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 47124
							output: 24
							thoughts: 37
						

Thoughts:
**Analyzing the KASAN Report and Object Allocation**

Okay, so the KASAN report is highlighting an issue involving a freed object. The report explicitly mentions this object was allocated via `kmalloc-4k`. Right, that's the key starting point. Now, I need to understand the context of this allocation. What's likely to be allocated with `kmalloc-4k` in this section of the code? I'm going to quickly check the size of `struct dvb_usb_device`. Knowing its size will help confirm or deny this suspicion, since the issue relates to a `kmalloc-4k` object. Is there any way this data structure relates to the freed memory?



42/2 2026/07/30 12:20 tool codesearch-struct-layout
0m Args:
map[Name:dvb_usb_device]

Results:
map[Fields:[map[Name:props OffsetBits:0 SizeBits:29760] map[Name:desc OffsetBits:29760 SizeBits:64] map[Name:udev OffsetBits:29824 SizeBits:64] map[Name:state OffsetBits:29888 SizeBits:32] map[Name:powered OffsetBits:29920 SizeBits:32] map[Name:data_mutex OffsetBits:29952 SizeBits:1024] map[Name:usb_mutex OffsetBits:30976 SizeBits:1024] map[Name:i2c_mutex OffsetBits:32000 SizeBits:1024] map[Name:i2c_adap OffsetBits:33024 SizeBits:17024] map[Name:num_adapters_initialized OffsetBits:50048 SizeBits:32] map[Name:adapter OffsetBits:50112 SizeBits:67840] map[Name:rc_dev OffsetBits:117952 SizeBits:64] map[Name:input_dev OffsetBits:118016 SizeBits:64] map[Name:rc_phys OffsetBits:118080 SizeBits:512] map[Name:rc_query_work OffsetBits:118592 SizeBits:1344] map[Name:last_event OffsetBits:119936 SizeBits:32] map[Name:last_state OffsetBits:119968 SizeBits:32] map[Name:owner OffsetBits:120000 SizeBits:64] map[Name:priv OffsetBits:120064 SizeBits:64]]]

43/2 2026/07/30 12:20 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 47798
							output: 23
							thoughts: 158
						

Thoughts:
**Analyzing a Potential Memory Management Issue**

Okay, let's break this down. First, I see that this `dvb_usb_device` structure is fairly large – 15016 bytes, allocated from `kmalloc-16k`, which makes sense given the size. Then, the observation that the freed object is a `struct usb_device` immediately triggers a flag. I know the size of a `struct usb_device` – 2251 bytes, I've checked that before. Now, I recall that `usb_device->dev` resides at offset 176 bytes. Aha! This is interesting; because I can see that `parent` is also at offset 176 bytes, in the freed object! So it seems that the freed object *is* the `struct usb_device` itself. Now, this further suggests the device is being allocated via `usb_alloc_dev` which I would expect.



44/2 2026/07/30 12:20 tool codesearch-definition-source
0m Args:
map[Name:usb_alloc_dev]

Results:
map[SourceCode: 628:	/**
 629:	 * usb_alloc_dev - usb device constructor (usbcore-internal)
 630:	 * @parent: hub to which device is connected; null to allocate a root hub
 631:	 * @bus: bus used to access the device
 632:	 * @port1: one-based index of port; ignored for root hubs
 633:	 *
 634:	 * Context: task context, might sleep.
 635:	 *
 636:	 * Only hub drivers (including virtual root hub drivers for host
 637:	 * controllers) should ever call this.
 638:	 *
 639:	 * This call may not be used in a non-sleeping context.
 640:	 *
 641:	 * Return: On success, a pointer to the allocated usb device. %NULL on
 642:	 * failure.
 643:	 */
 644:	struct usb_device *usb_alloc_dev(struct usb_device *parent,
 645:					 struct usb_bus *bus, unsigned port1)
 646:	{
 647:		struct usb_device *dev;
 648:		struct usb_hcd *usb_hcd = bus_to_hcd(bus);
 649:		unsigned raw_port = port1;
 650:	
 651:		dev = kzalloc_obj(*dev);
 652:		if (!dev)
 653:			return NULL;
 654:	
 655:		if (!usb_get_hcd(usb_hcd)) {
 656:			kfree(dev);
 657:			return NULL;
 658:		}
 659:		/* Root hubs aren't true devices, so don't allocate HCD resources */
 660:		if (usb_hcd->driver->alloc_dev && parent &&
 661:			!usb_hcd->driver->alloc_dev(usb_hcd, dev)) {
 662:			usb_put_hcd(bus_to_hcd(bus));
 663:			kfree(dev);
 664:			return NULL;
 665:		}
 666:	
 667:		device_initialize(&dev->dev);
 668:		dev->dev.bus = &usb_bus_type;
 669:		dev->dev.type = &usb_device_type;
 670:		dev->dev.groups = usb_device_groups;
 671:		set_dev_node(&dev->dev, dev_to_node(bus->sysdev));
 672:		dev->state = USB_STATE_ATTACHED;
 673:		dev->lpm_disable_count = 1;
 674:		spin_lock_init(&dev->offload_lock);
 675:		dev->offload_usage = 0;
 676:		atomic_set(&dev->urbnum, 0);
 677:	
 678:		INIT_LIST_HEAD(&dev->ep0.urb_list);
 679:		dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
 680:		dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
 681:		/* ep0 maxpacket comes later, from device descriptor */
 682:		usb_enable_endpoint(dev, &dev->ep0, false);
 683:		dev->can_submit = 1;
 684:	
 685:		/* Save readable and stable topology id, distinguishing devices
 686:		 * by location for diagnostics, tools, driver model, etc.  The
 687:		 * string is a path along hub ports, from the root.  Each device's
 688:		 * dev->devpath will be stable until USB is re-cabled, and hubs
 689:		 * are often labeled with these port numbers.  The name isn't
 690:		 * as stable:  bus->busnum changes easily from modprobe order,
 691:		 * cardbus or pci hotplugging, and so on.
 692:		 */
 693:		if (unlikely(!parent)) {
 694:			dev->devpath[0] = '0';
 695:			dev->route = 0;
 696:	
 697:			dev->dev.parent = bus->controller;
 698:			device_set_of_node_from_dev(&dev->dev, bus->sysdev);
 699:			dev_set_name(&dev->dev, "usb%d", bus->busnum);
 700:		} else {
 701:			int n;
 702:	
 703:			/* match any labeling on the hubs; it's one-based */
 704:			if (parent->devpath[0] == '0') {
 705:				n = snprintf(dev->devpath, sizeof(dev->devpath), "%d", port1);
 706:				/* Root ports are not counted in route string */
 707:				dev->route = 0;
 708:			} else {
 709:				n = snprintf(dev->devpath, sizeof(dev->devpath), "%s.%d",
 710:					     parent->devpath, port1);
 711:				/* Route string assumes hubs have less than 16 ports */
 712:				if (port1 < 15)
 713:					dev->route = parent->route +
 714:						(port1 << ((parent->level - 1)*4));
 715:				else
 716:					dev->route = parent->route +
 717:						(15 << ((parent->level - 1)*4));
 718:			}
 719:			if (n >= sizeof(dev->devpath)) {
 720:				usb_put_hcd(bus_to_hcd(bus));
 721:				usb_put_dev(dev);
 722:				return NULL;
 723:			}
 724:	
 725:			dev->dev.parent = &parent->dev;
 726:			dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath);
 727:	
 728:			if (!parent->parent) {
 729:				/* device under root hub's port */
 730:				raw_port = usb_hcd_find_raw_port_number(usb_hcd,
 731:					port1);
 732:			}
 733:			dev->dev.of_node = usb_of_get_device_node(parent, raw_port);
 734:	
 735:			/* hub driver sets up TT records */
 736:		}
 737:	
 738:		dev->portnum = port1;
 739:		dev->bus = bus;
 740:		dev->parent = parent;
 741:		INIT_LIST_HEAD(&dev->filelist);
 742:	
 743:	#ifdef	CONFIG_PM
 744:		pm_runtime_set_autosuspend_delay(&dev->dev,
 745:				usb_autosuspend_delay * 1000);
 746:		dev->connect_time = jiffies;
 747:		dev->active_duration = -jiffies;
 748:	#endif
 749:	
 750:		dev->authorized = usb_dev_authorized(dev, usb_hcd);
 751:		trace_usb_alloc_dev(dev);
 752:		return dev;
 753:	}
 SourceFile:drivers/usb/core/usb.c]

45/2 2026/07/30 12:20 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 50252
							output: 36
							thoughts: 458
						

Thoughts:
**Analyzing the KASAN Report and USB/I2C Device Relationships**

Okay, let's break this down. The KASAN report is definitely pointing at an issue involving a `struct usb_device` object freed from `kmalloc-4k`. That makes sense; `usb_alloc_dev` uses `kzalloc_obj`, and a `usb_device` is 2251 bytes, fitting neatly into that 4k slab. So far, so good.

Now, the interesting part: the suspicion that an `i2c_adapter` is somehow getting registered with the `usb_device` as its parent. That's immediately a red flag. Typically, in the USB subsystem, the `usb_device` is the parent of the `usb_interface`, and drivers bind to the *interface* not the device itself. Consequently, the `i2c_adapter`'s parent *should* be `usb_interface->dev`, right? `usb_interface` is allocated via `kzalloc_obj` in functions like `usb_ifnum_to_if` or `usb_set_configuration`, and its size of 1672 bytes would put it in `kmalloc-2k`.

But the KASAN report says the freed object is in `kmalloc-4k`, strongly suggesting we're dealing with the `usb_device` itself. The offset of the `parent` pointer (176 bytes) *within* the reported object confirms that the `parent` *cannot* be the `usb_interface`. Its `dev` member is at offset 120, so `usb_interface` is *not* the parent. It has to be `usb_device`. That is the crux of the issue.

So, how is this happening? Are there any I2C adapters *actually* registered directly with a `usb_device` as the parent? Let's check the code: Specifically, let's search for calls to `i2c_add_adapter` where `adapter->dev.parent` is directly set to `usb_device->dev`. It's possible an I2C adapter is registered by a driver that *does* bind to the `usb_device` instead of an interface. Granted, that's unusual – `usb_generic_driver` is an example of a `usb_device` driver, but it doesn't usually register I2C adapters, as far as I know.

Time to search through `drivers/media/usb/` and `drivers/usb/` for instances where `dev.parent = &usb_dev->dev` or a similar pattern is being used. That should shed some light on this, and hopefully explain the KASAN report.



46/2 2026/07/30 12:20 tool grepper
0m Args:
map[Expression:\.dev\.parent = .*&.*->dev PathPrefix:drivers/media/usb/]

Results:
map[Output:drivers/media/usb/au0828/au0828-i2c.c=354=int au0828_i2c_register(struct au0828_dev *dev)
--
drivers/media/usb/au0828/au0828-i2c.c-361-
drivers/media/usb/au0828/au0828-i2c.c:362:	dev->i2c_adap.dev.parent = &dev->usbdev->dev;
drivers/media/usb/au0828/au0828-i2c.c-363-
--
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c=56=static int dvb_usbv2_i2c_init(struct dvb_usb_device *d)
--
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c-65-	d->i2c_adap.algo = d->props->i2c_algo;
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c:66:	d->i2c_adap.dev.parent = &d->udev->dev;
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c-67-	i2c_set_adapdata(&d->i2c_adap, d);
--
drivers/media/usb/dvb-usb/dvb-usb-i2c.c=11=int dvb_usb_i2c_init(struct dvb_usb_device *d)
--
drivers/media/usb/dvb-usb/dvb-usb-i2c.c-26-	d->i2c_adap.algo_data = NULL;
drivers/media/usb/dvb-usb/dvb-usb-i2c.c:27:	d->i2c_adap.dev.parent = &d->udev->dev;
drivers/media/usb/dvb-usb/dvb-usb-i2c.c-28-
--
drivers/media/usb/em28xx/em28xx-i2c.c=970=int em28xx_i2c_register(struct em28xx *dev, unsigned int bus,
--
drivers/media/usb/em28xx/em28xx-i2c.c-982-	dev->i2c_adap[bus] = em28xx_adap_template;
drivers/media/usb/em28xx/em28xx-i2c.c:983:	dev->i2c_adap[bus].dev.parent = &dev->intf->dev;
drivers/media/usb/em28xx/em28xx-i2c.c-984-	strscpy(dev->i2c_adap[bus].name, dev_name(&dev->intf->dev),
--
drivers/media/usb/hdpvr/hdpvr-i2c.c=180=int hdpvr_register_i2c_adapter(struct hdpvr_device *dev)
--
drivers/media/usb/hdpvr/hdpvr-i2c.c-184-	dev->i2c_adapter = hdpvr_i2c_adapter_template;
drivers/media/usb/hdpvr/hdpvr-i2c.c:185:	dev->i2c_adapter.dev.parent = &dev->udev->dev;
drivers/media/usb/hdpvr/hdpvr-i2c.c-186-
--
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c=591=void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
--
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c-622-	strscpy(hdw->i2c_adap.name, hdw->name, sizeof(hdw->i2c_adap.name));
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c:623:	hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev;
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c-624-	hdw->i2c_adap.algo = &hdw->i2c_algo;
]

47/2 2026/07/30 12:20 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 52470
							output: 26
							thoughts: 381
						

Thoughts:
**Analyzing I2C Adapter Parent References in USB Drivers**

Okay, let's break this down. It seems a pattern is emerging with these USB drivers. I'm seeing that drivers like `dvb_usb_device`, `au0828`, `hdpvr`, and `pvrusb2` are all setting the `i2c_adap.dev.parent` field to the `usb_device->dev` structure. That's the key connection.

Now, the interesting part is what happens during disconnect. The driver's `disconnect` function gets called when the USB device is removed, which makes sense. Then the driver unregisters the I2C adapter, using functions like `i2c_del_adapter`. This is where it gets critical. `i2c_del_adapter` calls `device_unregister(&adap->dev)`. This should *drop* the reference that `adap->dev.parent` (which, again, points to the USB device's `dev` structure) has to its parent. Crucially, the USB device is then freed.

However, if an application still has the I2C adapter open via a `/dev/i2c-X` device node, `i2c_get_adapter` *holds* a reference to `adap->dev`. That means the `i2c_adapter` itself *isn't* automatically freed because the system thinks something is still using it.

But...wait a second. If the `i2c_adapter` struct is embedded *within* the driver's private struct (like `struct dvb_usb_device` or something similar), and the driver then frees *that* struct during the `disconnect` process, the `i2c_adapter` would get freed along with everything else! That's the likely scenario.

So, I need to check how `dvb_usb_device` handles this. The question is, does it free its private struct in `disconnect`, including the embedded `i2c_adapter`? I need to verify that.



48/2 2026/07/30 12:20 tool codesearch-definition-source
0m Args:
map[Name:dvb_usb_device_exit]

Results:
map[SourceCode: 329:	void dvb_usb_device_exit(struct usb_interface *intf)
 330:	{
 331:		struct dvb_usb_device *d = usb_get_intfdata(intf);
 332:		const char *default_name = "generic DVB-USB module";
 333:		char name[40];
 334:	
 335:		usb_set_intfdata(intf, NULL);
 336:		if (d != NULL && d->desc != NULL) {
 337:			strscpy(name, d->desc->name, sizeof(name));
 338:			dvb_usb_exit(d);
 339:		} else {
 340:			strscpy(name, default_name, sizeof(name));
 341:		}
 342:		info("%s successfully deinitialized and disconnected.", name);
 343:	
 344:	}
 SourceFile:drivers/media/usb/dvb-usb/dvb-usb-init.c]

49/2 2026/07/30 12:20 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 53611
							output: 24
							thoughts: 12
						

Thoughts:
Here's my attempt at summarizing the thought process, tailored for an expert audience:

**Examining the `dvb_usb_exit` Function**

Okay, so I'm thinking about the DVB USB driver framework, and the crucial `dvb_usb_exit` function in particular. My mind immediately jumps to that function as the cleanup and teardown point. I need to make sure I understand its execution path and all its implications. I'm focusing on ensuring it handles resources correctly, avoids memory leaks, and doesn't leave the system in an unstable state. My checklist in my head includes things like: are the USB endpoints properly de-registered? Is the associated DVB device freed, and is it done in the correct order to avoid race conditions with other modules? I'm visualizing the code flow now - where are the critical mutexes, what locks are held, what dependencies exist on the driver's state. I need to be sure any allocated buffers are freed, DMA mappings are unmapped if used, and the USB device itself is properly detached. Let's dig in and review `dvb_usb_exit` with a critical eye, checking for the usual suspects: potential double-frees, incorrect resource release order, and thread-safety issues. Gotta make sure it's robust and handles all the edge cases.



50/2 2026/07/30 12:20 tool codesearch-definition-source
0m Args:
map[Name:dvb_usb_exit]

Results:
map[SourceCode: 138:	/* general initialization functions */
 139:	static int dvb_usb_exit(struct dvb_usb_device *d)
 140:	{
 141:		deb_info("state before exiting everything: %x\n", d->state);
 142:		dvb_usb_remote_exit(d);
 143:		dvb_usb_adapter_exit(d);
 144:		dvb_usb_i2c_exit(d);
 145:		deb_info("state should be zero now: %x\n", d->state);
 146:		d->state = DVB_USB_STATE_INIT;
 147:	
 148:		if (d->priv != NULL && d->props.priv_destroy != NULL)
 149:			d->props.priv_destroy(d);
 150:	
 151:		kfree(d->priv);
 152:		kfree(d);
 153:		return 0;
 154:	}
 SourceFile:drivers/media/usb/dvb-usb/dvb-usb-init.c]

51/2 2026/07/30 12:20 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 54241
							output: 31
							thoughts: 1689
						

Thoughts:
**Analyzing a Use-After-Free Vulnerability**

Okay, so here's what's running through my head. We have a Use-After-Free (UAF) situation, and I'm trying to pinpoint the root cause. My initial thought was that `dvb_usb_exit` might be the culprit, freeing a structure (`d`) that includes an I2C adapter (`d->i2c_adap`), leading to a UAF when the adapter is still referenced. But the KASAN report throws a curveball: the UAF isn't on `dvb_usb_device` itself, but on `usb_device`. That's strange.

First, I need to understand this discrepancy. If the device's main struct `d` is freed, its internal `i2c_adap` should *also* be freed, so the fact that we're getting a report on the USB device itself feels strange. The KASAN report shows the buggy address is 264 bytes inside a 4096-byte region, but `usb_device` is 2251 bytes, within a `kmalloc-4k` region, not a `kmalloc-16k` region which makes no sense. The original UAF hypothesis doesn't seem to hold because the structure is not big enough.

So, let's trace the allocation. The KASAN report's stack trace points to `drivers/usb/mon/mon_main.c` and specifically to the allocation of a USB device. But then I realize: this stack trace is *for the page* allocation, not the object itself. It's the SLAB PAGE that's being described. The *object* was allocated by `nsim_dev_trap_skb_build` as `skb->head`.

This clicks. The KASAN report is showing the *last* allocation and free of that memory, which, in this case, is `skb->head` allocated and freed by `netdevsim`. The initial allocation of `usb_device` is lost from the KASAN report because it only keeps the last alloc/free. The memory was reused.

Now, if `usb_device` was allocated and freed, and then reallocated as `skb->head`, it's not clear where the original problem occurred. I need to understand the relationship between the `usb_device` and the `skb->head`.

Let's do some math: If the `usb_device` was allocated at `ffff8880270b4000`, the `usb_device->dev` is at offset 176. The `parent` pointer points to `ffff8880270b40b0`. It makes perfect sense! So the same memory was reallocated as `skb->head`!

Here's the likely scenario:

1.  A USB device is created.
2.  A driver binds to it and registers an I2C adapter with `adapter->dev.parent = &usb_device->dev`. This is where the initial relationship is established.
3.  The I2C adapter is opened via `/dev/i2c-X`.
4.  The USB device is disconnected.
5.  The driver unregisters the I2C adapter.
6.  *Crucially, the driver is freeing its private structure.*

Here's where it gets interesting and I need to verify assumptions. If the driver frees its private struct (let's call it `d` again), the I2C adapter `i2c_adapter` within it should be freed! But if that happens, there would be a UAF when `i2c_adapter_lock_bus` accesses `adapter->bus_lock`.

Wait a second: if `i2c_adapter` *is* freed, then a KASAN report would be triggered on the access of the `i2c_adapter->bus_lock` field. The KASAN report, however, says the UAF is on `parent->type`, which is *inside* `usb_device` which is `i2c_adapter->dev.parent->type`! This means `i2c_adapter` itself IS NOT FREED! This also means the memory is *not* reallocated as `skb->head`.

So, how can `i2c_adapter` not be freed? Either it's dynamically allocated separately, or, more likely, the driver uses something like `devm_kzalloc`, tying the I2C adapter's lifetime to `usb_interface->dev`. So when the `usb_interface` is destroyed, the I2C adapter goes with it. The `usb_device` is


52/2 2026/07/30 12:20 tool grepper
0m Args:
map[Expression:i2c_adapter PathPrefix:drivers/media/usb/]

Results:
map[Output:
Full output is too long, showing 500 out of 1286 lines.
Use more precise expression if possible.

drivers/media/usb/au0828/au0828-i2c.c=21=MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
--
drivers/media/usb/au0828/au0828-i2c.c-25-
drivers/media/usb/au0828/au0828-i2c.c:26:static inline int i2c_slave_did_read_ack(struct i2c_adapter *i2c_adap)
drivers/media/usb/au0828/au0828-i2c.c-27-{
--
drivers/media/usb/au0828/au0828-i2c.c-32-
drivers/media/usb/au0828/au0828-i2c.c:33:static int i2c_wait_read_ack(struct i2c_adapter *i2c_adap)
drivers/media/usb/au0828/au0828-i2c.c-34-{
--
drivers/media/usb/au0828/au0828-i2c.c-48-
drivers/media/usb/au0828/au0828-i2c.c:49:static inline int i2c_is_read_busy(struct i2c_adapter *i2c_adap)
drivers/media/usb/au0828/au0828-i2c.c-50-{
--
drivers/media/usb/au0828/au0828-i2c.c-55-
drivers/media/usb/au0828/au0828-i2c.c:56:static int i2c_wait_read_done(struct i2c_adapter *i2c_adap)
drivers/media/usb/au0828/au0828-i2c.c-57-{
--
drivers/media/usb/au0828/au0828-i2c.c-71-
drivers/media/usb/au0828/au0828-i2c.c:72:static inline int i2c_is_write_done(struct i2c_adapter *i2c_adap)
drivers/media/usb/au0828/au0828-i2c.c-73-{
--
drivers/media/usb/au0828/au0828-i2c.c-78-
drivers/media/usb/au0828/au0828-i2c.c:79:static int i2c_wait_write_done(struct i2c_adapter *i2c_adap)
drivers/media/usb/au0828/au0828-i2c.c-80-{
--
drivers/media/usb/au0828/au0828-i2c.c-94-
drivers/media/usb/au0828/au0828-i2c.c:95:static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
drivers/media/usb/au0828/au0828-i2c.c-96-{
--
drivers/media/usb/au0828/au0828-i2c.c-101-
drivers/media/usb/au0828/au0828-i2c.c:102:static int i2c_wait_done(struct i2c_adapter *i2c_adap)
drivers/media/usb/au0828/au0828-i2c.c-103-{
--
drivers/media/usb/au0828/au0828-i2c.c-118-/* FIXME: Implement join handling correctly */
drivers/media/usb/au0828/au0828-i2c.c:119:static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
drivers/media/usb/au0828/au0828-i2c.c-120-	const struct i2c_msg *msg, int joined_rlen)
--
drivers/media/usb/au0828/au0828-i2c.c-208-/* FIXME: Implement join handling correctly */
drivers/media/usb/au0828/au0828-i2c.c:209:static int i2c_readbytes(struct i2c_adapter *i2c_adap,
drivers/media/usb/au0828/au0828-i2c.c-210-	const struct i2c_msg *msg, int joined)
--
drivers/media/usb/au0828/au0828-i2c.c-274-
drivers/media/usb/au0828/au0828-i2c.c:275:static int i2c_xfer(struct i2c_adapter *i2c_adap,
drivers/media/usb/au0828/au0828-i2c.c-276-		    struct i2c_msg *msgs, int num)
--
drivers/media/usb/au0828/au0828-i2c.c-309-
drivers/media/usb/au0828/au0828-i2c.c:310:static u32 au0828_functionality(struct i2c_adapter *adap)
drivers/media/usb/au0828/au0828-i2c.c-311-{
--
drivers/media/usb/au0828/au0828-i2c.c=315=static const struct i2c_algorithm au0828_i2c_algo_template = {
--
drivers/media/usb/au0828/au0828-i2c.c-321-
drivers/media/usb/au0828/au0828-i2c.c:322:static const struct i2c_adapter au0828_i2c_adap_template = {
drivers/media/usb/au0828/au0828-i2c.c-323-	.name              = KBUILD_MODNAME,
--
drivers/media/usb/au0828/au0828.h=173=struct au0828_dev {
--
drivers/media/usb/au0828/au0828.h-180-	/* I2C */
drivers/media/usb/au0828/au0828.h:181:	struct i2c_adapter		i2c_adap;
drivers/media/usb/au0828/au0828.h-182-	struct i2c_algorithm		i2c_algo;
--
drivers/media/usb/b2c2/flexcop-usb.c=220=static int flexcop_usb_get_mac_addr(struct flexcop_device *fc, int extended)
--
drivers/media/usb/b2c2/flexcop-usb.c-227-/* usb i2c stuff */
drivers/media/usb/b2c2/flexcop-usb.c:228:static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
drivers/media/usb/b2c2/flexcop-usb.c-229-		flexcop_usb_request_t req, flexcop_usb_i2c_function_t func,
--
drivers/media/usb/b2c2/flexcop-usb.c=309=static int flexcop_usb_write_ibi_reg(struct flexcop_device *fc,
--
drivers/media/usb/b2c2/flexcop-usb.c-314-
drivers/media/usb/b2c2/flexcop-usb.c:315:static int flexcop_usb_i2c_request(struct flexcop_i2c_adapter *i2c,
drivers/media/usb/b2c2/flexcop-usb.c-316-		flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
--
drivers/media/usb/cx231xx/cx231xx-cards.c=1250=void cx231xx_card_setup(struct cx231xx *dev)
--
drivers/media/usb/cx231xx/cx231xx-cards.c-1272-	if (dev->board.tuner_type != TUNER_ABSENT) {
drivers/media/usb/cx231xx/cx231xx-cards.c:1273:		struct i2c_adapter *tuner_i2c = cx231xx_get_i2c_adap(dev,
drivers/media/usb/cx231xx/cx231xx-cards.c-1274-						dev->board.tuner_i2c_master);
--
drivers/media/usb/cx231xx/cx231xx-dvb.c=616=static int dvb_init(struct cx231xx *dev)
--
drivers/media/usb/cx231xx/cx231xx-dvb.c-619-	struct cx231xx_dvb *dvb;
drivers/media/usb/cx231xx/cx231xx-dvb.c:620:	struct i2c_adapter *tuner_i2c;
drivers/media/usb/cx231xx/cx231xx-dvb.c:621:	struct i2c_adapter *demod_i2c;
drivers/media/usb/cx231xx/cx231xx-dvb.c-622-	struct i2c_client *client;
drivers/media/usb/cx231xx/cx231xx-dvb.c:623:	struct i2c_adapter *adapter;
drivers/media/usb/cx231xx/cx231xx-dvb.c-624-
--
drivers/media/usb/cx231xx/cx231xx-dvb.c-747-			 "%s: looking for tuner / demod on i2c bus: %d\n",
drivers/media/usb/cx231xx/cx231xx-dvb.c:748:		       __func__, i2c_adapter_id(tuner_i2c));
drivers/media/usb/cx231xx/cx231xx-dvb.c-749-
--
drivers/media/usb/cx231xx/cx231xx-dvb.c-852-		lgdt3306a_config.fe = &dev->dvb->frontend[0];
drivers/media/usb/cx231xx/cx231xx-dvb.c:853:		lgdt3306a_config.i2c_adapter = &adapter;
drivers/media/usb/cx231xx/cx231xx-dvb.c-854-
--
drivers/media/usb/cx231xx/cx231xx-dvb.c-895-			 "%s: looking for demod on i2c bus: %d\n",
drivers/media/usb/cx231xx/cx231xx-dvb.c:896:			 __func__, i2c_adapter_id(tuner_i2c));
drivers/media/usb/cx231xx/cx231xx-dvb.c-897-
--
drivers/media/usb/cx231xx/cx231xx-dvb.c-924-		si2168_config.fe = &dev->dvb->frontend[0];
drivers/media/usb/cx231xx/cx231xx-dvb.c:925:		si2168_config.i2c_adapter = &adapter;
drivers/media/usb/cx231xx/cx231xx-dvb.c-926-		si2168_config.ts_clock_inv = true;
--
drivers/media/usb/cx231xx/cx231xx-dvb.c-993-		si2168_config.fe = &dev->dvb->frontend[0];
drivers/media/usb/cx231xx/cx231xx-dvb.c:994:		si2168_config.i2c_adapter = &adapter;
drivers/media/usb/cx231xx/cx231xx-dvb.c-995-		si2168_config.ts_clock_inv = true;
--
drivers/media/usb/cx231xx/cx231xx-dvb.c-1032-	{
drivers/media/usb/cx231xx/cx231xx-dvb.c:1033:		struct i2c_adapter *adapter2;
drivers/media/usb/cx231xx/cx231xx-dvb.c-1034-		struct si2157_config si2157_config = {};
--
drivers/media/usb/cx231xx/cx231xx-dvb.c-1040-		lgdt3306a_config.fe = &dev->dvb->frontend[0];
drivers/media/usb/cx231xx/cx231xx-dvb.c:1041:		lgdt3306a_config.i2c_adapter = &adapter;
drivers/media/usb/cx231xx/cx231xx-dvb.c-1042-
--
drivers/media/usb/cx231xx/cx231xx-dvb.c-1055-		si2168_config.fe = &dev->dvb->frontend[1];
drivers/media/usb/cx231xx/cx231xx-dvb.c:1056:		si2168_config.i2c_adapter = &adapter2;
drivers/media/usb/cx231xx/cx231xx-dvb.c-1057-		si2168_config.ts_clock_inv = true;
--
drivers/media/usb/cx231xx/cx231xx-i2c.c=52=static inline bool is_tuner(struct cx231xx *dev, struct cx231xx_i2c *bus,
--
drivers/media/usb/cx231xx/cx231xx-i2c.c-71- */
drivers/media/usb/cx231xx/cx231xx-i2c.c:72:static int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap,
drivers/media/usb/cx231xx/cx231xx-i2c.c-73-				  const struct i2c_msg *msg)
--
drivers/media/usb/cx231xx/cx231xx-i2c.c-182- */
drivers/media/usb/cx231xx/cx231xx-i2c.c:183:static int cx231xx_i2c_recv_bytes(struct i2c_adapter *i2c_adap,
drivers/media/usb/cx231xx/cx231xx-i2c.c-184-				  const struct i2c_msg *msg)
--
drivers/media/usb/cx231xx/cx231xx-i2c.c-268- */
drivers/media/usb/cx231xx/cx231xx-i2c.c:269:static int cx231xx_i2c_recv_bytes_with_saddr(struct i2c_adapter *i2c_adap,
drivers/media/usb/cx231xx/cx231xx-i2c.c-270-					     const struct i2c_msg *msg1,
--
drivers/media/usb/cx231xx/cx231xx-i2c.c-332- */
drivers/media/usb/cx231xx/cx231xx-i2c.c:333:static int cx231xx_i2c_check_for_device(struct i2c_adapter *i2c_adap,
drivers/media/usb/cx231xx/cx231xx-i2c.c-334-					const struct i2c_msg *msg)
--
drivers/media/usb/cx231xx/cx231xx-i2c.c-359- */
drivers/media/usb/cx231xx/cx231xx-i2c.c:360:static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap,
drivers/media/usb/cx231xx/cx231xx-i2c.c-361-			    struct i2c_msg msgs[], int num)
--
drivers/media/usb/cx231xx/cx231xx-i2c.c-437- */
drivers/media/usb/cx231xx/cx231xx-i2c.c:438:static u32 functionality(struct i2c_adapter *adap)
drivers/media/usb/cx231xx/cx231xx-i2c.c-439-{
--
drivers/media/usb/cx231xx/cx231xx-i2c.c=443=static const struct i2c_algorithm cx231xx_algo = {
--
drivers/media/usb/cx231xx/cx231xx-i2c.c-447-
drivers/media/usb/cx231xx/cx231xx-i2c.c:448:static const struct i2c_adapter cx231xx_adap_template = {
drivers/media/usb/cx231xx/cx231xx-i2c.c-449-	.owner = THIS_MODULE,
--
drivers/media/usb/cx231xx/cx231xx-i2c.c=476=void cx231xx_do_i2c_scan(struct cx231xx *dev, int i2c_port)
--
drivers/media/usb/cx231xx/cx231xx-i2c.c-479-	int i, rc;
drivers/media/usb/cx231xx/cx231xx-i2c.c:480:	struct i2c_adapter *adap;
drivers/media/usb/cx231xx/cx231xx-i2c.c-481-	struct i2c_msg msg = {
--
drivers/media/usb/cx231xx/cx231xx-i2c.c=573=void cx231xx_i2c_mux_unregister(struct cx231xx *dev)
--
drivers/media/usb/cx231xx/cx231xx-i2c.c-577-
drivers/media/usb/cx231xx/cx231xx-i2c.c:578:struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx *dev, int i2c_port)
drivers/media/usb/cx231xx/cx231xx-i2c.c-579-{
--
drivers/media/usb/cx231xx/cx231xx.h=446=struct cx231xx_i2c {
--
drivers/media/usb/cx231xx/cx231xx.h-451-	/* i2c i/o */
drivers/media/usb/cx231xx/cx231xx.h:452:	struct i2c_adapter i2c_adap;
drivers/media/usb/cx231xx/cx231xx.h-453-	int i2c_rc;
--
drivers/media/usb/cx231xx/cx231xx.h=562=struct cx231xx {
--
drivers/media/usb/cx231xx/cx231xx.h-601-	struct i2c_mux_core *muxc;
drivers/media/usb/cx231xx/cx231xx.h:602:	struct i2c_adapter *i2c_mux_adap[2];
drivers/media/usb/cx231xx/cx231xx.h-603-
--
drivers/media/usb/cx231xx/cx231xx.h=745=void cx231xx_i2c_mux_unregister(struct cx231xx *dev);
drivers/media/usb/cx231xx/cx231xx.h:746:struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx *dev, int i2c_port);
drivers/media/usb/cx231xx/cx231xx.h-747-
--
drivers/media/usb/dvb-usb-v2/af9015.c=126=static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
--
drivers/media/usb/dvb-usb-v2/af9015.c-138-
drivers/media/usb/dvb-usb-v2/af9015.c:139:static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
drivers/media/usb/dvb-usb-v2/af9015.c-140-			   int num)
--
drivers/media/usb/dvb-usb-v2/af9015.c-257-
drivers/media/usb/dvb-usb-v2/af9015.c:258:static u32 af9015_i2c_func(struct i2c_adapter *adapter)
drivers/media/usb/dvb-usb-v2/af9015.c-259-{
--
drivers/media/usb/dvb-usb-v2/af9015.c=998=static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
--
drivers/media/usb/dvb-usb-v2/af9015.c-1003-	struct i2c_client *client;
drivers/media/usb/dvb-usb-v2/af9015.c:1004:	struct i2c_adapter *adapter;
drivers/media/usb/dvb-usb-v2/af9015.c-1005-	int ret;
--
drivers/media/usb/dvb-usb-v2/af9015.c-1009-	client = state->demod_i2c_client[adap->id];
drivers/media/usb/dvb-usb-v2/af9015.c:1010:	adapter = state->af9013_pdata[adap->id].get_i2c_adapter(client);
drivers/media/usb/dvb-usb-v2/af9015.c-1011-
--
drivers/media/usb/dvb-usb-v2/af9035.c=180=static int af9035_add_i2c_dev(struct dvb_usb_device *d, const char *type,
drivers/media/usb/dvb-usb-v2/af9035.c:181:		u8 addr, void *platform_data, struct i2c_adapter *adapter)
drivers/media/usb/dvb-usb-v2/af9035.c-182-{
--
drivers/media/usb/dvb-usb-v2/af9035.c=232=static void af9035_del_i2c_dev(struct dvb_usb_device *d)
--
drivers/media/usb/dvb-usb-v2/af9035.c-266-
drivers/media/usb/dvb-usb-v2/af9035.c:267:static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
drivers/media/usb/dvb-usb-v2/af9035.c-268-		struct i2c_msg msg[], int num)
--
drivers/media/usb/dvb-usb-v2/af9035.c-480-
drivers/media/usb/dvb-usb-v2/af9035.c:481:static u32 af9035_i2c_functionality(struct i2c_adapter *adapter)
drivers/media/usb/dvb-usb-v2/af9035.c-482-{
--
drivers/media/usb/dvb-usb-v2/af9035.c=1150=static int af9035_frontend_callback(void *adapter_priv, int component,
--
drivers/media/usb/dvb-usb-v2/af9035.c-1152-{
drivers/media/usb/dvb-usb-v2/af9035.c:1153:	struct i2c_adapter *adap = adapter_priv;
drivers/media/usb/dvb-usb-v2/af9035.c-1154-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
--
drivers/media/usb/dvb-usb-v2/af9035.c=1225=static int it930x_frontend_attach(struct dvb_usb_adapter *adap)
--
drivers/media/usb/dvb-usb-v2/af9035.c-1231-	struct si2168_config si2168_config;
drivers/media/usb/dvb-usb-v2/af9035.c:1232:	struct i2c_adapter *adapter;
drivers/media/usb/dvb-usb-v2/af9035.c-1233-
--
drivers/media/usb/dvb-usb-v2/af9035.c-1278-	memset(&si2168_config, 0, sizeof(si2168_config));
drivers/media/usb/dvb-usb-v2/af9035.c:1279:	si2168_config.i2c_adapter = &adapter;
drivers/media/usb/dvb-usb-v2/af9035.c-1280-	si2168_config.fe = &adap->fe[0];
--
drivers/media/usb/dvb-usb-v2/af9035.c-1294-	}
drivers/media/usb/dvb-usb-v2/af9035.c:1295:	state->i2c_adapter_demod = adapter;
drivers/media/usb/dvb-usb-v2/af9035.c-1296-
--
drivers/media/usb/dvb-usb-v2/af9035.c=1626=static int it930x_tuner_attach(struct dvb_usb_adapter *adap)
--
drivers/media/usb/dvb-usb-v2/af9035.c-1661-				 it930x_addresses_table[state->it930x_addresses].tuner_i2c_addr,
drivers/media/usb/dvb-usb-v2/af9035.c:1662:				 &si2157_config, state->i2c_adapter_demod);
drivers/media/usb/dvb-usb-v2/af9035.c-1663-	if (ret)
--
drivers/media/usb/dvb-usb-v2/af9035.h=45=struct state {
--
drivers/media/usb/dvb-usb-v2/af9035.h-63-	struct i2c_client *i2c_client[AF9035_I2C_CLIENT_MAX];
drivers/media/usb/dvb-usb-v2/af9035.h:64:	struct i2c_adapter *i2c_adapter_demod;
drivers/media/usb/dvb-usb-v2/af9035.h-65-	struct platform_device *platform_device_tuner[2];
--
drivers/media/usb/dvb-usb-v2/anysee.c=176=static int anysee_ir_ctrl(struct dvb_usb_device *d, u8 onoff)
--
drivers/media/usb/dvb-usb-v2/anysee.c-183-/* I2C */
drivers/media/usb/dvb-usb-v2/anysee.c:184:static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
drivers/media/usb/dvb-usb-v2/anysee.c-185-	int num)
--
drivers/media/usb/dvb-usb-v2/anysee.c-232-
drivers/media/usb/dvb-usb-v2/anysee.c:233:static u32 anysee_i2c_func(struct i2c_adapter *adapter)
drivers/media/usb/dvb-usb-v2/anysee.c-234-{
--
drivers/media/usb/dvb-usb-v2/anysee.c=611=static int anysee_add_i2c_dev(struct dvb_usb_device *d, const char *type,
--
drivers/media/usb/dvb-usb-v2/anysee.c-616-	struct i2c_client *client;
drivers/media/usb/dvb-usb-v2/anysee.c:617:	struct i2c_adapter *adapter = &d->i2c_adap;
drivers/media/usb/dvb-usb-v2/anysee.c-618-	struct i2c_board_info board_info = {
--
drivers/media/usb/dvb-usb-v2/au6610.c=66=static int au6610_i2c_msg(struct dvb_usb_device *d, u8 addr,
--
drivers/media/usb/dvb-usb-v2/au6610.c-82-/* I2C */
drivers/media/usb/dvb-usb-v2/au6610.c:83:static int au6610_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
drivers/media/usb/dvb-usb-v2/au6610.c-84-			   int num)
--
drivers/media/usb/dvb-usb-v2/au6610.c-112-
drivers/media/usb/dvb-usb-v2/au6610.c:113:static u32 au6610_i2c_func(struct i2c_adapter *adapter)
drivers/media/usb/dvb-usb-v2/au6610.c-114-{
--
drivers/media/usb/dvb-usb-v2/az6007.c=689=static int az6007_power_ctrl(struct dvb_usb_device *d, int onoff)
--
drivers/media/usb/dvb-usb-v2/az6007.c-742-/* I2C */
drivers/media/usb/dvb-usb-v2/az6007.c:743:static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
drivers/media/usb/dvb-usb-v2/az6007.c-744-			   int num)
--
drivers/media/usb/dvb-usb-v2/az6007.c-835-
drivers/media/usb/dvb-usb-v2/az6007.c:836:static u32 az6007_i2c_func(struct i2c_adapter *adapter)
drivers/media/usb/dvb-usb-v2/az6007.c-837-{
--
drivers/media/usb/dvb-usb-v2/ce6230.c=83=static struct zl10353_config ce6230_zl10353_config;
drivers/media/usb/dvb-usb-v2/ce6230.c-84-
drivers/media/usb/dvb-usb-v2/ce6230.c:85:static int ce6230_i2c_master_xfer(struct i2c_adapter *adap,
drivers/media/usb/dvb-usb-v2/ce6230.c-86-		struct i2c_msg msg[], int num)
--
drivers/media/usb/dvb-usb-v2/ce6230.c-151-
drivers/media/usb/dvb-usb-v2/ce6230.c:152:static u32 ce6230_i2c_functionality(struct i2c_adapter *adapter)
drivers/media/usb/dvb-usb-v2/ce6230.c-153-{
--
drivers/media/usb/dvb-usb-v2/dvb_usb.h=375=struct dvb_usb_device {
--
drivers/media/usb/dvb-usb-v2/dvb_usb.h-389-	struct mutex i2c_mutex;
drivers/media/usb/dvb-usb-v2/dvb_usb.h:390:	struct i2c_adapter i2c_adap;
drivers/media/usb/dvb-usb-v2/dvb_usb.h-391-
--
drivers/media/usb/dvb-usb-v2/dvbsky.c=86=static int dvbsky_gpio_ctrl(struct dvb_usb_device *d, u8 gport, u8 value)
--
drivers/media/usb/dvb-usb-v2/dvbsky.c-98-/* I2C */
drivers/media/usb/dvb-usb-v2/dvbsky.c:99:static int dvbsky_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
drivers/media/usb/dvb-usb-v2/dvbsky.c-100-	int num)
--
drivers/media/usb/dvb-usb-v2/dvbsky.c-166-
drivers/media/usb/dvb-usb-v2/dvbsky.c:167:static u32 dvbsky_i2c_func(struct i2c_adapter *adapter)
drivers/media/usb/dvb-usb-v2/dvbsky.c-168-{
--
drivers/media/usb/dvb-usb-v2/dvbsky.c=274=static int dvbsky_s960_attach(struct dvb_usb_adapter *adap)
--
drivers/media/usb/dvb-usb-v2/dvbsky.c-277-	struct dvb_usb_device *d = adap_to_d(adap);
drivers/media/usb/dvb-usb-v2/dvbsky.c:278:	struct i2c_adapter *i2c_adapter;
drivers/media/usb/dvb-usb-v2/dvbsky.c-279-	struct m88ds3103_platform_data m88ds3103_pdata = {};
--
drivers/media/usb/dvb-usb-v2/dvbsky.c-299-	adap->fe[0] = m88ds3103_pdata.get_dvb_frontend(state->i2c_client_demod);
drivers/media/usb/dvb-usb-v2/dvbsky.c:300:	i2c_adapter = m88ds3103_pdata.get_i2c_adapter(state->i2c_client_demod);
drivers/media/usb/dvb-usb-v2/dvbsky.c-301-
--
drivers/media/usb/dvb-usb-v2/dvbsky.c-306-	state->i2c_client_tuner = dvb_module_probe("ts2020", NULL,
drivers/media/usb/dvb-usb-v2/dvbsky.c:307:						   i2c_adapter,
drivers/media/usb/dvb-usb-v2/dvbsky.c-308-						   0x60, &ts2020_config);
--
drivers/media/usb/dvb-usb-v2/dvbsky.c=376=static int dvbsky_s960c_attach(struct dvb_usb_adapter *adap)
--
drivers/media/usb/dvb-usb-v2/dvbsky.c-379-	struct dvb_usb_device *d = adap_to_d(adap);
drivers/media/usb/dvb-usb-v2/dvbsky.c:380:	struct i2c_adapter *i2c_adapter;
drivers/media/usb/dvb-usb-v2/dvbsky.c-381-	struct m88ds3103_platform_data m88ds3103_pdata = {};
--
drivers/media/usb/dvb-usb-v2/dvbsky.c-402-	adap->fe[0] = m88ds3103_pdata.get_dvb_frontend(state->i2c_client_demod);
drivers/media/usb/dvb-usb-v2/dvbsky.c:403:	i2c_adapter = m88ds3103_pdata.get_i2c_adapter(state->i2c_client_demod);
drivers/media/usb/dvb-usb-v2/dvbsky.c-404-
--
drivers/media/usb/dvb-usb-v2/dvbsky.c-409-	state->i2c_client_tuner = dvb_module_probe("ts2020", NULL,
drivers/media/usb/dvb-usb-v2/dvbsky.c:410:						   i2c_adapter,
drivers/media/usb/dvb-usb-v2/dvbsky.c-411-						   0x60, &ts2020_config);
--
drivers/media/usb/dvb-usb-v2/dvbsky.c=447=static int dvbsky_t680c_attach(struct dvb_usb_adapter *adap)
--
drivers/media/usb/dvb-usb-v2/dvbsky.c-450-	struct dvb_usb_device *d = adap_to_d(adap);
drivers/media/usb/dvb-usb-v2/dvbsky.c:451:	struct i2c_adapter *i2c_adapter;
drivers/media/usb/dvb-usb-v2/dvbsky.c-452-	struct si2168_config si2168_config = {};
--
drivers/media/usb/dvb-usb-v2/dvbsky.c-456-	/* attach demod */
drivers/media/usb/dvb-usb-v2/dvbsky.c:457:	si2168_config.i2c_adapter = &i2c_adapter;
drivers/media/usb/dvb-usb-v2/dvbsky.c-458-	si2168_config.fe = &adap->fe[0];
--
drivers/media/usb/dvb-usb-v2/dvbsky.c-471-	state->i2c_client_tuner = dvb_module_probe("si2157", NULL,
drivers/media/usb/dvb-usb-v2/dvbsky.c:472:						   i2c_adapter,
drivers/media/usb/dvb-usb-v2/dvbsky.c-473-						   0x60, &si2157_config);
--
drivers/media/usb/dvb-usb-v2/dvbsky.c=497=static int dvbsky_t330_attach(struct dvb_usb_adapter *adap)
--
drivers/media/usb/dvb-usb-v2/dvbsky.c-500-	struct dvb_usb_device *d = adap_to_d(adap);
drivers/media/usb/dvb-usb-v2/dvbsky.c:501:	struct i2c_adapter *i2c_adapter;
drivers/media/usb/dvb-usb-v2/dvbsky.c-502-	struct si2168_config si2168_config = {};
--
drivers/media/usb/dvb-usb-v2/dvbsky.c-505-	/* attach demod */
drivers/media/usb/dvb-usb-v2/dvbsky.c:506:	si2168_config.i2c_adapter = &i2c_adapter;
drivers/media/usb/dvb-usb-v2/dvbsky.c-507-	si2168_config.fe = &adap->fe[0];
--
drivers/media/usb/dvb-usb-v2/dvbsky.c-521-	state->i2c_client_tuner = dvb_module_probe("si2157", NULL,
drivers/media/usb/dvb-usb-v2/dvbsky.c:522:						   i2c_adapter,
drivers/media/usb/dvb-usb-v2/dvbsky.c-523-						   0x60, &si2157_config);
--
drivers/media/usb/dvb-usb-v2/dvbsky.c=532=static int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap)
--
drivers/media/usb/dvb-usb-v2/dvbsky.c-535-	struct dvb_usb_device *d = adap_to_d(adap);
drivers/media/usb/dvb-usb-v2/dvbsky.c:536:	struct i2c_adapter *i2c_adapter;
drivers/media/usb/dvb-usb-v2/dvbsky.c-537-	struct si2168_config si2168_config = {};
--
drivers/media/usb/dvb-usb-v2/dvbsky.c-540-	/* attach demod */
drivers/media/usb/dvb-usb-v2/dvbsky.c:541:	si2168_config.i2c_adapter = &i2c_adapter;
drivers/media/usb/dvb-usb-v2/dvbsky.c-542-	si2168_config.fe = &adap->fe[0];
--
drivers/media/usb/dvb-usb-v2/dvbsky.c-560-		state->i2c_client_tuner = dvb_module_probe("si2157", NULL,
drivers/media/usb/dvb-usb-v2/dvbsky.c:561:							   i2c_adapter,
drivers/media/usb/dvb-usb-v2/dvbsky.c-562-							   0x60,
--
drivers/media/usb/dvb-usb-v2/dvbsky.c-566-		state->i2c_client_tuner = dvb_module_probe("si2157", "si2141",
drivers/media/usb/dvb-usb-v2/dvbsky.c:567:							   i2c_adapter,
drivers/media/usb/dvb-usb-v2/dvbsky.c-568-							   0x60,
--
drivers/media/usb/dvb-usb-v2/ec168.c=99=static struct ec100_config ec168_ec100_config;
drivers/media/usb/dvb-usb-v2/ec168.c-100-
drivers/media/usb/dvb-usb-v2/ec168.c:101:static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
drivers/media/usb/dvb-usb-v2/ec168.c-102-	int num)
--
drivers/media/usb/dvb-usb-v2/ec168.c-173-
drivers/media/usb/dvb-usb-v2/ec168.c:174:static u32 ec168_i2c_func(struct i2c_adapter *adapter)
drivers/media/usb/dvb-usb-v2/ec168.c-175-{
--
drivers/media/usb/dvb-usb-v2/gl861.c=17=struct gl861 {
--
drivers/media/usb/dvb-usb-v2/gl861.c-20-
drivers/media/usb/dvb-usb-v2/gl861.c:21:	struct i2c_adapter *demod_sub_i2c;
drivers/media/usb/dvb-usb-v2/gl861.c-22-	struct i2c_client  *i2c_client_demod;
--
drivers/media/usb/dvb-usb-v2/gl861.c=81=static int gl861_short_write(struct dvb_usb_device *d, u8 addr, u8 reg, u8 val)
--
drivers/media/usb/dvb-usb-v2/gl861.c-86-
drivers/media/usb/dvb-usb-v2/gl861.c:87:static int gl861_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
drivers/media/usb/dvb-usb-v2/gl861.c-88-				 int num)
--
drivers/media/usb/dvb-usb-v2/gl861.c-159-
drivers/media/usb/dvb-usb-v2/gl861.c:160:static u32 gl861_i2c_functionality(struct i2c_adapter *adapter)
drivers/media/usb/dvb-usb-v2/gl861.c-161-{
--
drivers/media/usb/dvb-usb-v2/lmedm04.c=485=static int lme2510_msg(struct dvb_usb_device *d,
--
drivers/media/usb/dvb-usb-v2/lmedm04.c-494-
drivers/media/usb/dvb-usb-v2/lmedm04.c:495:static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
drivers/media/usb/dvb-usb-v2/lmedm04.c-496-				 int num)
--
drivers/media/usb/dvb-usb-v2/lmedm04.c-556-
drivers/media/usb/dvb-usb-v2/lmedm04.c:557:static u32 lme2510_i2c_func(struct i2c_adapter *adapter)
drivers/media/usb/dvb-usb-v2/lmedm04.c-558-{
--
drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c=427=static int mxl111sf_i2c_hw_xfer_msg(struct mxl111sf_state *state,
--
drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c-798-
drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c:799:int mxl111sf_i2c_xfer(struct i2c_adapter *adap,
drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c-800-		      struct i2c_msg msg[], int num)
--
drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h-12-
drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h:13:int mxl111sf_i2c_xfer(struct i2c_adapter *adap,
drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h-14-		      struct i2c_msg msg[], int num);
--
drivers/media/usb/dvb-usb-v2/mxl111sf.c=871=static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap)
--
drivers/media/usb/dvb-usb-v2/mxl111sf.c-908-
drivers/media/usb/dvb-usb-v2/mxl111sf.c:909:static u32 mxl111sf_i2c_func(struct i2c_adapter *adapter)
drivers/media/usb/dvb-usb-v2/mxl111sf.c-910-{
--
drivers/media/usb/dvb-usb-v2/rtl28xxu.c=118=static int rtl28xxu_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val,
--
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-138-/* I2C */
drivers/media/usb/dvb-usb-v2/rtl28xxu.c:139:static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-140-	int num)
--
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-287-
drivers/media/usb/dvb-usb-v2/rtl28xxu.c:288:static u32 rtl28xxu_i2c_func(struct i2c_adapter *adapter)
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-289-{
--
drivers/media/usb/dvb-usb-v2/rtl28xxu.c=699=static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap)
--
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-744-	adap->fe[0] = pdata->get_dvb_frontend(client);
drivers/media/usb/dvb-usb-v2/rtl28xxu.c:745:	dev->demod_i2c_adapter = pdata->get_i2c_adapter(client);
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-746-
--
drivers/media/usb/dvb-usb-v2/rtl28xxu.c=868=static int rtl2832u_frontend_callback(void *adapter_priv, int component,
--
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-870-{
drivers/media/usb/dvb-usb-v2/rtl28xxu.c:871:	struct i2c_adapter *adapter = adapter_priv;
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-872-	struct device *parent = adapter->dev.parent;
drivers/media/usb/dvb-usb-v2/rtl28xxu.c:873:	struct i2c_adapter *parent_adapter;
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-874-	struct dvb_usb_device *d;
--
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-882-	 */
drivers/media/usb/dvb-usb-v2/rtl28xxu.c:883:	if (parent != NULL && parent->type == &i2c_adapter_type)
drivers/media/usb/dvb-usb-v2/rtl28xxu.c:884:		parent_adapter = to_i2c_adapter(parent);
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-885-	else
--
drivers/media/usb/dvb-usb-v2/rtl28xxu.c=907=static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
--
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-965-	adap->fe[0] = pdata->get_dvb_frontend(client);
drivers/media/usb/dvb-usb-v2/rtl28xxu.c:966:	dev->demod_i2c_adapter = pdata->get_i2c_adapter(client);
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-967-
--
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-1034-			struct si2168_config si2168_config = {};
drivers/media/usb/dvb-usb-v2/rtl28xxu.c:1035:			struct i2c_adapter *adapter;
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-1036-
drivers/media/usb/dvb-usb-v2/rtl28xxu.c:1037:			si2168_config.i2c_adapter = &adapter;
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-1038-			si2168_config.fe = &adap->fe[1];
--
drivers/media/usb/dvb-usb-v2/rtl28xxu.c=1137=static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap)
--
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-1148-		fe = dvb_attach(qt1010_attach, adap->fe[0],
drivers/media/usb/dvb-usb-v2/rtl28xxu.c:1149:				dev->demod_i2c_adapter,
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-1150-				&rtl28xxu_qt1010_config);
--
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-1153-		fe = dvb_attach(mt2060_attach, adap->fe[0],
drivers/media/usb/dvb-usb-v2/rtl28xxu.c:1154:				dev->demod_i2c_adapter,
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-1155-				&rtl28xxu_mt2060_config, 1220);
--
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-1158-		fe = dvb_attach(mxl5005s_attach, adap->fe[0],
drivers/media/usb/dvb-usb-v2/rtl28xxu.c:1159:				dev->demod_i2c_adapter,
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-1160-				&rtl28xxu_mxl5005s_config);
--
drivers/media/usb/dvb-usb-v2/rtl28xxu.c=1197=static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
--
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-1216-		fe = dvb_attach(fc0012_attach, adap->fe[0],
drivers/media/usb/dvb-usb-v2/rtl28xxu.c:1217:			dev->demod_i2c_adapter, &rtl2832u_fc0012_config);
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-1218-
--
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-1225-		fe = dvb_attach(fc0013_attach, adap->fe[0],
drivers/media/usb/dvb-usb-v2/rtl28xxu.c:1226:			dev->demod_i2c_adapter, 0xc6>>1, 0, FC_XTAL_28_8_MHZ);
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-1227-
--
drivers/media/usb/dvb-usb-v2/rtl28xxu.c-1242-			request_module(info.type);
drivers/media/usb/dvb-usb-v2/rtl28xxu.c:1243:			client = i2c_new_client_device(dev->demod_i2c_adapter,

]

53/2 2026/07/30 12:20 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 72060
							output: 26
							thoughts: 41
						

Thoughts:
Okay, here's my take on those thoughts, framed as my own internal monologue, with a **bolded header**:

**Digging into the DVB-USB Driver Disconnect Sequence**

Right, let me just parse this quickly. Hmm, the code flow here… it seems `dvb_usb_device_exit` is being called directly from within `dvb_usbv2_disconnect`? Interesting. I've seen that pattern before, but it always warrants a quick double-check, especially in a driver context. I need to make sure the resource management is exactly as I expect. Okay, let's pull up the definition of `dvb_usbv2_disconnect`. Time to see what's actually happening on the other end of that function call. Need to understand the order of operations here; make sure nothing's getting freed too early, or that we're properly cleaning up all allocated resources. Let's see...



54/2 2026/07/30 12:20 tool codesearch-definition-source
0m Args:
map[Name:dvb_usbv2_disconnect]

Results:
map[SourceCode:1007:	void dvb_usbv2_disconnect(struct usb_interface *intf)
1008:	{
1009:		struct dvb_usb_device *d = usb_get_intfdata(intf);
1010:		const char *devname = kstrdup(dev_name(&d->udev->dev), GFP_KERNEL);
1011:		const char *drvname = d->name;
1012:	
1013:		dev_dbg(&d->udev->dev, "%s: bInterfaceNumber=%d\n", __func__,
1014:				intf->cur_altsetting->desc.bInterfaceNumber);
1015:	
1016:		if (d->props->exit)
1017:			d->props->exit(d);
1018:	
1019:		dvb_usbv2_exit(d);
1020:	
1021:		if (d->props->disconnect)
1022:			d->props->disconnect(d);
1023:	
1024:		kfree(d->priv);
1025:		kfree(d);
1026:	
1027:		pr_info("%s: '%s:%s' successfully deinitialized and disconnected\n",
1028:			KBUILD_MODNAME, drvname, devname);
1029:		kfree(devname);
1030:	}
 SourceFile:drivers/media/usb/dvb-usb-v2/dvb_usb_core.c]

55/2 2026/07/30 12:20 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 72744
							output: 27
							thoughts: 217
						

Thoughts:
**Investigating a Suspected Use-After-Free Vulnerability**

Okay, so I'm looking at this `dvb_usbv2_disconnect` function and immediately something smells fishy. It calls `kfree(d)`. Right, so `d` is getting freed. But, and this is the problem, if `d` is freed, then `d->i2c_adap` also gets freed, right? We're talking about pointers here, so one frees the other.

But hold on a second… if `d->i2c_adap` *is* freed, then a later call to `i2c_adapter_lock_bus` would try to access `adapter->bus_lock`. That's at offset 40 of the `i2c_adapter` struct. And if `i2c_adapter` is *inside* `d`, and `d` has been freed, then KASAN *should* be screaming about a Use-After-Free on `d`, which, by the way, is `kmalloc-16k`. I'd expect the report to be complaining about that.

But here's the kicker: the KASAN report is telling me UAF on `usb_device`, which is `kmalloc-4k`. That means that `i2c_adapter` is *not* getting freed as part of `d`. This just isn't making sense. I need to figure out how `i2c_adapter` can survive the free of `d`! Is this even a `dvb_usb_v2` driver? I need to check the relevant drivers! Let's check `au0828`.



56/2 2026/07/30 12:21 tool codesearch-definition-source
0m Args:
map[Name:au0828_usb_disconnect]

Results:
map[SourceCode: 163:	static void au0828_usb_disconnect(struct usb_interface *interface)
 164:	{
 165:		struct au0828_dev *dev = usb_get_intfdata(interface);
 166:	
 167:		dprintk(1, "%s()\n", __func__);
 168:	
 169:		/* there is a small window after disconnect, before
 170:		   dev->usbdev is NULL, for poll (e.g: IR) try to access
 171:		   the device and fill the dmesg with error messages.
 172:		   Set the status so poll routines can check and avoid
 173:		   access after disconnect.
 174:		*/
 175:		set_bit(DEV_DISCONNECTED, &dev->dev_state);
 176:	
 177:		au0828_rc_unregister(dev);
 178:		/* Digital TV */
 179:		au0828_dvb_unregister(dev);
 180:	
 181:		usb_set_intfdata(interface, NULL);
 182:		mutex_lock(&dev->mutex);
 183:		dev->usbdev = NULL;
 184:		mutex_unlock(&dev->mutex);
 185:		if (au0828_analog_unregister(dev)) {
 186:			/*
 187:			 * No need to call au0828_usb_release() if V4L2 is enabled,
 188:			 * as this is already called via au0828_usb_v4l2_release()
 189:			 */
 190:			return;
 191:		}
 192:		au0828_usb_release(dev);
 193:	}
 SourceFile:drivers/media/usb/au0828/au0828-core.c]

57/2 2026/07/30 12:21 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 73884
							output: 27
							thoughts: 15
						

Thoughts:
Okay, let's dive into this. Here's my take on those thoughts, as if they're my own:

**Analyzing `au0828_usb_release`**

Alright, time to get to it. My initial thought is to take a look at `au0828_usb_release`. Given my experience, I'm already mentally running through the typical USB release function workflow. I'm expecting to see resource deallocation – perhaps memory free operations, cleanup of internal data structures related to the USB device, and potentially calls to deregister the device from the USB bus if it's being disconnected. I'll be looking specifically for any potential race conditions or missed cleanup steps that could lead to memory leaks or other issues. I'll also be mentally mapping the function's place within the overall driver architecture. Let's dig in and see what's actually going on.



58/2 2026/07/30 12:21 tool codesearch-definition-source
0m Args:
map[Name:au0828_usb_release]

Results:
map[SourceCode: 153:	void au0828_usb_release(struct au0828_dev *dev)
 154:	{
 155:		au0828_unregister_media_device(dev);
 156:	
 157:		/* I2C */
 158:		au0828_i2c_unregister(dev);
 159:	
 160:		kfree(dev);
 161:	}
 SourceFile:drivers/media/usb/au0828/au0828-core.c]

59/2 2026/07/30 12:21 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 74286
							output: 27
							thoughts: 82
						

Thoughts:
**My Immediate Concerns Regarding the `au0828_usb_release` Function**

Okay, so `au0828_usb_release` is calling `kfree(dev)`. That's standard cleanup, freeing the device structure. My primary worry, as always with memory management, is that subsequent freeing of `dev->i2c_adap` could result in a double free. I'll need to check the code that sets up `i2c_adap` and verify there aren't any potential race conditions or other issues lurking there.

Wait a minute... I remember seeing something about `au0828_analog_unregister(dev)` potentially returning 1 if V4L2 is enabled. That's a red flag! If `au0828_analog_unregister` returns this value, it *could* imply a conditional path where `dev` is still in use, or at least that some resources associated with it haven't been properly cleaned up. I need to dive into the implementation of `au0828_analog_unregister` right now and understand the circumstances under which it returns 1. This is a potential bug or a subtle design flaw that needs thorough investigation. The relationship between `au0828_usb_release` and `au0828_analog_unregister` looks crucial here.



60/2 2026/07/30 12:21 tool codesearch-definition-source
0m Args:
map[Name:au0828_analog_unregister]

Results:
map[SourceCode: 920:	/* ------------------------------------------------------------------
 921:	   V4L2 interface
 922:	   ------------------------------------------------------------------*/
 923:	/*
 924:	 * au0828_analog_unregister
 925:	 * unregister v4l2 devices
 926:	 */
 927:	int au0828_analog_unregister(struct au0828_dev *dev)
 928:	{
 929:		dprintk(1, "au0828_analog_unregister called\n");
 930:	
 931:		/* No analog TV */
 932:		if (AUVI_INPUT(0).type == AU0828_VMUX_UNDEFINED)
 933:			return 0;
 934:	
 935:		mutex_lock(&au0828_sysfs_lock);
 936:		vb2_video_unregister_device(&dev->vdev);
 937:		vb2_video_unregister_device(&dev->vbi_dev);
 938:		mutex_unlock(&au0828_sysfs_lock);
 939:	
 940:		v4l2_device_disconnect(&dev->v4l2_dev);
 941:		v4l2_device_put(&dev->v4l2_dev);
 942:	
 943:		return 1;
 944:	}
 SourceFile:drivers/media/usb/au0828/au0828-video.c]

61/2 2026/07/30 12:21 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 75117
							output: 32
							thoughts: 97
						

Thoughts:
Okay, here's my interpretation of this scenario, focusing on the release sequence of this device.

**Understanding the Device Release Mechanism**

Alright, so the crucial takeaway here is how this device's resources are freed. If the return value is 1, a specific release function, `au0828_usb_release`, *isn't* directly invoked. Instead, the driver leans on a different mechanism: `v4l2_device_put(&dev->v4l2_dev)`.  This is a V4L2-centric approach, which is good. I need to keep in mind that this is a V4L2 device. The system uses reference counting for the `v4l2_device`. The important thing to understand is that it leverages the `v4l2_device` refcount to control the device lifetime.

When that reference count for the `v4l2_device` drops to zero, *then* the registered `release` callback associated with that `v4l2_device` is automatically executed. This is where I have to look carefully at `au0828_usb_v4l2_release`. This is where all the actual device-specific resource cleanup presumably happens. I need to make sure this is what I expect. I'll need to check if there is an issue with how the refcount is managed. I must analyze `au0828_usb_v4l2_release` to confirm that all resources are properly freed when the count hits zero.



62/2 2026/07/30 12:21 tool codesearch-definition-source
0m Args:
map[Name:au0828_usb_v4l2_release]

Results:
map[SourceCode: 635:	static void au0828_usb_v4l2_release(struct v4l2_device *v4l2_dev)
 636:	{
 637:		struct au0828_dev *dev =
 638:			container_of(v4l2_dev, struct au0828_dev, v4l2_dev);
 639:	
 640:		v4l2_ctrl_handler_free(&dev->v4l2_ctrl_hdl);
 641:		v4l2_device_unregister(&dev->v4l2_dev);
 642:		au0828_usb_v4l2_media_release(dev);
 643:		au0828_usb_release(dev);
 644:	}
 SourceFile:drivers/media/usb/au0828/au0828-video.c]

63/2 2026/07/30 12:21 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 75831
							output: 27
							thoughts: 273
						

Thoughts:
**My Analysis of a Potential USB Device Driver Vulnerability**

Okay, so I'm digging into this driver, specifically looking at how the `au0828_usb_release` function is handled. My concern is that `au0828_usb_release` gets triggered during the release of the `v4l2_device` structure. Here's the key thing: if a V4L2 device like `/dev/videoX` is kept open, `au0828_usb_release` *isn't* called. This means the `dev` pointer within the driver, and crucially, `dev->i2c_adap`, aren't freed. But the underlying `usb_device` *is* released. This is where it gets interesting.

So, picture this: I open `/dev/videoX`, artificially bumping the `v4l2_device`'s reference count. Then, I trigger a USB disconnect. The `usb_device` is now gone, freed by the system. But because `/dev/videoX` is still open, `au0828_dev` remains, so the `dev->i2c_adap` pointer is still valid... kind of.

Now, here's the kicker: I then try to access `dev->i2c_adap` through an I2C character device like `/dev/i2c-X`, or maybe it was already open. When the I2C adapter attempts to access its `adapter->dev.parent` pointer, which is supposed to point to the USB device, it's pointing to *freed memory*! That's it! That's the vulnerability I'm looking for! This is a classic use-after-free scenario.

The question then is, is this isolated to the `au0828` driver? I'd better expand this test to other drivers that deal with USB V4L2 devices. I'm going to check the `cx231xx` driver next.



64/2 2026/07/30 12:21 tool codesearch-definition-source
0m Args:
map[Name:cx231xx_usb_disconnect]

Results:
map[SourceCode:1926:	/*
1927:	 * cx231xx_usb_disconnect()
1928:	 * called when the device gets disconnected
1929:	 * video device will be unregistered on v4l2_close in case it is still open
1930:	 */
1931:	static void cx231xx_usb_disconnect(struct usb_interface *interface)
1932:	{
1933:		struct cx231xx *dev;
1934:	
1935:		dev = usb_get_intfdata(interface);
1936:		usb_set_intfdata(interface, NULL);
1937:	
1938:		if (!dev)
1939:			return;
1940:	
1941:		if (!dev->udev)
1942:			return;
1943:	
1944:		dev->state |= DEV_DISCONNECTED;
1945:	
1946:		flush_request_modules(dev);
1947:	
1948:		/* wait until all current v4l2 io is finished then deallocate
1949:		   resources */
1950:		mutex_lock(&dev->lock);
1951:	
1952:		wake_up_interruptible_all(&dev->open);
1953:	
1954:		if (dev->users) {
1955:			dev_warn(dev->dev,
1956:				 "device %s is open! Deregistration and memory deallocation are deferred on close.\n",
1957:				 video_device_node_name(&dev->vdev));
1958:	
1959:			/* Even having users, it is safe to remove the RC i2c driver */
1960:			cx231xx_ir_exit(dev);
1961:	
1962:			if (dev->USE_ISO)
1963:				cx231xx_uninit_isoc(dev);
1964:			else
1965:				cx231xx_uninit_bulk(dev);
1966:			wake_up_interruptible(&dev->wait_frame);
1967:			wake_up_interruptible(&dev->wait_stream);
1968:		} else {
1969:		}
1970:	
1971:		cx231xx_close_extension(dev);
1972:	
1973:		mutex_unlock(&dev->lock);
1974:	
1975:		if (!dev->users)
1976:			cx231xx_release_resources(dev);
1977:	}
 SourceFile:drivers/media/usb/cx231xx/cx231xx-cards.c]

65/2 2026/07/30 12:21 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 77316
							output: 29
							thoughts: 104
						

Thoughts:
**Resource Leakage in cx231xx Driver: A Deep Dive**

Okay, so I'm looking at this `cx231xx` driver code, and alarm bells are starting to go off. I'm seeing a potential resource leak, and it hinges on the `dev->users` counter. If `dev->users` is greater than zero, meaning someone still has a handle on this device, the `cx231xx_release_resources` function *isn't* called. This is the critical point.

Now, if `cx231xx_release_resources` doesn't run, the `dev` structure itself *isn't* freed. And that's not all. Crucially, the `dev->i2c_adap` pointer, which represents the I2C adapter associated with this device, also remains untouched and unfreed! This means we are leaking memory associated with the I2C adapter.

But here is where it gets interesting...

I think there may be an even more fundamental issue: The `usb_device` structure is freed, irrespective. So the USB device is gone, but the cx231xx-related resources remain, potentially orphaned. 

Now, I'm starting to wonder if the `cx231xx` driver, somewhere in its I2C initialization, might be setting the `adapter->dev.parent` to point to the USB device's device structure. Let me quickly double-check the `cx231xx_i2c_register` function, because if that's the case, we have a bigger problem than just a simple memory leak. I need to know how the parent/child relationship is being established here. This could become really messy, really fast. Let's see...



66/2 2026/07/30 12:21 tool codesearch-definition-source
0m Args:
map[Name:cx231xx_i2c_register]

Results:
map[SourceCode: 510:	/*
 511:	 * cx231xx_i2c_register()
 512:	 * register i2c bus
 513:	 */
 514:	int cx231xx_i2c_register(struct cx231xx_i2c *bus)
 515:	{
 516:		struct cx231xx *dev = bus->dev;
 517:	
 518:		if (!dev->cx231xx_send_usb_command)
 519:			return -EINVAL;
 520:	
 521:		bus->i2c_adap = cx231xx_adap_template;
 522:		bus->i2c_adap.dev.parent = dev->dev;
 523:	
 524:		snprintf(bus->i2c_adap.name, sizeof(bus->i2c_adap.name), "%s-%d", bus->dev->name, bus->nr);
 525:	
 526:		bus->i2c_adap.algo_data = bus;
 527:		i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
 528:		bus->i2c_rc = i2c_add_adapter(&bus->i2c_adap);
 529:	
 530:		if (0 != bus->i2c_rc)
 531:			dev_warn(dev->dev,
 532:				 "i2c bus %d register FAILED\n", bus->nr);
 533:	
 534:		return bus->i2c_rc;
 535:	}
 SourceFile:drivers/media/usb/cx231xx/cx231xx-i2c.c]

67/2 2026/07/30 12:21 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 78324
							output: 27
							thoughts: 43
						

Thoughts:
Okay, here's my interpretation of that line of code, as if it were my thought process:

**Diving into the Driver Structure**

Alright, let's break this down. `bus->i2c_adap.dev.parent = dev->dev;` - This line is assigning a parent device pointer in the I2C adapter structure. The `bus` variable looks like it refers to something USB related, and the assignment looks to be establishing the parent-child relationship.

The key question is what exactly `dev->dev` is representing. It's likely a structure within `dev` that contains the actual device's information within the broader context of the USB subsystem. I need to refresh my memory on the structure here. My gut says this is some kind of core device structure.

Let's check `cx231xx_usb_probe`, that should give me a good context to what `dev` actually is. Looking at the probe routine will show me the `dev` structure is likely what is being passed in. And that the assignment sets the proper parent for the I2C adapter, which makes perfect sense for USB devices.



68/2 2026/07/30 12:21 tool codesearch-definition-source
0m Args:
map[Name:cx231xx_usb_probe]

Results:
map[SourceCode:1685:	/*
1686:	 * cx231xx_usb_probe()
1687:	 * checks for supported devices
1688:	 */
1689:	static int cx231xx_usb_probe(struct usb_interface *interface,
1690:				     const struct usb_device_id *id)
1691:	{
1692:		struct usb_device *udev;
1693:		struct device *d = &interface->dev;
1694:		struct usb_interface *uif;
1695:		struct cx231xx *dev = NULL;
1696:		int retval = -ENODEV;
1697:		int nr = 0, ifnum;
1698:		int i, isoc_pipe = 0;
1699:		char *speed;
1700:		u8 idx;
1701:		struct usb_interface_assoc_descriptor *assoc_desc;
1702:	
1703:		ifnum = interface->altsetting[0].desc.bInterfaceNumber;
1704:	
1705:		/*
1706:		 * Interface number 0 - IR interface (handled by mceusb driver)
1707:		 * Interface number 1 - AV interface (handled by this driver)
1708:		 */
1709:		if (ifnum != 1)
1710:			return -ENODEV;
1711:	
1712:		/* Check to see next free device and mark as used */
1713:		do {
1714:			nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS);
1715:			if (nr >= CX231XX_MAXBOARDS) {
1716:				/* No free device slots */
1717:				dev_err(d,
1718:					"Supports only %i devices.\n",
1719:					CX231XX_MAXBOARDS);
1720:				return -ENOMEM;
1721:			}
1722:		} while (test_and_set_bit(nr, &cx231xx_devused));
1723:	
1724:		udev = interface_to_usbdev(interface);
1725:	
1726:		/* allocate memory for our device state and initialize it */
1727:		dev = devm_kzalloc(&interface->dev, sizeof(*dev), GFP_KERNEL);
1728:		if (dev == NULL) {
1729:			retval = -ENOMEM;
1730:			goto err_if;
1731:		}
1732:	
1733:		snprintf(dev->name, 29, "cx231xx #%d", nr);
1734:		dev->devno = nr;
1735:		dev->model = id->driver_info;
1736:		dev->video_mode.alt = -1;
1737:		dev->dev = d;
1738:	
1739:		cx231xx_set_model(dev);
1740:	
1741:		dev->interface_count++;
1742:		/* reset gpio dir and value */
1743:		dev->gpio_dir = 0;
1744:		dev->gpio_val = 0;
1745:		dev->xc_fw_load_done = 0;
1746:		dev->has_alsa_audio = 1;
1747:		dev->power_mode = -1;
1748:		atomic_set(&dev->devlist_count, 0);
1749:	
1750:		/* 0 - vbi ; 1 -sliced cc mode */
1751:		dev->vbi_or_sliced_cc_mode = 0;
1752:	
1753:		/* get maximum no.of IAD interfaces */
1754:		dev->max_iad_interface_count = udev->config->desc.bNumInterfaces;
1755:	
1756:		/* init CIR module TBD */
1757:	
1758:		/*mode_tv: digital=1 or analog=0*/
1759:		dev->mode_tv = 0;
1760:	
1761:		dev->USE_ISO = transfer_mode;
1762:	
1763:		switch (udev->speed) {
1764:		case USB_SPEED_LOW:
1765:			speed = "1.5";
1766:			break;
1767:		case USB_SPEED_UNKNOWN:
1768:		case USB_SPEED_FULL:
1769:			speed = "12";
1770:			break;
1771:		case USB_SPEED_HIGH:
1772:			speed = "480";
1773:			break;
1774:		default:
1775:			speed = "unknown";
1776:		}
1777:	
1778:		dev_info(d,
1779:			 "New device %s %s @ %s Mbps (%04x:%04x) with %d interfaces\n",
1780:			 udev->manufacturer ? udev->manufacturer : "",
1781:			 udev->product ? udev->product : "",
1782:			 speed,
1783:			 le16_to_cpu(udev->descriptor.idVendor),
1784:			 le16_to_cpu(udev->descriptor.idProduct),
1785:			 dev->max_iad_interface_count);
1786:	
1787:		/* increment interface count */
1788:		dev->interface_count++;
1789:	
1790:		/* get device number */
1791:		nr = dev->devno;
1792:	
1793:		assoc_desc = udev->actconfig->intf_assoc[0];
1794:		if (!assoc_desc || assoc_desc->bFirstInterface != ifnum) {
1795:			dev_err(d, "Not found matching IAD interface\n");
1796:			retval = -ENODEV;
1797:			goto err_if;
1798:		}
1799:	
1800:		dev_dbg(d, "registering interface %d\n", ifnum);
1801:	
1802:		/* save our data pointer in this interface device */
1803:		usb_set_intfdata(interface, dev);
1804:	
1805:		/* Initialize the media controller */
1806:		retval = cx231xx_media_device_init(dev, udev);
1807:		if (retval) {
1808:			dev_err(d, "cx231xx_media_device_init failed\n");
1809:			goto err_media_init;
1810:		}
1811:	
1812:		/* Create v4l2 device */
1813:	#ifdef CONFIG_MEDIA_CONTROLLER
1814:		dev->v4l2_dev.mdev = dev->media_dev;
1815:	#endif
1816:		retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
1817:		if (retval) {
1818:			dev_err(d, "v4l2_device_register failed\n");
1819:			goto err_v4l2;
1820:		}
1821:	
1822:		/* allocate device struct */
1823:		retval = cx231xx_init_dev(dev, udev, nr);
1824:		if (retval)
1825:			goto err_init;
1826:	
1827:		retval = cx231xx_init_v4l2(dev, udev, interface, isoc_pipe);
1828:		if (retval)
1829:			goto err_init;
1830:	
1831:		if (dev->current_pcb_config.ts1_source != 0xff) {
1832:			/* compute alternate max packet sizes for TS1 */
1833:			idx = dev->current_pcb_config.hs_config_info[0].interface_info.ts1_index + 1;
1834:			if (idx >= dev->max_iad_interface_count) {
1835:				dev_err(d, "TS1 PCB interface #%d doesn't exist\n",
1836:					idx);
1837:				retval = -ENODEV;
1838:				goto err_video_alt;
1839:			}
1840:			uif = udev->actconfig->interface[idx];
1841:	
1842:			if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) {
1843:				retval = -ENODEV;
1844:				goto err_video_alt;
1845:			}
1846:	
1847:			dev->ts1_mode.end_point_addr =
1848:			    uif->altsetting[0].endpoint[isoc_pipe].
1849:					desc.bEndpointAddress;
1850:	
1851:			dev->ts1_mode.num_alt = uif->num_altsetting;
1852:			dev_info(d,
1853:				 "TS EndPoint Addr 0x%x, Alternate settings: %i\n",
1854:				 dev->ts1_mode.end_point_addr,
1855:				 dev->ts1_mode.num_alt);
1856:	
1857:			dev->ts1_mode.alt_max_pkt_size = devm_kmalloc_array(&interface->dev, 32,
1858:									    dev->ts1_mode.num_alt,
1859:									    GFP_KERNEL);
1860:			if (dev->ts1_mode.alt_max_pkt_size == NULL) {
1861:				retval = -ENOMEM;
1862:				goto err_video_alt;
1863:			}
1864:	
1865:			for (i = 0; i < dev->ts1_mode.num_alt; i++) {
1866:				u16 tmp;
1867:	
1868:				if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) {
1869:					retval = -ENODEV;
1870:					goto err_video_alt;
1871:				}
1872:	
1873:				tmp = le16_to_cpu(uif->altsetting[i].
1874:							endpoint[isoc_pipe].desc.
1875:							wMaxPacketSize);
1876:				dev->ts1_mode.alt_max_pkt_size[i] =
1877:				    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
1878:				dev_dbg(d, "Alternate setting %i, max size= %i\n",
1879:					i, dev->ts1_mode.alt_max_pkt_size[i]);
1880:			}
1881:		}
1882:	
1883:		if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER) {
1884:			cx231xx_enable_OSC(dev);
1885:			cx231xx_reset_out(dev);
1886:			cx231xx_set_alt_setting(dev, INDEX_VIDEO, 3);
1887:		}
1888:	
1889:		if (dev->model == CX231XX_BOARD_CNXT_RDE_253S)
1890:			cx231xx_sleep_s5h1432(dev);
1891:	
1892:		/* load other modules required */
1893:		request_modules(dev);
1894:	
1895:	#ifdef CONFIG_MEDIA_CONTROLLER
1896:		/* Init entities at the Media Controller */
1897:		cx231xx_v4l2_create_entities(dev);
1898:	
1899:		retval = v4l2_mc_create_media_graph(dev->media_dev);
1900:		if (!retval)
1901:			retval = media_device_register(dev->media_dev);
1902:	#endif
1903:		if (retval < 0)
1904:			cx231xx_release_resources(dev);
1905:		return retval;
1906:	
1907:	err_video_alt:
1908:		/* cx231xx_uninit_dev: */
1909:		cx231xx_close_extension(dev);
1910:		cx231xx_ir_exit(dev);
1911:		cx231xx_release_analog_resources(dev);
1912:		cx231xx_417_unregister(dev);
1913:		cx231xx_remove_from_devlist(dev);
1914:		cx231xx_dev_uninit(dev);
1915:	err_init:
1916:		v4l2_device_unregister(&dev->v4l2_dev);
1917:	err_v4l2:
1918:		cx231xx_unregister_media_device(dev);
1919:	err_media_init:
1920:		usb_set_intfdata(interface, NULL);
1921:	err_if:
1922:		clear_bit(nr, &cx231xx_devused);
1923:		return retval;
1924:	}
 SourceFile:drivers/media/usb/cx231xx/cx231xx-cards.c]

69/2 2026/07/30 12:21 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 82451
							output: 23
							thoughts: 446
						

Thoughts:
**Analyzing a Kernel Use-After-Free Vulnerability**

Okay, let's break this down. We have a Use-After-Free (UAF) report and I need to figure out what's going on. The initial thought process began with `dev->dev = d;` where `d = &interface->dev;`. So, `cx231xx` sets `bus->i2c_adap.dev.parent = &interface->dev;`. I immediately realized that `interface->dev` is a `usb_interface`. But, the KASAN report is screaming about the UAF occurring on a `usb_device`, not the interface! That's a huge discrepancy. If the parent were a `usb_interface`, the allocation size for the parent should be `kmalloc-2k`, not the `kmalloc-4k` size associated with a `usb_device`. This means `cx231xx` *isn't* the culprit here.

Alright, let's pivot and examine `dvb_usb_device` closely. Examining the code, I see that `d->i2c_adap.dev.parent = &d->udev->dev;` - and `d->udev` *is* the `usb_device`. Perfect, this matches the reported UAF location. Furthermore, `dvb_usb_device` is freed in `dvb_usbv2_disconnect` with `kfree(d)`. But, hold on... if `d` is freed, then `d->i2c_adap` *should* be freed as well! Which means KASAN should have reported a UAF on `d` itself, which is `kmalloc-16k`. However, the report shows the UAF on `usb_device` (specifically `kmalloc-4k`) meaning that `d->i2c_adap` isn't freed! That is the core of the problem - why is `d->i2c_adap` not being freed? How is this even possible?

Maybe `d` *isn't* freed. I should reread `dvb_usbv2_disconnect`'s code again. I see it now:

```c
	if (d->props->disconnect)
		d->props->disconnect(d);

	kfree(d->priv);
	kfree(d);
```

Nope, `kfree(d)` *is* called. So, the `dvb_usb_device` itself *is* freed, which still doesn't explain how the adapter is left dangling, causing the UAF on the `usb_device`.

Alright, I'm at the point where I have to think more broadly. Is there another driver that dynamically allocates an `i2c_adapter` and sets its `parent` to the `usb_device`? Time to investigate and see if the `hdpvr` driver does something like this.



70/2 2026/07/30 12:21 tool codesearch-definition-source
0m Args:
map[Name:hdpvr_probe]

Results:
map[SourceCode: 264:	static int hdpvr_probe(struct usb_interface *interface,
 265:			       const struct usb_device_id *id)
 266:	{
 267:		struct hdpvr_device *dev;
 268:		struct usb_endpoint_descriptor *endpoint;
 269:	#if IS_ENABLED(CONFIG_I2C)
 270:		struct i2c_client *client;
 271:	#endif
 272:		int dev_num;
 273:		int retval = -ENOMEM;
 274:	
 275:		/* allocate memory for our device state and initialize it */
 276:		dev = kzalloc_obj(*dev);
 277:		if (!dev) {
 278:			dev_err(&interface->dev, "Out of memory\n");
 279:			goto error;
 280:		}
 281:	
 282:		/* init video transfer queues first of all */
 283:		/* to prevent oops in hdpvr_delete() on error paths */
 284:		INIT_LIST_HEAD(&dev->free_buff_list);
 285:		INIT_LIST_HEAD(&dev->rec_buff_list);
 286:	
 287:		/* register v4l2_device early so it can be used for printks */
 288:		if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) {
 289:			dev_err(&interface->dev, "v4l2_device_register failed\n");
 290:			goto error_free_dev;
 291:		}
 292:	
 293:		mutex_init(&dev->io_mutex);
 294:		mutex_init(&dev->i2c_mutex);
 295:		mutex_init(&dev->usbc_mutex);
 296:		dev->usbc_buf = kmalloc(64, GFP_KERNEL);
 297:		if (!dev->usbc_buf) {
 298:			v4l2_err(&dev->v4l2_dev, "Out of memory\n");
 299:			goto error_v4l2_unregister;
 300:		}
 301:	
 302:		init_waitqueue_head(&dev->wait_buffer);
 303:		init_waitqueue_head(&dev->wait_data);
 304:	
 305:		dev->options = hdpvr_default_options;
 306:	
 307:		if (default_video_input < HDPVR_VIDEO_INPUTS)
 308:			dev->options.video_input = default_video_input;
 309:	
 310:		if (default_audio_input < HDPVR_AUDIO_INPUTS) {
 311:			dev->options.audio_input = default_audio_input;
 312:			if (default_audio_input == HDPVR_SPDIF)
 313:				dev->options.audio_codec =
 314:					V4L2_MPEG_AUDIO_ENCODING_AC3;
 315:		}
 316:	
 317:		dev->udev = usb_get_dev(interface_to_usbdev(interface));
 318:	
 319:		/* set up the endpoint information */
 320:		/* use only the first bulk-in and bulk-out endpoints */
 321:		if (usb_find_bulk_in_endpoint(interface->cur_altsetting, &endpoint)) {
 322:			v4l2_err(&dev->v4l2_dev, "Could not find bulk-in endpoint\n");
 323:			goto error_put_usb;
 324:		}
 325:	
 326:		/*
 327:		 * USB interface description is buggy, reported max packet size is 512
 328:		 * bytes, windows driver uses 8192
 329:		 */
 330:		dev->bulk_in_size = 8192;
 331:		dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
 332:	
 333:		/* init the device */
 334:		if (hdpvr_device_init(dev)) {
 335:			v4l2_err(&dev->v4l2_dev, "device init failed\n");
 336:			goto error_put_usb;
 337:		}
 338:	
 339:		mutex_lock(&dev->io_mutex);
 340:		if (hdpvr_alloc_buffers(dev, NUM_BUFFERS)) {
 341:			mutex_unlock(&dev->io_mutex);
 342:			v4l2_err(&dev->v4l2_dev,
 343:				 "allocating transfer buffers failed\n");
 344:			goto error_put_usb;
 345:		}
 346:		mutex_unlock(&dev->io_mutex);
 347:	
 348:	#if IS_ENABLED(CONFIG_I2C)
 349:		retval = hdpvr_register_i2c_adapter(dev);
 350:		if (retval < 0) {
 351:			v4l2_err(&dev->v4l2_dev, "i2c adapter register failed\n");
 352:			goto error_free_buffers;
 353:		}
 354:	
 355:		client = hdpvr_register_ir_i2c(dev);
 356:		if (IS_ERR(client)) {
 357:			v4l2_err(&dev->v4l2_dev, "i2c IR device register failed\n");
 358:			retval = PTR_ERR(client);
 359:			goto reg_fail;
 360:		}
 361:	#endif
 362:	
 363:		dev_num = atomic_inc_return(&dev_nr);
 364:		if (dev_num >= HDPVR_MAX) {
 365:			v4l2_err(&dev->v4l2_dev,
 366:				 "max device number reached, device register failed\n");
 367:			atomic_dec(&dev_nr);
 368:			retval = -ENODEV;
 369:			goto reg_fail;
 370:		}
 371:	
 372:		retval = hdpvr_register_videodev(dev, &interface->dev,
 373:					    video_nr[dev_num]);
 374:		if (retval < 0) {
 375:			v4l2_err(&dev->v4l2_dev, "registering videodev failed\n");
 376:			goto reg_fail;
 377:		}
 378:	
 379:		/* let the user know what node this device is now attached to */
 380:		v4l2_info(&dev->v4l2_dev, "device now attached to %s\n",
 381:			  video_device_node_name(&dev->video_dev));
 382:		return 0;
 383:	
 384:	reg_fail:
 385:	#if IS_ENABLED(CONFIG_I2C)
 386:		i2c_del_adapter(&dev->i2c_adapter);
 387:	error_free_buffers:
 388:	#endif
 389:		hdpvr_free_buffers(dev);
 390:	error_put_usb:
 391:		usb_put_dev(dev->udev);
 392:		kfree(dev->usbc_buf);
 393:	error_v4l2_unregister:
 394:		v4l2_device_unregister(&dev->v4l2_dev);
 395:	error_free_dev:
 396:		kfree(dev);
 397:	error:
 398:		return retval;
 399:	}
 SourceFile:drivers/media/usb/hdpvr/hdpvr-core.c]

71/2 2026/07/30 12:21 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 85779
							output: 23
							thoughts: 33
						

Thoughts:
Here's a breakdown of my thought process:

**Diving into hdpvr_disconnect**

Okay, so I'm looking at the `hdpvr_probe` function. The first thing that jumps out is the allocation of `dev` using `kzalloc_obj(*dev)`. I need to remember that. It's allocated there via `kzalloc_obj`, which is important for understanding the lifecycle of this structure. Now, I want to see how that `dev` is handled on the disconnect path. I'm going to shift my focus to `hdpvr_disconnect` to understand how the driver cleans up after itself and, specifically, if the memory allocated for `dev` is properly freed. Understanding the pair of probe and disconnect gives a full picture of the driver's memory management.



72/2 2026/07/30 12:21 tool codesearch-definition-source
0m Args:
map[Name:hdpvr_disconnect]

Results:
map[SourceCode: 401:	static void hdpvr_disconnect(struct usb_interface *interface)
 402:	{
 403:		struct hdpvr_device *dev = to_hdpvr_dev(usb_get_intfdata(interface));
 404:	
 405:		v4l2_info(&dev->v4l2_dev, "device %s disconnected\n",
 406:			  video_device_node_name(&dev->video_dev));
 407:		/* prevent more I/O from starting and stop any ongoing */
 408:		mutex_lock(&dev->io_mutex);
 409:		dev->status = STATUS_DISCONNECTED;
 410:		wake_up_interruptible(&dev->wait_data);
 411:		wake_up_interruptible(&dev->wait_buffer);
 412:		mutex_unlock(&dev->io_mutex);
 413:		v4l2_device_disconnect(&dev->v4l2_dev);
 414:		msleep(100);
 415:		flush_work(&dev->worker);
 416:		mutex_lock(&dev->io_mutex);
 417:		hdpvr_cancel_queue(dev);
 418:		mutex_unlock(&dev->io_mutex);
 419:	#if IS_ENABLED(CONFIG_I2C)
 420:		i2c_del_adapter(&dev->i2c_adapter);
 421:	#endif
 422:		video_unregister_device(&dev->video_dev);
 423:		atomic_dec(&dev_nr);
 424:	}
 SourceFile:drivers/media/usb/hdpvr/hdpvr-core.c]

73/2 2026/07/30 12:21 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 86477
							output: 23
							thoughts: 52
						

Thoughts:
**My Concerns Regarding Device Deallocation in the HDPVR Driver**

Okay, so I'm digging into this `hdpvr_disconnect` function and something's immediately jumping out at me. I see that `hdpvr_disconnect` is responsible for unregistering the video device using `video_unregister_device(&dev->video_dev)`. However, it *doesn't* appear to free the `dev` pointer itself. That's a potential memory leak if we're not careful. This warrants further investigation, as a resource should always be deallocated after being unregistered.

The question then becomes: where *is* `dev` getting freed? I need to trace the lifecycle of this `dev` structure to ensure there's a corresponding `kfree` somewhere. My next step is to examine the `hdpvr_release` function. That seems like the most likely place where this crucial deallocation would occur. I need to understand the logic in `hdpvr_release` to confirm or refute my suspicion and confirm there are no memory management problems in the driver.



74/2 2026/07/30 12:21 tool codesearch-definition-source
0m Args:
map[Name:hdpvr_release]

Results:
map[SourceCode: 392:	static int hdpvr_release(struct file *file)
 393:	{
 394:		struct hdpvr_device *dev = video_drvdata(file);
 395:	
 396:		mutex_lock(&dev->io_mutex);
 397:		if (file_to_v4l2_fh(file) == dev->owner) {
 398:			hdpvr_stop_streaming(dev);
 399:			dev->owner = NULL;
 400:		}
 401:		mutex_unlock(&dev->io_mutex);
 402:	
 403:		return v4l2_fh_release(file);
 404:	}
 SourceFile:drivers/media/usb/hdpvr/hdpvr-video.c]

75/2 2026/07/30 12:21 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 87014
							output: 25
							thoughts: 40
						

Thoughts:
**Debugging Memory Management in `hdpvr`**

Okay, so I'm digging into this `hdpvr` code again. I was just reviewing the `hdpvr_release` function, and it suddenly hit me: wait a minute, this function *isn't* freeing the `dev` structure! I'm pretty sure I thought it did. Where *is* the memory allocated to `dev` being released? This is a critical point; a memory leak here would be pretty nasty. Alright, time to trace this down. Let's shift our focus to `hdpvr_device_release`, that seems like the next logical place to start looking. I'm hoping I'll find the answer in there.



76/2 2026/07/30 12:21 tool codesearch-definition-source
0m Args:
map[Name:hdpvr_device_release]

Results:
map[SourceCode:1130:	static void hdpvr_device_release(struct video_device *vdev)
1131:	{
1132:		struct hdpvr_device *dev = video_get_drvdata(vdev);
1133:	
1134:		hdpvr_delete(dev);
1135:		flush_work(&dev->worker);
1136:	
1137:		v4l2_device_unregister(&dev->v4l2_dev);
1138:		v4l2_ctrl_handler_free(&dev->hdl);
1139:	
1140:		/* deregister I2C adapter */
1141:	#if IS_ENABLED(CONFIG_I2C)
1142:		mutex_lock(&dev->i2c_mutex);
1143:		i2c_del_adapter(&dev->i2c_adapter);
1144:		mutex_unlock(&dev->i2c_mutex);
1145:	#endif /* CONFIG_I2C */
1146:	
1147:		kfree(dev->usbc_buf);
1148:		kfree(dev);
1149:	}
 SourceFile:drivers/media/usb/hdpvr/hdpvr-video.c]

77/2 2026/07/30 12:21 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 87587
							output: 29
							thoughts: 287
						

Thoughts:
**UAF Investigation - HDPVR Driver**

Okay, so I'm looking at this `hdpvr` driver code. Specifically, the cleanup process – I see that `hdpvr_device_release` calls `kfree(dev)`. That makes sense; it's the standard way to deallocate memory. And it's triggered when the `video_device` refcount hits zero.

But then I see something that makes me pause: `hdpvr_disconnect` also calls `i2c_del_adapter(&dev->i2c_adapter)`. And `hdpvr_device_release` *also* calls it! Now, that double call to `i2c_del_adapter` raises a red flag immediately. A double free situation is a classic bug. I wonder, is this somehow protected? We need to investigate.

The good news is that if `/dev/videoX` is kept open, `hdpvr_device_release` isn't called. Which means `dev` *isn't* freed. And that also means `dev->i2c_adapter` isn't freed either! But the `usb_device` *is* freed! Hmm, this is getting interesting.

Here's the idea: If we open `/dev/videoX`, disconnect the USB device, and *then* try to do an `I2C_SMBUS` ioctl on `/dev/i2c-X`, we could trigger a Use-After-Free (UAF) condition! That `i2c_adapter` struct is pointing to memory that's been freed. Let's see if we can trigger this UAF!

Hold on, I think I've got it. I recall that `hdpvr` sets `dev->i2c_adapter.dev.parent = &dev->udev->dev;` And `dev->udev` is the `usb_device`. So that perfectly matches the scenario: the I2C adapter's parent is the USB device.

Okay, let's take a look at the `pvrusb2` code too, just to be sure. I want to see if this pattern is re-used or a pattern of code reuse.



78/2 2026/07/30 12:21 tool codesearch-definition-source
0m Args:
map[Name:pvr2_i2c_core_init]

Results:
map[SourceCode: 591:	void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
 592:	{
 593:		unsigned int idx;
 594:	
 595:		/* The default action for all possible I2C addresses is just to do
 596:		   the transfer normally. */
 597:		for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) {
 598:			hdw->i2c_func[idx] = pvr2_i2c_basic_op;
 599:		}
 600:	
 601:		/* However, deal with various special cases for 24xxx hardware. */
 602:		if (ir_mode[hdw->unit_number] == 0) {
 603:			pr_info("%s: IR disabled\n", hdw->name);
 604:			hdw->i2c_func[0x18] = i2c_black_hole;
 605:		} else if (ir_mode[hdw->unit_number] == 1) {
 606:			if (hdw->ir_scheme_active == PVR2_IR_SCHEME_24XXX) {
 607:				/* Set up translation so that our IR looks like a
 608:				   29xxx device */
 609:				hdw->i2c_func[0x18] = i2c_24xxx_ir;
 610:			}
 611:		}
 612:		if (hdw->hdw_desc->flag_has_cx25840) {
 613:			hdw->i2c_func[0x44] = i2c_hack_cx25840;
 614:		}
 615:		if (hdw->hdw_desc->flag_has_wm8775) {
 616:			hdw->i2c_func[0x1b] = i2c_hack_wm8775;
 617:		}
 618:	
 619:		// Configure the adapter and set up everything else related to it.
 620:		hdw->i2c_adap = pvr2_i2c_adap_template;
 621:		hdw->i2c_algo = pvr2_i2c_algo_template;
 622:		strscpy(hdw->i2c_adap.name, hdw->name, sizeof(hdw->i2c_adap.name));
 623:		hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev;
 624:		hdw->i2c_adap.algo = &hdw->i2c_algo;
 625:		hdw->i2c_adap.algo_data = hdw;
 626:		hdw->i2c_linked = !0;
 627:		i2c_set_adapdata(&hdw->i2c_adap, &hdw->v4l2_dev);
 628:		i2c_add_adapter(&hdw->i2c_adap);
 629:		if (hdw->i2c_func[0x18] == i2c_24xxx_ir) {
 630:			/* Probe for a different type of IR receiver on this
 631:			   device.  This is really the only way to differentiate
 632:			   older 24xxx devices from 24xxx variants that include an
 633:			   IR blaster.  If the IR blaster is present, the IR
 634:			   receiver is part of that chip and thus we must disable
 635:			   the emulated IR receiver. */
 636:			if (do_i2c_probe(hdw, 0x71)) {
 637:				pvr2_trace(PVR2_TRACE_INFO,
 638:					   "Device has newer IR hardware; disabling unneeded virtual IR device");
 639:				hdw->i2c_func[0x18] = NULL;
 640:				/* Remember that this is a different device... */
 641:				hdw->ir_scheme_active = PVR2_IR_SCHEME_24XXX_MCE;
 642:			}
 643:		}
 644:		if (i2c_scan) do_i2c_scan(hdw);
 645:	
 646:		pvr2_i2c_register_ir(hdw);
 647:	}
 SourceFile:drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c]

79/2 2026/07/30 12:21 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 89632
							output: 27
							thoughts: 1882
						

Thoughts:
**Unraveling the I2C Adapter UAF Bug**

Okay, let's break this down. The fuzzer triggered a Use-After-Free (UAF) on a `usb_device`, and it looks like the culprit is in how I2C adapters are handled in relation to USB device lifecycles.

My initial thought is that `pvrusb2` sets `hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev;`, and `hdw` (likely the structure containing the I2C adapter) is freed when its reference count hits zero. If a `/dev/videoX` is open, `hdw` isn't freed. But that isn't the whole story.

The KASAN report indicates the `usb_device` itself is getting allocated, freed, and then resurrected as `skb->head` due to some side effect of the fuzzer. The critical flaw is in how an `i2c_adapter`'s `dev.parent` is linked to a `usb_device` which can be freed while the adapter is still alive. This means any driver that does this, and doesn't explicitly free the adapter when disconnecting, is vulnerable.

Let's check drivers like `au0828`, `hdpvr`, `pvrusb2`, `cx231xx`, `dvb_usb_v2`, and `dvb_usb`. `dvb_usb_v2` and `dvb_usb` free `d` which houses their I2C adapter in their `disconnect` function. But if `d` is freed while the adapter's still in use, KASAN should report UAF on `d`, which is the `kmalloc-16k` memory block. But the report says UAF on `usb_device`, which is the `kmalloc-4k` memory block. That means we should look at drivers which do *not* free the adapter in disconnect. `au0828`, `hdpvr`, and `pvrusb2` are the leading candidates.

`hdpvr` calls `i2c_del_adapter` during disconnect. Does `i2c_del_adapter` free the `i2c_adapter`? No, `i2c_del_adapter` unregisters the device, but the memory is freed with the containing struct. However, if the `/dev/i2c-X` device has been opened before the disconnect, `i2c_get_adapter` will have incremented the `adapter->dev`'s reference count. Then, during disconnect, `i2c_del_adapter` unregisters the device. `device_unregister` drops the parent's refcount (`usb_device`). If this was the last reference to `usb_device`, it is freed. But the adapter's refcount is still > 0, so the adapter itself is NOT freed. Then the `I2C_SMBUS` ioctl gets called on `/dev/i2c-X`, which calls through to `i2c_adapter_depth`, which accesses `adapter->dev.parent->type`. But `adapter->dev.parent` is now pointing to a freed `usb_device`!  This perfectly explains the KASAN UAF on `usb_device`!

This means any driver with that pattern is at risk! Now, let's explore the `dvb_usb_device` case. If `/dev/i2c-X` is open, `i2c_get_adapter` holds a reference to the adapter. However, the disconnect function frees `dvb_usb_device` and therefore also the adapter! This would be a UAF on `dvb_usb_device`, not the `usb_device`. Since the KASAN report is on `usb_device`, the driver must *not* be freeing the `i2c_adapter` on disconnect. This points back to `au0828`, `hdpvr`, and `pvrusb2`, as they do NOT free the struct on disconnect if `/dev/videoX` is open.

What if `/dev/videoX` is not open?  Does `i2c_get_adapter` prevent the struct from being freed? It calls `try_module_get` and `get_device`. This does not increment the refcount of the structure. So if `/dev/videoX` is *not* open, the driver's disconnect function *might* free the struct.  However, if the driver *does* free the struct in `disconnect`, it's still a bug because the adapter is still referenced. For example, `au0828` calls `au0


80/2 2026/07/30 12:22 tool codesearch-definition-source
0m Args:
map[Name:i2c_adapter_dev_release]

Results:
map[SourceCode:1231:	static void i2c_adapter_dev_release(struct device *dev)
1232:	{
1233:		struct i2c_adapter *adap = to_i2c_adapter(dev);
1234:		complete(&adap->dev_released);
1235:	}
 SourceFile:drivers/i2c/i2c-core-base.c]

81/2 2026/07/30 12:22 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 92685
							output: 25
							thoughts: 16
						

Thoughts:
Okay, here's the summarized thought process, as if it were my own, assuming the role of an expert:

**Concerning I2C Adapter Deletion and Completion**

Right, so `i2c_del_adapter` is the crucial function here. And the key thing to lock in is that, yes, it *does* wait for the completion of the operations it initiates. This isn't always obvious in all asynchronous contexts, so confirming this is essential for understanding the overall data flow and synchronization. I need to keep this in mind as I analyse the surrounding code; understanding if there are any race conditions here, and ensuring this synchronization is being handled correctly. This waiting behaviour is likely fundamental to maintaining data integrity and preventing resource corruption. So I'm glad this detail is clear in my mind.



82/2 2026/07/30 12:22 tool codesearch-definition-source
0m Args:
map[Name:i2c_del_adapter]

Results:
map[SourceCode:1795:	/**
1796:	 * i2c_del_adapter - unregister I2C adapter
1797:	 * @adap: the adapter being unregistered
1798:	 * Context: can sleep
1799:	 *
1800:	 * This unregisters an I2C adapter which was previously registered
1801:	 * by @i2c_add_adapter or @i2c_add_numbered_adapter.
1802:	 */
1803:	void i2c_del_adapter(struct i2c_adapter *adap)
1804:	{
1805:		struct i2c_adapter *found;
1806:	
1807:		/* First make sure that this adapter was ever added */
1808:		mutex_lock(&core_lock);
1809:		found = idr_find(&i2c_adapter_idr, adap->nr);
1810:		if (found == adap)
1811:			idr_replace(&i2c_adapter_idr, NULL, adap->nr);
1812:		mutex_unlock(&core_lock);
1813:		if (found != adap) {
1814:			pr_debug("attempting to delete unregistered adapter [%s]\n", adap->name);
1815:			return;
1816:		}
1817:	
1818:		i2c_acpi_remove_space_handler(adap);
1819:	
1820:		i2c_deregister_clients(adap);
1821:	
1822:		/* device name is gone after device_unregister */
1823:		dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
1824:	
1825:		pm_runtime_disable(&adap->dev);
1826:	
1827:		i2c_host_notify_irq_teardown(adap);
1828:	
1829:		debugfs_remove_recursive(adap->debugfs);
1830:	
1831:		/* wait until all references to the device are gone
1832:		 *
1833:		 * FIXME: This is old code and should ideally be replaced by an
1834:		 * alternative which results in decoupling the lifetime of the struct
1835:		 * device from the i2c_adapter, like spi or netdev do. Any solution
1836:		 * should be thoroughly tested with DEBUG_KOBJECT_RELEASE enabled!
1837:		 */
1838:		init_completion(&adap->dev_released);
1839:		device_unregister(&adap->dev);
1840:		wait_for_completion(&adap->dev_released);
1841:	
1842:		/* free bus id */
1843:		mutex_lock(&core_lock);
1844:		idr_remove(&i2c_adapter_idr, adap->nr);
1845:		mutex_unlock(&core_lock);
1846:	
1847:		/* Clear the device structure in case this adapter is ever going to be
1848:		   added again */
1849:		memset(&adap->dev, 0, sizeof(adap->dev));
1850:	}
 SourceFile:drivers/i2c/i2c-core-base.c]

83/2 2026/07/30 12:22 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 93788
							output: 29
							thoughts: 2645
						

Thoughts:
**The I2C Adapter UAF Saga**

Okay, so here's the breakdown of this frustrating I2C adapter Use-After-Free (UAF) situation. It all revolves around how the `i2c_del_adapter` function interacts with the USB device removal process. My initial thought process was:

1.  `i2c_del_adapter` blocks until all references to the I2C adapter's device are gone. Makes sense.
2.  If `/dev/i2c-X` (the character device) is open, the reference count for the adapter increases with `i2c_get_adapter`. Then `i2c_del_adapter` blocks. That's a problem in the `disconnect` callback if it has to block.
3.  That block causes the entire USB device disconnect to block in the `disconnect` function. That cannot be right. The USB device is not freed if disconnect blocks! But the KASAN report indicates it IS freed.  That's a contradiction.
4.  Then I started tracing the refcounts of the `usb_device`, specifically considering `usb_disconnect` and how the device is un-registered.
5.  I had to think about how parents are handled: `device_unregister` calls `device_del` which calls `put_device(parent)`.  If the "parent" of the I2C adapter is the `usb_device`, then the refcount of `usb_device` drops.  But when?
6.  The `usb_device` is referenced by the USB core.  So, even if the parent reference drops, it is still being referenced.
7.  `usb_disconnect` calls `device_del(&udev->dev)`, which drops the reference to the parent. That is the USB driver's device structure.
8.  I asked myself, when does the `udev` refcount drop to 0?  That happens in `usb_release_dev`.
9.  If `i2c_del_adapter` is called *during* `usb_disconnect`, it has to be called inside `disconnect` so how can it work?
10. So I went back and went through the logic.  I realized `i2c_del_adapter` does **not** call `put_device(udev)` **directly**. I traced the `put_device` function from both `usb_disconnect` and `device_unregister`.
11. Here's the key: What if the driver doesn't call `i2c_del_adapter` directly from the `disconnect` callback, but instead calls it from a *different* callback, like a release callback?
12. Aha!  If the driver calls `i2c_del_adapter` later, the USB device's resources might be freed *before* the I2C adapter is unregistered.  The driver in this case will be at fault.
13.  If `/dev/videoX` is open, the driver's `disconnect` returns without calling `i2c_del_adapter`.
14.  `usb_disconnect` continues!
15.  `usb_disconnect` calls `device_del(&intf->dev)`, which drops the `udev` refcount and then finishes and calls `put_device(&udev->dev)`.  The `udev` is freed.  BUT the I2C adapter is STILL registered.
16.  This is where the UAF happens: We try to use `/dev/i2c-X`, and it accesses `adapter->dev.parent->type` which is accessing the freed `udev` memory. BINGO!

**Identifying the Culprit**

So, the key is finding a driver that:

*   Defers `i2c_del_adapter` to a release callback, usually if there are open users.
*   Does *not* call `i2c_del_adapter` directly in `disconnect` if users are present.

`au0828` does exactly that.  It calls `au0828_usb_release` from `au0828_usb_v4l2_release`, which is called when the `v4l2_device` refcount drops.  If V4L2 is enabled, the adapter is never un-registered in disconnect.

**Verification and Reproducibility**

I verified that `au0828` indeed defers the unregistration.

`pvrusb2` is complex.

`hdpvr` does not appear to be the same, because it calls `i2c_del_adapter` directly from `disconnect`.

The best candidate for a reproducer is `au082


84/2 2026/07/30 12:22 tool codesearch-definition-source
0m Args:
map[Name:au0828_usb_id_table]

Results:
map[SourceCode: 351:	/* table of devices that work with this driver */
 352:	struct usb_device_id au0828_usb_id_table[] = {
 353:		{ USB_DEVICE(0x2040, 0x7200),
 354:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 355:		{ USB_DEVICE(0x2040, 0x7240),
 356:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 },
 357:		{ USB_DEVICE(0x0fe9, 0xd620),
 358:			.driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 },
 359:		{ USB_DEVICE(0x2040, 0x7210),
 360:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 361:		{ USB_DEVICE(0x2040, 0x7217),
 362:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 363:		{ USB_DEVICE(0x2040, 0x721b),
 364:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 365:		{ USB_DEVICE(0x2040, 0x721e),
 366:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 367:		{ USB_DEVICE(0x2040, 0x721f),
 368:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 369:		{ USB_DEVICE(0x2040, 0x7280),
 370:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 371:		{ USB_DEVICE(0x0fd9, 0x0008),
 372:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 373:		{ USB_DEVICE(0x2040, 0x7201),
 374:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
 375:		{ USB_DEVICE(0x2040, 0x7211),
 376:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
 377:		{ USB_DEVICE(0x2040, 0x7281),
 378:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
 379:		{ USB_DEVICE(0x05e1, 0x0480),
 380:			.driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY },
 381:		{ USB_DEVICE(0x2040, 0x8200),
 382:			.driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY },
 383:		{ USB_DEVICE(0x2040, 0x7260),
 384:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 385:		{ USB_DEVICE(0x2040, 0x7213),
 386:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 387:		{ USB_DEVICE(0x2040, 0x7270),
 388:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 389:		{ USB_DEVICE(0x2040, 0x72b0),
 390:			.driver_info = AU0828_BOARD_HAUPPAUGE_IMPACTVCBE },
 391:		{ USB_DEVICE(0x2040, 0x72a0),
 392:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR1265 },
 393:		{ },
 394:	};
 SourceFile:drivers/media/usb/au0828/au0828-cards.c]

85/2 2026/07/30 12:22 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 98784
							output: 19
							thoughts: 154
						

Thoughts:
**Reproducer Design for USB and I2C Interaction**

Okay, so I'm thinking, let's start with those addresses: `0x2040, 0x7200`. Now, how do I actually build this syzkaller reproducer? Right, the USB device. I can use `syz_usb_connect` to attach the device. Then, I need to open the relevant device file – something like `/dev/video0`, or whatever gets created. After that, disconnect it with `syz_usb_disconnect`. Next, I'll need to open something like `/dev/i2c-0`, the I2C interface. Finally, I'll use `ioctl(fd, I2C_SMBUS, ...)` for the I2C transaction.

Hmm, a quick check. Ah yes, `syz_usb_connect` and `syz_usb_disconnect` are pseudo-syscalls. Fine, I'll just double-check the syntax of `syz_usb_connect` to make sure I get that right.



86/2 2026/07/30 12:23 tool read-description
0m Args:
map[File:vusb.txt]

Results:
map[Output:# Copyright 2019 syzkaller project authors. All rights reserved.
# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

include <linux/types.h>
include <linux/byteorder/generic.h>

include <uapi/linux/usb/ch9.h>
include <uapi/linux/usb/ch11.h>

include <uapi/linux/usb/midi.h>
include <uapi/linux/usb/audio.h>
include <linux/usb/audio-v2.h>
include <linux/usb/audio-v3.h>
include <uapi/linux/hid.h>
include <linux/hid.h>
include <uapi/linux/usb/cdc.h>
include <uapi/linux/if_ether.h>
include <linux/interrupt.h>
include <linux/usb/cdc_ncm.h>
include <drivers/net/usb/asix.h>

# This is a special fd for USB fuzzing and should only be used with syz_usb_* pseudo-syscalls.
# We don't inherit it from the fd resource, to discourage syzkaller calling raw ioctls on it.
resource fd_usb[int32]: -1

# These are generic pseudo-syscalls for emulating arbitrary USB devices.
# They are mostly targeted to cover the enumeration process.
syz_usb_connect(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io(fd fd_usb, descs ptr[in, vusb_descriptors], resps ptr[in, vusb_responses]) (timeout[300], remote_cover)
syz_usb_ep_write(fd fd_usb, ep int8, len len[data], data ptr[in, array[int8, 0:256]]) (timeout[300], remote_cover)
syz_usb_ep_read(fd fd_usb, ep int8, len len[data], data buffer[out]) (timeout[300], remote_cover)
syz_usb_disconnect(fd fd_usb) (timeout[300], remote_cover)

usb_device_speed = USB_SPEED_UNKNOWN, USB_SPEED_LOW, USB_SPEED_FULL, USB_SPEED_HIGH, USB_SPEED_WIRELESS, USB_SPEED_SUPER, USB_SPEED_SUPER_PLUS

# TODO: consider patching idVendor and idProduct for all class specific descriptions in Go code to cover more drivers.
# TODO: custom syz_usb_ep_write() descriptions for all class specific descriptions.
# TODO: consider adding custom vusb_connect_descriptors definitions to all class specific descriptions.

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

type usb_device_descriptor_verbose_t[USB, CLASS, SUBCLASS, PROTOCOL, PACKET, VENDOR, PRODUCT, DEVICE, CFS] {
	bLength			const[USB_DT_DEVICE_SIZE, int8]
	bDescriptorType		const[USB_DT_DEVICE, int8]

	bcdUSB			USB
	bDeviceClass		const[CLASS, int8]
	bDeviceSubClass		const[SUBCLASS, int8]
	bDeviceProtocol		const[PROTOCOL, int8]
	bMaxPacketSize0		PACKET
	idVendor		const[VENDOR, int16]
	idProduct		const[PRODUCT, int16]
	bcdDevice		const[DEVICE, int16]
	iManufacturer		const[1, int8]
	iProduct		const[2, int8]
	iSerialNumber		const[3, int8]
	bNumConfigurations	len[configs, int8]

	configs			CFS
} [packed]

type usb_device_descriptor_t[CLASS, SUBCLASS, PROTOCOL, VENDOR, PRODUCT, DEVICE, CFS] usb_device_descriptor_verbose_t[flags[usb_versions, int16], CLASS, SUBCLASS, PROTOCOL, flags[usb_device_max_packet_sizes, int8], VENDOR, PRODUCT, DEVICE, CFS]
type usb_device_descriptor_fixed_t[USB, CLASS, SUBCLASS, PROTOCOL, PACKET, VENDOR, PRODUCT, DEVICE, CFS] usb_device_descriptor_verbose_t[const[USB, int16], CLASS, SUBCLASS, PROTOCOL, const[PACKET, int8], VENDOR, PRODUCT, DEVICE, CFS]

usb_versions = 0x110, 0x200, 0x201, 0x250, 0x300, 0x310

# https://elixir.bootlin.com/linux/v5.1.7/source/drivers/usb/core/hub.c#L4661
usb_device_max_packet_sizes = 8, 16, 32, 64, 255

type usb_config_descriptor_verbose_t[NUM, IFSNUM, ICONFIG, ATTRS, POWER, EXTRA, IFS] {
	bLength			const[USB_DT_CONFIG_SIZE, int8]
	bDescriptorType		const[USB_DT_CONFIG, int8]

	wTotalLength		len[parent, int16]
	bNumInterfaces		IFSNUM
	bConfigurationValue	NUM
	iConfiguration		ICONFIG
	bmAttributes		ATTRS
	bMaxPower		POWER

	extra			EXTRA
	interfaces		IFS
} [packed]

type usb_config_descriptor_t[NUM, IFSNUM, IFS] usb_config_descriptor_verbose_t[NUM, IFSNUM, int8, flags[usb_config_attributes, int8], int8, void, IFS]
type usb_config_descriptor_ifaces_array_t[NUM, IFS] usb_config_descriptor_t[NUM, len[interfaces, int8], IFS]
type usb_config_descriptor_fixed_t[NUM, IFSNUM, ATTRS, POWER, IFS] usb_config_descriptor_verbose_t[const[NUM, int8], const[IFSNUM, int8], const[0, int8], const[ATTRS, int8], const[POWER, int8], void, IFS]
type usb_config_descriptor_extra_t[NUM, IFSNUM, EXTRA, IFS] usb_config_descriptor_verbose_t[NUM, IFSNUM, int8, flags[usb_config_attributes, int8], int8, EXTRA, IFS]

type usb_interface_descriptor_verbose_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, IIF, EXTRA, EPS] {
	bLength			const[USB_DT_INTERFACE_SIZE, int8]
	bDescriptorType		const[USB_DT_INTERFACE, int8]

	bInterfaceNumber	IFNUM
	bAlternateSetting	ALTNUM
	bNumEndpoints		EPSNUM
	bInterfaceClass		CLASS
	bInterfaceSubClass	SUBCLASS
	bInterfaceProtocol	PROTOCOL
	iInterface		IIF

	extra			EXTRA
	endpoints		EPS
} [packed]

type usb_interface_descriptor_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS] usb_interface_descriptor_verbose_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, int8, EXTRA, EPS]
type usb_interface_descriptor_eps_array_t[IFNUM, ALTNUM, CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS] usb_interface_descriptor_t[IFNUM, ALTNUM, len[endpoints, int8], CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS]
type usb_interface_descriptor_fixed_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS] usb_interface_descriptor_verbose_t[const[IFNUM, int8], const[ALTNUM, int8], const[EPSNUM, int8], const[CLASS, int8], const[SUBCLASS, int8], const[PROTOCOL, int8], const[0, int8], EXTRA, EPS]

# TODO: non-audio endpoints have USB_DT_ENDPOINT_SIZE.
type usb_endpoint_descriptor_verbose_t[ADDR, ATTRS, PACKET, INTERVAL, REFRESH, SYNCH, EXTRA] {
	bLength			const[USB_DT_ENDPOINT_AUDIO_SIZE, int8]
	bDescriptorType		const[USB_DT_ENDPOINT, int8]

	bEndpointAddress	ADDR
	bmAttributes		ATTRS
	wMaxPacketSize		PACKET
	bInterval		INTERVAL

	bRefresh		REFRESH
	bSynchAddress		SYNCH

	extra			EXTRA
} [packed]

type usb_endpoint_descriptor_t[ADDR, ATTRS, EXTRA] usb_endpoint_descriptor_verbose_t[ADDR, ATTRS, flags[usb_endpoint_max_packet_sizes, int16], int8, int8, int8, EXTRA]
type usb_endpoint_descriptor_fixed_t[ADDR, ATTRS, PACKET, INTERVAL, EXTRA] usb_endpoint_descriptor_verbose_t[const[ADDR, int8], const[ATTRS, int8], const[PACKET, int16], const[INTERVAL, int8], const[0, int8], const[0, int8], EXTRA]

# TODO: dummy driver has complex requirements for packet sizes, account for those:
# https://elixir.bootlin.com/linux/v5.3.6/source/drivers/usb/gadget/udc/dummy_hcd.c#L497
usb_endpoint_max_packet_sizes = 8, 16, 32, 64, 512, 1023, 1024

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Generic USB device, configuration, interface and endpoint descriptors.

# We only support one configuration per device.
# bDeviceClass, bDeviceSubClass, bDeviceProtocol, idVendor, idProduct
# and bcdDevice are patched by Go code, see sys/linux/init_vusb.go.
usb_device_descriptor {
	inner	usb_device_descriptor_t[0, 0, 0, 0, 0, 0, array[usb_config_descriptor, 1]]
} [packed]

usb_config_descriptor {
	inner	usb_config_descriptor_ifaces_array_t[int8, array[usb_interface_descriptor, 1:4]]
} [packed]

usb_config_attributes = USB_CONFIG_ATT_ONE, USB_CONFIG_ATT_SELFPOWER, USB_CONFIG_ATT_WAKEUP, USB_CONFIG_ATT_BATTERY

# bInterfaceNumber, bInterfaceClass, bInterfaceSubClass and bInterfaceProtocol
# are patched by Go code, see sys/linux/init_vusb.go.
usb_interface_descriptor {
	inner	usb_interface_descriptor_eps_array_t[int8, int8, const[0, int8], const[0, int8], const[0, int8], array[usb_interface_extra_descriptor, 0:2], array[usb_endpoint_descriptor, 0:16]]
} [packed]

usb_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], flags[usb_endpoint_attributes, int8], array[usb_endpoint_extra_descriptor, 0:2]]
} [packed]

usb_endpoint_addresses = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, USB_DIR_OUT, USB_DIR_IN

usb_endpoint_attributes = USB_ENDPOINT_XFER_CONTROL, USB_ENDPOINT_XFER_ISOC, USB_ENDPOINT_XFER_BULK, USB_ENDPOINT_XFER_INT, USB_ENDPOINT_INTR_PERIODIC, USB_ENDPOINT_INTR_NOTIFICATION, USB_ENDPOINT_SYNC_NONE, USB_ENDPOINT_SYNC_ASYNC, USB_ENDPOINT_SYNC_ADAPTIVE, USB_ENDPOINT_SYNC_SYNC, USB_ENDPOINT_USAGE_DATA, USB_ENDPOINT_USAGE_FEEDBACK, USB_ENDPOINT_USAGE_FEEDBACK

vusb_connect_descriptors {
	qual_len	len[qual, int32]
	qual		ptr[in, usb_qualifier_descriptor]
	bos_len		len[bos, int32]
	bos		ptr[in, usb_bos_descriptor]
	strs_len	len[strs, int32]
	strs		array[vusb_connect_string_descriptor]
} [packed]

vusb_connect_string_descriptor {
	len	len[str, int32]
	str	ptr[in, usb_string_descriptor]
} [packed]

vusb_descriptors {
	len	len[parent, int32]
	generic	ptr[in, vusb_descriptor_generic]

	string	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
	bos	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_BOS, usb_bos_descriptor]]

	hub_hs	ptr[in, vusb_descriptor_t[USB_TYPE_CLASS, USB_DT_HUB, usb_hub_descriptor_hs]]
	hub_ss	ptr[in, vusb_descriptor_t[USB_TYPE_CLASS, USB_DT_SS_HUB, usb_hub_descriptor_ss]]
} [packed]

vusb_descriptor_generic {
	req_type	flags[usb_request_types, int8]
	desc_type	flags[usb_descriptor_types, int8]
	len		bytesize[data, int32]
	data		usb_generic_descriptor
} [packed]

usb_request_types = USB_TYPE_STANDARD, USB_TYPE_CLASS, USB_TYPE_VENDOR

type vusb_descriptor_t[CLASS, REQ, DATA] {
	type	const[CLASS, int8]
	req	const[REQ, int8]
	len	bytesize[data, int32]
	data	DATA
} [packed]

# TODO: consider doing lookups based on USB_RECIP values.
vusb_responses {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	get_interface			ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	get_configuration		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

# TODO: move these into custom descriptions for hub class when they are added.
	hub_USB_REQ_GET_STATUS_hub	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_REQ_GET_STATUS, usb_hub_status]]
	hub_USB_REQ_GET_STATUS_port	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_REQ_GET_STATUS, usb_port_status]]

# TODO: move these into custom descriptions for asix driver when they are added.
	asix_AX_CMD_READ_MII_REG	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_MII_REG, int16]]
	asix_AX_CMD_STATMNGSTS_REG	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_STATMNGSTS_REG, int8]]
	asix_AX_CMD_READ_EEPROM		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_EEPROM, array[int8, 2]]]
	asix_AX_CMD_READ_RX_CTL		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_RX_CTL, int16]]
	asix_AX_CMD_READ_NODE_ID	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_NODE_ID, mac_addr]]
	asix_AX88172_CMD_READ_NODE_ID	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX88172_CMD_READ_NODE_ID, mac_addr]]
	asix_AX_CMD_READ_PHY_ID		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_PHY_ID, array[int8, 2]]]
	asix_AX_CMD_READ_MEDIUM_STATUS	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_MEDIUM_STATUS, int16]]
	asix_AX_CMD_READ_MONITOR_MODE	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_MONITOR_MODE, int8]]
	asix_AX_CMD_READ_GPIOS		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_GPIOS, int8]]
	asix_AX_CMD_SW_PHY_STATUS	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_SW_PHY_STATUS, int8]]
} [packed]

vusb_response_generic {
	type	flags[usb_request_types, int8]
	req	flags[usb_requests, int8]
	len	bytesize[data, int32]
	data	array[int8, 0:256]
} [packed]

usb_requests = USB_REQ_GET_STATUS, USB_REQ_CLEAR_FEATURE, USB_REQ_SET_FEATURE, USB_REQ_SET_ADDRESS, USB_REQ_GET_DESCRIPTOR, USB_REQ_SET_DESCRIPTOR, USB_REQ_GET_CONFIGURATION, USB_REQ_SET_CONFIGURATION, USB_REQ_GET_INTERFACE, USB_REQ_SET_INTERFACE, USB_REQ_SYNCH_FRAME, USB_REQ_SET_SEL, USB_REQ_SET_ISOCH_DELAY, USB_REQ_SET_ENCRYPTION, USB_REQ_GET_ENCRYPTION, USB_REQ_RPIPE_ABORT, USB_REQ_SET_HANDSHAKE, USB_REQ_RPIPE_RESET, USB_REQ_GET_HANDSHAKE, USB_REQ_SET_CONNECTION, USB_REQ_SET_SECURITY_DATA, USB_REQ_GET_SECURITY_DATA, USB_REQ_SET_WUSB_DATA, USB_REQ_LOOPBACK_DATA_WRITE, USB_REQ_LOOPBACK_DATA_READ, USB_REQ_SET_INTERFACE_DS, USB_REQ_GET_PARTNER_PDO, USB_REQ_GET_BATTERY_STATUS, USB_REQ_SET_PDO, USB_REQ_GET_VDM, USB_REQ_SEND_VDM

type vusb_response_t[CLASS, REQ, DATA] {
	type	const[CLASS, int8]
	req	const[REQ, int8]
	len	bytesize[data, int32]
	data	DATA
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# USB descriptors requested by the kernel before the SET_CONFIGURATION request.

# TODO: figure out when is the USB_DT_OTG descriptor used.
# TODO: figure out when is the USB_DT_INTERFACE_ASSOCIATION descriptor used.
# TODO: figure out when is the USB_DT_BOS descriptor used.

type usb_string_descriptor_t[DATA] {
	bLength		len[parent, int8]
	bDescriptorType	const[USB_DT_STRING, int8]

	data		DATA
} [packed]

usb_string_descriptor [
	lang_id	usb_string_descriptor_t[flags[usb_lang_ids, int16]]
	string	usb_string_descriptor_t[array[int8, 0:256]]
] [varlen]

usb_lang_ids = 0x436, 0x41c, 0x401, 0x801, 0xc01, 0x1001, 0x1401, 0x1801, 0x1c01, 0x2001, 0x2401, 0x2801, 0x2c01, 0x3001, 0x3401, 0x3801, 0x3c01, 0x4001, 0x42b, 0x44d, 0x42c, 0x82c, 0x42d, 0x423, 0x445, 0x402, 0x455, 0x403, 0x404, 0x804, 0xc04, 0x1004, 0x1404, 0x41a, 0x405, 0x406, 0x413, 0x813, 0x409, 0x809, 0xc09, 0x1009, 0x1409, 0x1809, 0x1c09, 0x2009, 0x2409, 0x2809, 0x2c09, 0x3009, 0x3409, 0x425, 0x438, 0x429, 0x40b, 0x40c, 0x80c, 0xc0c, 0x100c, 0x140c, 0x180c, 0x437, 0x407, 0x807, 0xc07, 0x1007, 0x1407, 0x408, 0x447, 0x40d, 0x439, 0x40e, 0x40f, 0x421, 0x410, 0x810, 0x411, 0x44b, 0x860, 0x43f, 0x457, 0x412, 0x812, 0x426, 0x427, 0x827, 0x42f, 0x43e, 0x83e, 0x44c, 0x458, 0x44e, 0x861, 0x414, 0x814, 0x448, 0x415, 0x416, 0x816, 0x446, 0x418, 0x419, 0x44f, 0xc1a, 0x81a, 0x459, 0x41b, 0x424, 0x40a, 0x80a, 0xc0a, 0x100a, 0x140a, 0x180a, 0x1c0a, 0x200a, 0x240a, 0x280a, 0x2c0a, 0x300a, 0x340a, 0x380a, 0x3c0a, 0x400a, 0x440a, 0x480a, 0x4c0a, 0x500a, 0x430, 0x441, 0x41d, 0x81d, 0x449, 0x444, 0x44a, 0x41e, 0x41f, 0x422, 0x420, 0x820, 0x443, 0x843, 0x42a, 0x4ff, 0xf0ff, 0xf4ff, 0xf8ff, 0xfcff

usb_qualifier_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_QUALIFIER, int8]

	bcdUSB			flags[usb_versions, int16]
	bDeviceClass		int8
	bDeviceSubClass		int8
	bDeviceProtocol		int8
	bMaxPacketSize0		flags[usb_device_max_packet_sizes, int8]
	bNumConfigurations	int8
	bRESERVED		const[0, int8]
} [packed]

usb_bos_descriptor {
	bLength		const[USB_DT_BOS_SIZE, int8]
	bDescriptorType	const[USB_DT_BOS, int8]

	wTotalLength	len[parent, int16]
	bNumDeviceCaps	len[caps, int8]

	caps		array[usb_dev_cap, 0:6]
} [packed]

usb_dev_cap [
	generic		usb_generic_cap_descriptor
	wireless	usb_wireless_cap_descriptor
	ext_cap		usb_ext_cap_descriptor
	ss_cap		usb_ss_cap_descriptor
	ss_container_id	usb_ss_container_id_descriptor
	ssp_cap		usb_ssp_cap_descriptor
	ptm_cap		usb_ptm_cap_descriptor
] [varlen]

usb_generic_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	flags[usb_capability_types, int8]

	data			array[int8, 0:256]
} [packed]

usb_capability_types = USB_CAP_TYPE_WIRELESS_USB, USB_CAP_TYPE_EXT, USB_SS_CAP_TYPE, USB_SSP_CAP_TYPE, CONTAINER_ID_TYPE, USB_PTM_CAP_TYPE

usb_wireless_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_CAP_TYPE_WIRELESS_USB, int8]

	bmAttributes		flags[usb_wireless_cap_attributes, int8]
	wPHYRates		flags[usb_wireless_cap_phyrates, int16]
	bmTFITXPowerInfo	int8
	bmFFITXPowerInfo	int8
	bmBandGroup		int16
	bReserved		int8
} [packed]

usb_wireless_cap_attributes = USB_WIRELESS_P2P_DRD, USB_WIRELESS_BEACON_MASK, USB_WIRELESS_BEACON_SELF, USB_WIRELESS_BEACON_DIRECTED, USB_WIRELESS_BEACON_NONE

usb_wireless_cap_phyrates = USB_WIRELESS_PHY_53, USB_WIRELESS_PHY_80, USB_WIRELESS_PHY_107, USB_WIRELESS_PHY_160, USB_WIRELESS_PHY_200, USB_WIRELESS_PHY_320, USB_WIRELESS_PHY_400, USB_WIRELESS_PHY_480

usb_ext_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_CAP_TYPE_EXT, int8]

	bmAttributes1		flags[usb_ext_cap_attributes, int32:8]
	bmAttributes2		int32:4
	bmAttributes3		int32:4
	bmAttributes4		int32:16
} [packed]

usb_ext_cap_attributes = USB_LPM_SUPPORT, USB_BESL_SUPPORT, USB_BESL_BASELINE_VALID, USB_BESL_DEEP_VALID

usb_ss_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_SS_CAP_TYPE, int8]

	bmAttributes		flags[usb_ss_cap_attributes, int8]
	wSpeedSupported		flags[usb_ss_cap_speed, int16]
	bFunctionalitySupport	int8
	bU1devExitLat		int8
	bU2DevExitLat		int16
} [packed]

usb_ss_cap_attributes = USB_LTM_SUPPORT

usb_ss_cap_speed = USB_LOW_SPEED_OPERATION, USB_FULL_SPEED_OPERATION, USB_HIGH_SPEED_OPERATION, USB_5GBPS_OPERATION

usb_ss_container_id_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[CONTAINER_ID_TYPE, int8]

	bReserved		int8
	ContainerID		array[int8, 16]
} [packed]

usb_ssp_cap_descriptor {
	bLength				len[parent, int8]
	bDescriptorType			const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType		const[USB_SSP_CAP_TYPE, int8]

	bReserved			int8
	bmAttributesSublinkSpeeds	len[bmSublinkSpeedAttr, int32:5]
	bmAttributesSpeedIDs		int32:27
	wFunctionalitySupport		flags[usb_ssp_cap_funcs, int16]
	wReserved			int16
	bmSublinkSpeedAttr		array[flags[usb_ssp_cap_sublink_speeds, int32], 0:6]
} [packed]

usb_ssp_cap_funcs = USB_SSP_MIN_SUBLINK_SPEED_ATTRIBUTE_ID, USB_SSP_MIN_RX_LANE_COUNT, USB_SSP_MIN_TX_LANE_COUNT

usb_ssp_cap_sublink_speeds = USB_SSP_SUBLINK_SPEED_SSID, USB_SSP_SUBLINK_SPEED_LSE, USB_SSP_SUBLINK_SPEED_ST, USB_SSP_SUBLINK_SPEED_RSVD, USB_SSP_SUBLINK_SPEED_LP, USB_SSP_SUBLINK_SPEED_LSM

usb_ptm_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_PTM_CAP_TYPE, int8]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Extra USB descriptors that come after an interface or an endpoint descriptor.

# TODO: consider removing class specific descriptors here for described classes.
usb_interface_extra_descriptor [
	generic		usb_generic_descriptor
	hid_hid		usb_hid_descriptor_hid
	cdc_ecm		usb_cdc_header_ecm
	cdc_ncm		usb_cdc_header_ncm
	uac_control	uac_control_iface_extra_descriptors
	uac_as		uac_as_iface_extra_descriptors
] [varlen]

usb_endpoint_extra_descriptor [
	generic	usb_generic_descriptor
	uac_iso	uac_iso_endpoint_descriptor
] [varlen]

usb_generic_descriptor {
	bLength		len[parent, int8]
	bDescriptorType	flags[usb_descriptor_types, int8]

	data		array[int8, 0:256]
} [packed]

usb_descriptor_types = USB_DT_DEVICE, USB_DT_CONFIG, USB_DT_STRING, USB_DT_INTERFACE, USB_DT_ENDPOINT, USB_DT_DEVICE_QUALIFIER, USB_DT_OTHER_SPEED_CONFIG, USB_DT_INTERFACE_POWER, USB_DT_OTG, USB_DT_DEBUG, USB_DT_INTERFACE_ASSOCIATION, USB_DT_SECURITY, USB_DT_KEY, USB_DT_ENCRYPTION_TYPE, USB_DT_BOS, USB_DT_DEVICE_CAPABILITY, USB_DT_WIRELESS_ENDPOINT_COMP, USB_DT_WIRE_ADAPTER, USB_DT_RPIPE, USB_DT_CS_RADIO_CONTROL, USB_DT_PIPE_USAGE, USB_DT_SS_ENDPOINT_COMP, USB_DT_SSP_ISOC_ENDPOINT_COMP, HID_DT_HID, HID_DT_REPORT, HID_DT_PHYSICAL

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# USB descriptors requested after the SET_CONFIGURATION request.

usb_hub_descriptor_hs {
	bDescLength		len[parent, int8]
	bDescriptorType		const[USB_DT_HUB, int8]

	bNbrPorts		int8
	wHubCharacteristics	flags[usb_hub_characteristics, int16]
	bPwrOn2PwrGood		int8
	bHubContrCurrent	int8

	DeviceRemovable		array[int8, USB_HUB_PORTS_BITS]
	PortPwrCtrlMask		array[int8, USB_HUB_PORTS_BITS]
} [packed]

usb_hub_descriptor_ss {
	bDescLength		len[parent, int8]
	bDescriptorType		const[USB_DT_SS_HUB, int8]

	bNbrPorts		int8
	wHubCharacteristics	flags[usb_hub_characteristics, int16]
	bPwrOn2PwrGood		int8
	bHubContrCurrent	int8

	bHubHdrDecLat		int8
	wHubDelay		int16
	DeviceRemovable		int16
} [packed]

define USB_HUB_PORTS_BITS	((USB_MAXCHILDREN + 1 + 7) / 8)

usb_hub_characteristics = HUB_CHAR_LPSM, HUB_CHAR_COMMON_LPSM, HUB_CHAR_INDV_PORT_LPSM, HUB_CHAR_NO_LPSM, HUB_CHAR_COMPOUND, HUB_CHAR_OCPM, HUB_CHAR_COMMON_OCPM, HUB_CHAR_INDV_PORT_OCPM, HUB_CHAR_NO_OCPM, HUB_CHAR_TTTT, HUB_CHAR_PORTIND

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Replies to USB control requests requested after the SET_CONFIGURATION request.

usb_port_status {
	wPortStatus	flags[usb_port_status_flags, int16]
	wPortChange	flags[usb_port_change_flags, int16]
	dwExtPortStatus	array[flags[usb_ext_port_status_flags, int32], 0:1]
} [packed]

usb_port_status_flags = USB_PORT_STAT_CONNECTION, USB_PORT_STAT_ENABLE, USB_PORT_STAT_SUSPEND, USB_PORT_STAT_OVERCURRENT, USB_PORT_STAT_RESET, USB_PORT_STAT_L1, USB_PORT_STAT_POWER, USB_PORT_STAT_LOW_SPEED, USB_PORT_STAT_HIGH_SPEED, USB_PORT_STAT_TEST, USB_PORT_STAT_INDICATOR, USB_PORT_STAT_LINK_STATE, USB_SS_PORT_STAT_POWER, USB_SS_PORT_STAT_SPEED, USB_PORT_STAT_SPEED_5GBPS, USB_SS_PORT_LS_U0, USB_SS_PORT_LS_U1, USB_SS_PORT_LS_U2, USB_SS_PORT_LS_U3, USB_SS_PORT_LS_SS_DISABLED, USB_SS_PORT_LS_RX_DETECT, USB_SS_PORT_LS_SS_INACTIVE, USB_SS_PORT_LS_POLLING, USB_SS_PORT_LS_RECOVERY, USB_SS_PORT_LS_HOT_RESET, USB_SS_PORT_LS_COMP_MOD, USB_SS_PORT_LS_LOOPBACK

usb_port_change_flags = USB_PORT_STAT_C_CONNECTION, USB_PORT_STAT_C_ENABLE, USB_PORT_STAT_C_SUSPEND, USB_PORT_STAT_C_OVERCURRENT, USB_PORT_STAT_C_RESET, USB_PORT_STAT_C_L1, USB_PORT_STAT_C_BH_RESET, USB_PORT_STAT_C_LINK_STATE, USB_PORT_STAT_C_CONFIG_ERROR

usb_ext_port_status_flags = USB_EXT_PORT_STAT_RX_SPEED_ID, USB_EXT_PORT_STAT_TX_SPEED_ID, USB_EXT_PORT_STAT_RX_LANES, USB_EXT_PORT_STAT_TX_LANES

usb_hub_status {
	wHubStatus	flags[usb_hub_status_flags, int16]
	wHubChange	flags[usb_hub_change_flags, int16]
} [packed]

usb_hub_status_flags = HUB_STATUS_LOCAL_POWER, HUB_STATUS_OVERCURRENT

usb_hub_change_flags = HUB_CHANGE_LOCAL_POWER, HUB_CHANGE_OVERCURRENT

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# HID device class specific descriptions.
# https://www.usb.org/sites/default/files/documents/hid1_11.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/hid/usbhid/hid-core.c
# https://elixir.bootlin.com/linux/latest/source/drivers/hid/hid-core.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/hid.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_hid.c

# Connected HID devices are known to create the following /dev/ files:
# /dev/hidraw#, /dev/usb/hiddev# and /dev/input/event#.

resource fd_usb_hid[fd_usb]

syz_usb_connect$hid(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_hid], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_hid (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$hid(fd fd_usb_hid, descs ptr[in, vusb_descriptors_hid], resps ptr[in, vusb_responses_hid]) (timeout[300], remote_cover)

# idVendor and idProduct are patched by Go code, see sys/linux/init_vusb.go.
usb_device_descriptor_hid {
	inner	usb_device_descriptor_t[0, 0, 0, 0, 0, 64, array[usb_config_descriptor_hid, 1]]
} [packed]

usb_config_descriptor_hid {
	inner	usb_config_descriptor_ifaces_array_t[const[1, int8], array[usb_interface_descriptor_hid, 1]]
} [packed]

usb_interface_descriptor_hid {
	inner	usb_interface_descriptor_t[const[0, int8], int8, int8[1:2], const[USB_CLASS_HID, int8], const[USB_INTERFACE_SUBCLASS_BOOT, int8], flags[usb_hid_protocols, int8], usb_hid_descriptor_hid, usb_endpoint_descriptors_hid]
} [packed]

usb_hid_protocols = USB_INTERFACE_PROTOCOL_KEYBOARD, USB_INTERFACE_PROTOCOL_MOUSE

usb_endpoint_descriptors_hid {
	in	usb_endpoint_descriptor_hid_in
	out	array[usb_endpoint_descriptor_hid_out, 0:1]
} [packed]

usb_endpoint_descriptor_hid_in {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_HID_IN_ADDRESS, int8], const[USB_ENDPOINT_HID_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_hid_out {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_HID_OUT_ADDRESS, int8], const[USB_ENDPOINT_HID_ATTRIBUTES, int8], void]
} [packed]

define USB_ENDPOINT_HID_ATTRIBUTES	(USB_ENDPOINT_XFER_INT)
define USB_ENDPOINT_HID_IN_ADDRESS	(1 | USB_DIR_IN)
define USB_ENDPOINT_HID_OUT_ADDRESS	(2)

vusb_descriptors_hid {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]

# For unknown reasons these are requested as USB_TYPE_STANDARD and not as USB_TYPE_CLASS.
# Linux doesn't request HID_DT_HID, but some hosts might do that.
	HID_DT_REPORT	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, HID_DT_REPORT, hid_descriptor_report]]
	HID_DT_HID	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, HID_DT_HID, usb_hid_descriptor_hid]]
} [packed]

vusb_responses_hid {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	HID_REQ_GET_REPORT		ptr[in, vusb_response_t[USB_TYPE_CLASS, HID_REQ_GET_REPORT, array[int8, 0:256]]]
	HID_REQ_GET_PROTOCOL		ptr[in, vusb_response_t[USB_TYPE_CLASS, HID_REQ_GET_PROTOCOL, int8]]
} [packed]

# USB HID specifications allows for multiple report and physical descriptors
# to be present, but I don't see any support for them in the Linux kernel,
# except for a single report descriptor.
usb_hid_descriptor_hid {
	bLength		len[parent, int8]
	bDescriptorType	const[HID_DT_HID, int8]

	bcdHID		int16
	bCountryCode	int8
	bNumDescriptors	const[1, int8]

	report_desc	usb_hid_class_descriptor_report
} [packed]

usb_hid_class_descriptor_report {
	bDescriptorType		const[HID_DT_REPORT, int8]
	wDescriptorLength	int16[0:HID_MAX_DESCRIPTOR_SIZE]
} [packed]

# TODO: it's hard to describe the REPORT descriptor structure via syzkaller
# descriptions, so consider generating it in Go code.
# TODO: the length of REPORT descriptor must match the value in HID descriptor.
# TODO: there are vendor specific REPORT descriptor formats (Logitech HID++).

# Linux HID stack doesn't support long items.
hid_descriptor_report {
	items	array[hid_report_item_short]
} [packed]

type hid_report_item_short_012_t[TYPE, TAGS] {
	bSize	len[data, int8:2]
	bType	const[TYPE, int8:2]
	bTag	flags[TAGS, int8:4]
	data	array[int8, 0:2]
} [packed]

type hid_report_item_short_4_t[TYPE, TAGS] {
	bSize	const[3, int8:2]
	bType	const[TYPE, int8:2]
	bTag	flags[TAGS, int8:4]
	data	array[int8, 4]
} [packed]

type hid_report_item_short_t[TYPE, TAGS] [
	item_012	hid_report_item_short_012_t[TYPE, TAGS]
	item_4		hid_report_item_short_4_t[TYPE, TAGS]
] [varlen]

hid_report_item_short [
	main	hid_report_item_short_t[HID_ITEM_TYPE_MAIN, hid_report_item_main_tags]
	global	hid_report_item_short_t[HID_ITEM_TYPE_GLOBAL, hid_report_item_global_tags]
	local	hid_report_item_short_t[HID_ITEM_TYPE_LOCAL, hid_report_item_local_tags]
] [varlen]

hid_report_item_main_tags = HID_MAIN_ITEM_TAG_INPUT, HID_MAIN_ITEM_TAG_OUTPUT, HID_MAIN_ITEM_TAG_FEATURE, HID_MAIN_ITEM_TAG_BEGIN_COLLECTION, HID_MAIN_ITEM_TAG_END_COLLECTION
hid_report_item_global_tags = HID_GLOBAL_ITEM_TAG_USAGE_PAGE, HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM, HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM, HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM, HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM, HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT, HID_GLOBAL_ITEM_TAG_UNIT, HID_GLOBAL_ITEM_TAG_REPORT_SIZE, HID_GLOBAL_ITEM_TAG_REPORT_ID, HID_GLOBAL_ITEM_TAG_REPORT_COUNT, HID_GLOBAL_ITEM_TAG_PUSH, HID_GLOBAL_ITEM_TAG_POP
hid_report_item_local_tags = HID_LOCAL_ITEM_TAG_USAGE, HID_LOCAL_ITEM_TAG_USAGE_MINIMUM, HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM, HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX, HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM, HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM, HID_LOCAL_ITEM_TAG_STRING_INDEX, HID_LOCAL_ITEM_TAG_STRING_MINIMUM, HID_LOCAL_ITEM_TAG_STRING_MAXIMUM, HID_LOCAL_ITEM_TAG_DELIMITER

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# PRINTER device class specific descriptions.
# https://www.usb.org/sites/default/files/usbprint11a021811.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/class/usblp.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/printer.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_printer.c

# Connected PRINTER devices are known to create the following /dev/ files:
# /dev/usb/lp#.
# TODO: write descriptions for those.

# drivers/usb/class/usblp.c
define USBLP_REQ_GET_ID	0x00
define USBLP_REQ_GET_STATUS	0x01
define USBLP_REQ_RESET	0x02
define USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST	0x00
define USBLP_FIRST_PROTOCOL	1
define USBLP_LAST_PROTOCOL	3

resource fd_usb_printer[fd_usb]

syz_usb_connect$printer(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_printer], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_printer (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$printer(fd fd_usb_printer, descs ptr[in, vusb_descriptors_printer], resps ptr[in, vusb_responses_printer]) (timeout[300], remote_cover)

usb_device_descriptor_printer {
	inner	usb_device_descriptor_t[0, 0, 0, 0x525, 0xa4a8, 64, array[usb_config_descriptor_printer, 1]]
} [packed]

usb_config_descriptor_printer {
	inner	usb_config_descriptor_ifaces_array_t[const[1, int8], array[usb_interface_descriptor_printer, 1]]
} [packed]

usb_interface_descriptor_printer {
	inner	usb_interface_descriptor_t[const[0, int8], int8, int8[1:2], const[USB_CLASS_PRINTER, int8], const[1, int8], int8[USBLP_FIRST_PROTOCOL:USBLP_LAST_PROTOCOL], void, usb_endpoint_descriptors_printer]
} [packed]

usb_endpoint_descriptors_printer {
	in	usb_endpoint_descriptor_printer_out
	out	array[usb_endpoint_descriptor_printer_in, 0:1]
} [packed]

usb_endpoint_descriptor_printer_out {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_PRINTER_OUT_ADDRESS, int8], const[USB_ENDPOINT_PRINTER_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_printer_in {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_PRINTER_IN_ADDRESS, int8], const[USB_ENDPOINT_PRINTER_ATTRIBUTES, int8], void]
} [packed]

define USB_ENDPOINT_PRINTER_ATTRIBUTES	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_PRINTER_OUT_ADDRESS	(1)
define USB_ENDPOINT_PRINTER_IN_ADDRESS	(2 | USB_DIR_IN)

vusb_descriptors_printer {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_printer {
	len					len[parent, int32]
	generic					ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE			ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	USBLP_REQ_GET_ID			ptr[in, vusb_response_t[USB_TYPE_CLASS, USBLP_REQ_GET_ID, usb_printer_get_id_response]]
	USBLP_REQ_GET_STATUS			ptr[in, vusb_response_t[USB_TYPE_CLASS, USBLP_REQ_GET_STATUS, int8]]
	USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST	ptr[in, vusb_response_t[USB_TYPE_CLASS, USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST, int8]]
} [packed]

usb_printer_get_id_response {
	length	len[id, int16be]
	id	array[int8, 0:256]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# CDC ECM (Ethernet) device class specific descriptions.
# https://www.usb.org/document-library/class-definitions-communication-devices-12
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/cdc_ether.c
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/usbnet.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/ether.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_ecm.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/u_ether.c

# Connected CDC ECM devices are known to create usbN network interfaces.
# TODO: write descriptions for those.

resource fd_usb_cdc_ecm[fd_usb]

syz_usb_connect$cdc_ecm(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_cdc_ecm], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_cdc_ecm (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$cdc_ecm(fd fd_usb_cdc_ecm, descs ptr[in, vusb_descriptors_cdc_ecm], resps ptr[in, vusb_responses_cdc_ecm]) (timeout[300], remote_cover)

usb_device_descriptor_cdc_ecm {
	inner	usb_device_descriptor_t[USB_CLASS_COMM, 0, 0, 0x525, 0xa4a1, 64, array[usb_config_descriptor_cdc_ecm, 1]]
} [packed]

usb_config_descriptor_cdc_ecm {
	inner	usb_config_descriptor_ifaces_array_t[const[1, int8], array[usb_interface_descriptor_cdc_ecm, 1]]
} [packed]

# Per specification CDC ECM devices have two interfaces (control and data),
# but here we're merging them into one for simplicity since Linux supports that.
usb_interface_descriptor_cdc_ecm {
	inner	usb_interface_descriptor_t[const[0, int8], int8, int8[2:3], const[USB_CLASS_COMM, int8], const[USB_CDC_SUBCLASS_ETHERNET, int8], const[USB_CDC_PROTO_NONE, int8], usb_cdc_header_ecm, usb_endpoint_descriptors_cdc_ecm]
} [packed]

usb_endpoint_descriptors_cdc_ecm {
	notify	array[usb_endpoint_descriptor_cdc_ecm_notify, 0:1]
	in	usb_endpoint_descriptor_cdc_ecm_in
	out	usb_endpoint_descriptor_cdc_ecm_out
} [packed]

usb_endpoint_descriptor_cdc_ecm_notify {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_CDC_ECM_NOTIFY_ADDRESS, int8], const[USB_ENDPOINT_CDC_ECM_NOTIFY_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_cdc_ecm_in {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_CDC_ECM_IN_ADDRESS, int8], const[USB_ENDPOINT_CDC_ECM_DATA_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_cdc_ecm_out {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_CDC_ECM_OUT_ADDRESS, int8], const[USB_ENDPOINT_CDC_ECM_DATA_ATTRIBUTES, int8], void]
} [packed]

define USB_ENDPOINT_CDC_ECM_NOTIFY_ATTRIBUTES	(USB_ENDPOINT_XFER_INT)
define USB_ENDPOINT_CDC_ECM_DATA_ATTRIBUTES	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_CDC_ECM_NOTIFY_ADDRESS	(1 | USB_DIR_IN)
define USB_ENDPOINT_CDC_ECM_IN_ADDRESS	(2 | USB_DIR_IN)
define USB_ENDPOINT_CDC_ECM_OUT_ADDRESS	(3)

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/usb/core/message.c#L2137
# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/cdc_ether.c#L155
usb_cdc_header_ecm {
	union	usb_cdc_union_desc_t[0, 0]
	header	usb_cdc_header_desc
	ether	usb_cdc_ether_desc

	other	array[usb_cdc_header_ecm_other, 0:6]
} [packed]

usb_cdc_header_ecm_other [
	call_mgmt		usb_cdc_call_mgmt_descriptor
	acm			usb_cdc_acm_descriptor
	country_functional	usb_cdc_country_functional_desc
	network_terminal	usb_cdc_network_terminal_desc
	dmm			usb_cdc_dmm_desc
	mdlm			usb_cdc_mdlm_desc
	mdlm_detail		usb_cdc_mdlm_detail_desc
	obex			usb_cdc_obex_desc
	ncm			usb_cdc_ncm_desc
	mbim			usb_cdc_mbim_desc
	mbim_extended		usb_cdc_mbim_extended_desc
] [varlen]

usb_cdc_header_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_HEADER_TYPE, int8]

	bcdCDC			int16
} [packed]

usb_cdc_call_mgmt_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_CALL_MANAGEMENT_TYPE, int8]

	bmCapabilities		flags[usb_cdc_call_mgmt_caps, int8]
	bDataInterface		int8
} [packed]

usb_cdc_call_mgmt_caps = USB_CDC_CALL_MGMT_CAP_CALL_MGMT, USB_CDC_CALL_MGMT_CAP_DATA_INTF

usb_cdc_acm_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_ACM_TYPE, int8]

	bmCapabilities		flags[usb_cdc_acm_caps, int8]
} [packed]

usb_cdc_acm_caps = USB_CDC_COMM_FEATURE, USB_CDC_CAP_LINE, USB_CDC_CAP_BRK, USB_CDC_CAP_NOTIFY

type usb_cdc_union_desc_t[MASTER, SLAVE] {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_UNION_TYPE, int8]

	bMasterInterface0	const[MASTER, int8]
	bSlaveInterface0	const[SLAVE, int8]
	slave_interfaces	array[int8, 0:6]
} [packed]

usb_cdc_country_functional_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_COUNTRY_TYPE, int8]

	iCountryCodeRelDate	int8
	wCountyCode0		int16
	country_codes		array[int16, 0:6]
} [packed]

usb_cdc_network_terminal_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_NETWORK_TERMINAL_TYPE, int8]

	bEntityId		int8
	iName			int8
	bChannelIndex		int8
	bPhysicalInterface	int8
} [packed]

usb_cdc_ether_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_ETHERNET_TYPE, int8]

	iMACAddress		const[1, int8]
	bmEthernetStatistics	int32
	wMaxSegmentSize		int16
	wNumberMCFilters	int16
	bNumberPowerFilters	int8
} [packed]

usb_cdc_dmm_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_DMM_TYPE, int8]

	bcdVersion		int16
	wMaxCommand		int16
} [packed]

usb_cdc_mdlm_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_MDLM_TYPE, int8]

	bcdVersion		int16
	bGUID			usb_cdc_ecm_mbm_guid
} [packed]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/cdc_ether.c#L61
usb_cdc_ecm_mbm_guid {
	id0	const[0x14f5e048ba817a3, int64]
	id1	const[0x2a397ecbffc007a6, int64]
} [packed]

usb_cdc_mdlm_detail_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_MDLM_DETAIL_TYPE, int8]

	bGuidDescriptorType	int8
	bDetailData		array[int8, 0:256]
} [packed]

usb_cdc_obex_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_OBEX_TYPE, int8]

	bcdVersion		int16
} [packed]

usb_cdc_ncm_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_NCM_TYPE, int8]

	bcdNcmVersion		int16
	bmNetworkCapabilities	flags[usb_cdc_ncm_ncaps, int8]
} [packed]

usb_cdc_ncm_ncaps = USB_CDC_NCM_NCAP_ETH_FILTER, USB_CDC_NCM_NCAP_NET_ADDRESS, USB_CDC_NCM_NCAP_ENCAP_COMMAND, USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE, USB_CDC_NCM_NCAP_CRC_MODE, USB_CDC_NCM_NCAP_NTB_INPUT_SIZE

usb_cdc_mbim_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_MBIM_TYPE, int8]

	bcdMBIMVersion		int16
	wMaxControlMessage	int16
	bNumberFilters		int8
	bMaxFilterSize		int8
	wMaxSegmentSize		int16
	bmNetworkCapabilities	int8
} [packed]

usb_cdc_mbim_extended_desc {
	bLength				len[parent, int8]
	bDescriptorType			const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType		const[USB_CDC_MBIM_EXTENDED_TYPE, int8]

	bcdMBIMExtendedVersion		int16
	bMaxOutstandingCommandMessages	int8
	wMTU				int16
} [packed]

vusb_descriptors_cdc_ecm {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/usbnet.c#L147
	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor_t[usb_cdc_ecm_mac]]]
} [packed]

usb_cdc_ecm_mac {
# This is a UTF16 encoded string "424242424242".
	data0	const[0x3400320034003200, int64be]
	data1	const[0x3400320034003200, int64be]
	data2	const[0x3400320034003200, int64be]
} [packed]

vusb_responses_cdc_ecm {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# CDC NCM class specific descriptions.
# CDC NCM is based on CDC ECM, so some of the descriptions are reused.
# https://www.usb.org/document-library/network-control-model-devices-specification-v10-and-errata-and-adopters-agreement
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/cdc_ncm.c
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/usbnet.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/ncm.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_ncm.c

resource fd_usb_cdc_ncm[fd_usb]

syz_usb_connect$cdc_ncm(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_cdc_ncm], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_cdc_ncm (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$cdc_ncm(fd fd_usb_cdc_ncm, descs ptr[in, vusb_descriptors_cdc_ncm], resps ptr[in, vusb_responses_cdc_ncm]) (timeout[300], remote_cover)

usb_device_descriptor_cdc_ncm {
	inner	usb_device_descriptor_t[USB_CLASS_COMM, 0, 0, 0x525, 0xa4a1, 64, array[usb_config_descriptor_cdc_ncm, 1]]
} [packed]

usb_config_descriptor_cdc_ncm {
	inner	usb_config_descriptor_t[const[1, int8], const[2, int8], usb_interface_descriptors_cdc_ncm]
} [packed]

usb_interface_descriptors_cdc_ncm {
	control		usb_interface_descriptor_fixed_t[0, CDC_NCM_COMM_ALTSETTING_NCM, 1, USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE, usb_cdc_header_ncm, usb_endpoint_descriptor_cdc_ecm_notify]
	data_nop	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE, void, void]
	data		usb_interface_descriptor_fixed_t[1, CDC_NCM_DATA_ALTSETTING_NCM, 2, USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE, void, usb_endpoint_descriptors_cdc_ncm_data]
} [packed]

usb_endpoint_descriptors_cdc_ncm_data {
	in	usb_endpoint_descriptor_cdc_ecm_in
	out	usb_endpoint_descriptor_cdc_ecm_out
} [packed]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/usb/core/message.c#L2137
# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/cdc_ncm.c#L798
usb_cdc_header_ncm {
	union	usb_cdc_union_desc_t[0, 1]
	header	usb_cdc_header_desc
	ether	usb_cdc_ether_desc
	ncm	usb_cdc_ncm_desc

	other	array[usb_cdc_header_ncm_other, 0:6]
} [packed]

usb_cdc_header_ncm_other [
	call_mgmt		usb_cdc_call_mgmt_descriptor
	acm			usb_cdc_acm_descriptor
	country_functional	usb_cdc_country_functional_desc
	network_terminal	usb_cdc_network_terminal_desc
	dmm			usb_cdc_dmm_desc
	mdlm			usb_cdc_mdlm_desc
	mdlm_detail		usb_cdc_mdlm_detail_desc
	obex			usb_cdc_obex_desc
	mbim			usb_cdc_mbim_desc
	mbim_extended		usb_cdc_mbim_extended_desc
] [varlen]

vusb_descriptors_cdc_ncm {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/usbnet.c#L147
	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor_t[usb_cdc_ecm_mac]]]
} [packed]

vusb_responses_cdc_ncm {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	USB_CDC_GET_NTB_PARAMETERS	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_NTB_PARAMETERS, usb_cdc_ncm_ntb_parameters]]
	USB_CDC_GET_NTB_INPUT_SIZE	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_NTB_INPUT_SIZE, int32]]
	USB_CDC_GET_NTB_FORMAT		ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_NTB_FORMAT, int16[0:1]]]
	USB_CDC_GET_MAX_DATAGRAM_SIZE	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_MAX_DATAGRAM_SIZE, int16]]
	USB_CDC_GET_CRC_MODE		ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_CRC_MODE, int16[0:1]]]
} [packed]

usb_cdc_ncm_ntb_parameters {
	wLength			int16
	bmNtbFormatsSupported	int16
	dwNtbInMaxSize		int32
	wNdpInDivisor		int16
	wNdpInPayloadRemainder	int16
	wNdpInAlignment		int16
	wPadding1		int16
	dwNtbOutMaxSize		int32
	wNdpOutDivisor		int16
	wNdpOutPayloadRemainder	int16
	wNdpOutAlignment	int16
	wNtbOutMaxDatagrams	int16
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC1 device class specific descriptions.
# https://www.usb.org/sites/default/files/audio10.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/audio.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac1.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac1_legacy.c
# https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/usb/audio.h

# TODO: find out which /dev/ files are created by connected UAC1 devices and add descriptions for those.

resource fd_usb_uac1[fd_usb]

syz_usb_connect$uac1(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_uac1], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_uac1 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$uac1(fd fd_usb_uac1, descs ptr[in, vusb_descriptors_uac1], resps ptr[in, vusb_responses_uac1]) (timeout[300], remote_cover)

usb_device_descriptor_uac1 {
	inner	usb_device_descriptor_t[0, 0, 0, 0x1d6b, 0x101, 64, array[usb_config_descriptor_uac1, 1]]
} [packed]

usb_config_descriptor_uac1 {
	inner	usb_config_descriptor_t[const[1, int8], const[3, int8], usb_interface_descriptors_uac1]
} [packed]

# TODO: control interface might have and optional interrupt endpoint.
usb_interface_descriptors_uac1 {
	inner	usb_interface_descriptors_uac1_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_uac1_inner {
	control		usb_interface_descriptor_fixed_t[0, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOCONTROL, 0, uac_control_iface_extra_descriptors, void]
	as_out_alt_0	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, void, void]
	as_out_alt_1	usb_interface_descriptor_fixed_t[1, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, uac_as_iface_extra_descriptors, uac_as_out_endpoint_descriptor]
	as_in_alt_0	usb_interface_descriptor_fixed_t[2, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, void, void]
	as_in_alt_1	usb_interface_descriptor_fixed_t[2, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, uac_as_iface_extra_descriptors, uac_as_in_endpoint_descriptor]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC uses IDs to make it possible for terminals and units to refer to each other.
# We don't have a way to describe this, so just use a limited number of ids.
type uac_id int8[1:6]

uac_control_iface_extra_descriptors {
	header	uac1_ac_header_descriptor
	others	array[uac_control_iface_extra_descriptor, 0:6]
} [packed]

uac1_ac_header_descriptor {
	bLength			const[UAC_DT_AC_HEADER_LENGTH, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_HEADER, int8]

	bcdADC			int16
	wTotalLength		len[uac_control_iface_extra_descriptors, int16]
	bInCollection		const[F_AUDIO_NUM_INTERFACES, int8]

# These must match interfaces numbers.
	baInterfaceNr0		const[1, int8]
	baInterfaceNr1		const[2, int8]
} [packed]

uac_control_iface_extra_descriptor [
	input_terminal	uac_input_terminal_descriptor
	output_terminal	uac1_output_terminal_descriptor
	mixer_unit	uac_mixer_unit_descriptor
	selector_unit	uac_selector_unit_descriptor
	feature_unit	uac_feature_unit_descriptor
	processing_unit	uac_processing_unit_descriptor
	extension_unit	uac_extension_unit_descriptor
] [varlen]

define F_AUDIO_NUM_INTERFACES	2
define UAC_DT_AC_HEADER_LENGTH	UAC_DT_AC_HEADER_SIZE(F_AUDIO_NUM_INTERFACES)

uac_input_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_INPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_input_terminal_types, int16]
	bAssocTerminal		uac_id
	bNrChannels		int8
	wChannelConfig		int16
	iChannelNames		int8
	iTerminal		int8
} [packed]

# The following list contains input terminal types and inout terminal types.
uac_input_terminal_types = UAC_TERMINAL_UNDEFINED, UAC_TERMINAL_STREAMING, UAC_TERMINAL_VENDOR_SPEC, UAC_INPUT_TERMINAL_UNDEFINED, UAC_INPUT_TERMINAL_MICROPHONE, UAC_INPUT_TERMINAL_DESKTOP_MICROPHONE, UAC_INPUT_TERMINAL_PERSONAL_MICROPHONE, UAC_INPUT_TERMINAL_OMNI_DIR_MICROPHONE, UAC_INPUT_TERMINAL_MICROPHONE_ARRAY, UAC_INPUT_TERMINAL_PROC_MICROPHONE_ARRAY, UAC_BIDIR_TERMINAL_UNDEFINED, UAC_BIDIR_TERMINAL_HANDSET, UAC_BIDIR_TERMINAL_HEADSET, UAC_BIDIR_TERMINAL_SPEAKER_PHONE, UAC_BIDIR_TERMINAL_ECHO_SUPPRESSING, UAC_BIDIR_TERMINAL_ECHO_CANCELING
# The following list contains output terminal types and inout terminal types.
uac_output_terminal_types = UAC_TERMINAL_UNDEFINED, UAC_TERMINAL_STREAMING, UAC_TERMINAL_VENDOR_SPEC, UAC_OUTPUT_TERMINAL_UNDEFINED, UAC_OUTPUT_TERMINAL_SPEAKER, UAC_OUTPUT_TERMINAL_HEADPHONES, UAC_OUTPUT_TERMINAL_HEAD_MOUNTED_DISPLAY_AUDIO, UAC_OUTPUT_TERMINAL_DESKTOP_SPEAKER, UAC_OUTPUT_TERMINAL_ROOM_SPEAKER, UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER, UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER, UAC_BIDIR_TERMINAL_UNDEFINED, UAC_BIDIR_TERMINAL_HANDSET, UAC_BIDIR_TERMINAL_HEADSET, UAC_BIDIR_TERMINAL_SPEAKER_PHONE, UAC_BIDIR_TERMINAL_ECHO_SUPPRESSING, UAC_BIDIR_TERMINAL_ECHO_CANCELING

uac1_output_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_OUTPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_output_terminal_types, int16]
	bAssocTerminal		uac_id
	bSourceID		uac_id
	iTerminal		int8
} [packed]

uac_mixer_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIXER_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac_selector_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_SELECTOR_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac_feature_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FEATURE_UNIT, int8]

	bUnitID			uac_id
	bSourceID		uac_id
	bControlSize		len[bmaControls, int8]
	bmaControls		array[flags[uac_feature_unit_controls, int16], 1:6]
	iFeature		int8
} [packed]

uac_feature_unit_controls = UAC_FU_MUTE, UAC_FU_VOLUME, UAC_FU_BASS, UAC_FU_MID, UAC_FU_TREBLE, UAC_FU_GRAPHIC_EQUALIZER, UAC_FU_AUTOMATIC_GAIN, UAC_FU_DELAY, UAC_FU_BASS_BOOST, UAC_FU_LOUDNESS

uac_processing_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC1_PROCESSING_UNIT, int8]

	bUnitID			uac_id
	wProcessType		flags[uac_processing_unit_types, int16]
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac_processing_unit_types = UAC_PROCESS_UNDEFINED, UAC_PROCESS_UP_DOWNMIX, UAC_PROCESS_DOLBY_PROLOGIC, UAC_PROCESS_STEREO_EXTENDER, UAC_PROCESS_REVERB, UAC_PROCESS_CHORUS, UAC_PROCESS_DYN_RANGE_COMP

uac_extension_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC1_EXTENSION_UNIT, int8]

	bUnitID			uac_id
	wProcessType		int16
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac_as_iface_extra_descriptors {
	others	array[uac_as_iface_extra_descriptor, 0:6]
} [packed]

uac_as_iface_extra_descriptor [
	as_header			uac1_as_header_descriptor
	format_type_i_continuous	uac_format_type_i_continuous_descriptor
	format_type_i_discrete		uac_format_type_i_discrete_descriptor
	format_type_ii_discrete		uac_format_type_ii_discrete_descriptor
	format_type_ii_ext		uac_format_type_ii_ext_descriptor
	format_type_i_ext		uac_format_type_i_ext_descriptor
] [varlen]

uac1_as_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_AS_GENERAL, int8]

	bTerminalLink		int8
	bDelay			int8
	wFormatTag		flags[uac_format_tags, int16]
} [packed]

uac_format_tags = UAC_FORMAT_TYPE_I_UNDEFINED, UAC_FORMAT_TYPE_I_PCM, UAC_FORMAT_TYPE_I_PCM8, UAC_FORMAT_TYPE_I_IEEE_FLOAT, UAC_FORMAT_TYPE_I_ALAW, UAC_FORMAT_TYPE_I_MULAW, UAC_FORMAT_TYPE_II_MPEG, UAC_FORMAT_TYPE_II_AC3
uac_usb_format_types_i = UAC_FORMAT_TYPE_I, UAC_FORMAT_TYPE_II, UAC_FORMAT_TYPE_III, UAC_FORMAT_TYPE_UNDEFINED

uac_format_type_i_continuous_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bNrChannels		int8
	bSubframeSize		int8[1:4]
	bBitResolution		int8
	bSamFreqType		int8
	tLowerSamFreq		array[int8, 0:3]
	tUpperSamFreq		array[int8, 0:3]
} [packed]

uac_format_type_i_discrete_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bNrChannels		int8
	bSubframeSize		int8[1:4]
	bBitResolution		int8
	bSamFreqType		int8
	tSamFreq		array[int8, 0:9]
} [packed]

uac_format_type_ii_discrete_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_II, int8]
	wMaxBitRate		int16
	wSamplesPerFrame	int16
	bSamFreqType		int8
	tSamFreq		array[int8, 0:9]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac_as_out_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac_iso_endpoint_descriptor]
} [packed]

uac_as_in_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_IN_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac_iso_endpoint_descriptor]
} [packed]

define USB_ENDPOINT_UAC1_AS_OUT_ADDRESS	(1 | USB_DIR_OUT)
define USB_ENDPOINT_UAC1_AS_IN_ADDRESS	(2 | USB_DIR_IN)
define USB_ENDPOINT_UAC1_AS_ATTRIBUTES	(USB_ENDPOINT_SYNC_ADAPTIVE | USB_ENDPOINT_XFER_ISOC)

uac_iso_ep_attributes = USB_ENDPOINT_SYNCTYPE, USB_ENDPOINT_SYNC_NONE, USB_ENDPOINT_SYNC_ASYNC, USB_ENDPOINT_SYNC_ADAPTIVE, USB_ENDPOINT_SYNC_SYNC

uac_iso_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubType	const[UAC_EP_GENERAL, int8]

	bmAttributes		flags[uac_iso_ep_attributes, int8]
	bLockDelayUnits		int8
	wLockDelay		int16
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

vusb_descriptors_uac1 {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_uac1 {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	audio_UAC_GET_CUR		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_CUR, array[int8, 1:3]]]
	audio_UAC_GET_MIN		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_MIN, array[int8, 1:3]]]
	audio_UAC_GET_MAX		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_MAX, array[int8, 1:3]]]
	audio_UAC_GET_RES		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_RES, array[int8, 1:4]]]
	audio_UAC_GET_MEM		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_MEM, array[int8, 3]]]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC2 device class specific descriptions.
# https://www.usb.org/sites/default/files/audio10.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/audio.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac2.c
# https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/usb/audio.h

resource fd_usb_uac2[fd_usb]

syz_usb_connect$uac2(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_uac2], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_uac2 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$uac2(fd fd_usb_uac2, descs ptr[in, vusb_descriptors_uac1], resps ptr[in, vusb_responses_uac1]) (timeout[300], remote_cover)

usb_device_descriptor_uac2 {
	inner	usb_device_descriptor_t[0, 0, 0, 0x41e, 0x3000, 64, array[usb_config_descriptor_uac2, 1]]
} [packed]

usb_config_descriptor_uac2 {
	inner	usb_config_descriptor_extra_t[const[1, int8], const[3, int8], uac2_interface_assoc_descriptor, usb_interface_descriptors_uac2]
} [packed]

uac2_interface_assoc_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_INTERFACE_ASSOCIATION, int8]

	bFirstInterface		int8[0:2]
	bInterfaceCount		int8[0:2]
	bFunctionClass		const[USB_CLASS_AUDIO, int8]
	bFunctionSubClass	flags[audio_function_category_types, int8]
	bFunctionProtocol	const[UAC_VERSION_2, int8]
	iFunction		int8
} [packed]

audio_function_category_types = UAC2_FUNCTION_SUBCLASS_UNDEFINED, UAC2_FUNCTION_DESKTOP_SPEAKER, UAC2_FUNCTION_HOME_THEATER, UAC2_FUNCTION_MICROPHONE, UAC2_FUNCTION_HEADSET, UAC2_FUNCTION_TELEPHONE, UAC2_FUNCTION_CONVERTER, UAC2_FUNCTION_SOUND_RECORDER, UAC2_FUNCTION_IO_BOX, UAC2_FUNCTION_MUSICAL_INSTRUMENT, UAC2_FUNCTION_PRO_AUDIO, UAC2_FUNCTION_AUDIO_VIDEO, UAC2_FUNCTION_CONTROL_PANEL, UAC2_FUNCTION_OTHER

usb_interface_descriptors_uac2 {
	inner	usb_interface_descriptors_uac2_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_uac2_inner {
	control		usb_interface_descriptor_fixed_t[0, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOCONTROL, UAC_VERSION_2, uac2_control_iface_extra_descriptors, void]
	as_out_alt_0	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, void, void]
	as_out_alt_1	usb_interface_descriptor_fixed_t[1, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, uac2_as_iface_extra_descriptors, uac2_as_out_endpoint_descriptor]
	as_in_alt_0	usb_interface_descriptor_fixed_t[2, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, void, void]
	as_in_alt_1	usb_interface_descriptor_fixed_t[2, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, uac2_as_iface_extra_descriptors, uac2_as_in_endpoint_descriptor]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac2_control_iface_extra_descriptors {
	header	uac2_ac_header_descriptor
	others	array[uac2_control_iface_extra_descriptor, 0:6]
} [packed]

uac2_ac_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MS_HEADER, int8]
	bcdADC			int16
	bCategory		flags[uac2_feature_unit_controls, int8]
	wTotalLength		len[uac2_control_iface_extra_descriptors, int16]
	bmControls		int8
} [packed]

uac2_feature_unit_controls = UAC2_FUNCTION_SUBCLASS_UNDEFINED, UAC2_FUNCTION_DESKTOP_SPEAKER, UAC2_FUNCTION_HOME_THEATER, UAC2_FUNCTION_MICROPHONE, UAC2_FUNCTION_HEADSET, UAC2_FUNCTION_TELEPHONE, UAC2_FUNCTION_CONVERTER, UAC2_FUNCTION_SOUND_RECORDER, UAC2_FUNCTION_IO_BOX, UAC2_FUNCTION_MUSICAL_INSTRUMENT, UAC2_FUNCTION_PRO_AUDIO, UAC2_FUNCTION_AUDIO_VIDEO, UAC2_FUNCTION_CONTROL_PANEL, UAC2_FUNCTION_OTHER, uac_feature_unit_controls

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac2_as_iface_extra_descriptors {
	others	array[uac2_as_iface_extra_descriptor, 0:6]
} [packed]

uac2_as_iface_extra_descriptor [
	as_header			uac2_as_header_descriptor
	format_type_i_descriptor	uac2_format_type_i_descriptor
	format_type_i_continuous	uac_format_type_i_continuous_descriptor
	format_type_i_discrete		uac_format_type_i_discrete_descriptor
	format_type_ii_discrete		uac_format_type_ii_discrete_descriptor
	format_type_i_ext		uac2_format_type_i_ext_descriptor
	format_type_ii_ext		uac_format_type_ii_ext_descriptor
] [varlen]

uac2_as_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_AS_GENERAL, int8]
	bTerminalLink		int8
	bmControls		int8
	bFormatType		flags[uac_usb_format_types_i, int8]
	bmFormats		flags[uac_format_tags, int32]
	bNrChannels		int8
	bmChannelConfig		int32
	iChannelNames		int8
} [packed]

b_sub_slot_sizes = 1, 2, 3, 4

uac2_format_type_i_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]
	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bSubslotSize		flags[b_sub_slot_sizes, int8]
	bBitResolution		int8
} [packed]

uac2_format_type_i_ext_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bSubslotSize		int8
	bBitResolution		int8
	bHeaderLength		int8
	bControlSize		int8
	bSideBandProtocol	int8
} [packed]

uac_format_type_ii_ext_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]
	bFormatType		const[UAC_FORMAT_TYPE_II, int8]
	wMaxBitRate		int16
	wSamplesPerFrame	int16
	bHeaderLength		int8
	bSideBandProtocol	int8
} [packed]

uac_format_type_i_ext_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]
	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bSubslotSize		int8
	bBitResolution		int8
	bHeaderLength		int8
	bControlSize		int8
	bSideBandProtocol	int8
} [packed]

uac2_as_out_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac2_iso_endpoint_descriptor]
} [packed]

uac2_as_in_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_IN_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac2_iso_endpoint_descriptor]
} [packed]

uac2_iso_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubtype	const[UAC_EP_GENERAL, int8]

	bmAttributes		flags[csep_bm_attributes, int8]
	bmControls		flags[csep_bm_controls, int8]
	bLockDelayUnits		int8
	wLockDelay		int16
} [packed]

csep_bm_attributes = UAC_EP_CS_ATTR_SAMPLE_RATE, UAC_EP_CS_ATTR_PITCH_CONTROL, UAC_EP_CS_ATTR_FILL_MAX
csep_bm_controls = UAC2_CONTROL_PITCH, UAC2_CONTROL_DATA_OVERRUN, UAC2_CONTROL_DATA_UNDERRUN

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac2_control_iface_extra_descriptor [
	input_terminal	uac2_input_terminal_descriptor
	output_terminal	uac2_output_terminal_descriptor
	mixer_unit	uac2_mixer_unit_descriptor
	selector_unit	uac2_clock_selector_descriptor

	feature_unit	uac2_feature_unit_descriptor
	processing_unit	uac2_processing_unit_descriptor
	extension_unit	uac2_extension_unit_descriptor

	effect_unit	uac2_effect_unit_descriptor
	sample_rate	uac2_sample_rate_descriptor
	source_unit	uac2_clock_source_descriptor
	multiply_unit	uac2_clock_multiplier_descriptor
] [varlen]

uac2_input_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_INPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_input_terminal_types, int16]
	bAssocTerminal		uac_id
	bCSourceID		int8
	bNrChannels		int8
	bmChannelConfig		int32
	iChannelNames		int8
	bmControls		int8
	iTerminal		int8
} [packed]

uac2_output_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_OUTPUT_TERMINAL, int8]
	bTerminalID		uac_id
	wTerminalType		flags[uac_output_terminal_types, int16]
	bAssocTerminal		int8
	bSourceID		uac_id
	bCSourceID		int8
	bmControls		int16
	iTerminal		int8
} [packed]

uac2_mixer_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIXER_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

# TODO: Figure out if bmControls and iClockSelector should be a part of this structure.
uac2_clock_selector_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_CLOCK_SELECTOR, int8]
	bClockID		int8
	bNrInPins		len[baCSourceID, int8]
	baCSourceID		array[int8, 0:8]
} [packed]

# TODO: Verify coverage.
uac2_processing_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC2_PROCESSING_UNIT_V2, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac2_processing_unit_types, int16], 1:6]
} [packed]

uac2_processing_unit_types = UAC2_PROCESS_UNDEFINED, UAC2_PROCESS_UP_DOWNMIX, UAC2_PROCESS_DOLBY_PROLOCIC, UAC2_PROCESS_STEREO_EXTENDER

uac2_extension_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_EXTENSION_UNIT_V2, int8]

	bUnitID			uac_id
	wProcessType		int16
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

# TODO: Verify coverage.
uac2_effect_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC2_EFFECT_UNIT, int8]
	bUnitID			uac_id
	wEffectType		flags[uac2_effect_unit_types, int16]
	bSourceID		uac_id
	bmaControls		array[flags[uac2_processing_unit_types, int16], 1:6]
} [packed]

uac2_effect_unit_types = UAC2_EFFECT_UNDEFINED, UAC2_EFFECT_PARAM_EQ, UAC2_EFFECT_REVERB, UAC2_EFFECT_MOD_DELAY, UAC2_EFFECT_DYN_RANGE_COMP

uac2_sample_rate_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC2_SAMPLE_RATE_CONVERTER, int8]
	bUnitID			uac_id
	wProcessType		flags[uac2_processing_unit_types, int16]
	bSourceID		uac_id
	bmaControls		array[flags[uac2_processing_unit_types, int16], 1:6]
} [packed]

uac2_feature_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_FEATURE_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac2_feature_unit_controls, int16], 1:6]
} [packed]

uac2_clock_source_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_CLOCK_SOURCE, int8]
	bClockID		int8
	bmAttributes		flags[uac2_clock_bmattribute_types, int8]
	bmControls		int8
	bAssocTerminal		int8
	iClockSource		flags[uac2_clock_source_types, int8]
} [packed]

uac2_clock_bmattribute_types = UAC_CLOCK_SOURCE_TYPE_EXT, UAC_CLOCK_SOURCE_TYPE_INT_FIXED, UAC_CLOCK_SOURCE_TYPE_INT_VAR, UAC_CLOCK_SOURCE_TYPE_INT_PROG, UAC_CLOCK_SOURCE_SYNCED_TO_SOF
uac2_clock_source_types = UAC_CLOCK_SOURCE_TYPE_EXT, UAC_CLOCK_SOURCE_TYPE_INT_FIXED, UAC_CLOCK_SOURCE_TYPE_INT_VAR, UAC_CLOCK_SOURCE_TYPE_INT_PROG, UAC_CLOCK_SOURCE_SYNCED_TO_SOF

uac2_clock_multiplier_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_CLOCK_MULTIPLIER, int8]
	bClockID		int8
	bCSourceID		int8
	bmControls		int8
	iClockMultiplier	int8
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC3 device class specific descriptions.
# https://www.usb.org/sites/default/files/audio10.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/audio.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac3.c
# https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/usb/audio.h

resource fd_usb_uac3[fd_usb]

syz_usb_connect$uac3(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_uac3], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_uac3 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$uac3(fd fd_usb_uac3, descs ptr[in, vusb_descriptors_uac1], resps ptr[in, vusb_responses_uac1]) (timeout[300], remote_cover)

usb_device_descriptor_uac3 {
	inner	usb_device_descriptor_t[0, 0, 0, 0x582, 0x582, 64, array[usb_config_descriptor_uac3, 1]]
} [packed]

usb_config_descriptor_uac3 {
	inner	usb_config_descriptor_extra_t[const[1, int8], const[3, int8], uac3_interface_assoc_descriptor, usb_interface_descriptors_uac3]
} [packed]

uac3_interface_assoc_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_INTERFACE_ASSOCIATION, int8]

	bFirstInterface		int8[0:2]
	bInterfaceCount		int8[0:2]
	bFunctionClass		const[USB_CLASS_AUDIO, int8]
	bFunctionSubClass	flags[uac3_all_subclasses, int8]
	bFunctionProtocol	const[UAC_VERSION_3, int8]
	iFunction		int8
} [packed]

usb_interface_descriptors_uac3 {
	inner	usb_interface_descriptors_uac3_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_uac3_inner {
	control		usb_interface_descriptor_fixed_t[0, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOCONTROL, UAC_VERSION_3, uac3_control_iface_extra_descriptors, void]
	as_out_alt_0	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, void, void]
	as_out_alt_1	usb_interface_descriptor_fixed_t[1, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, uac3_as_iface_extra_descriptors, uac3_as_out_endpoint_descriptor]
	as_in_alt_0	usb_interface_descriptor_fixed_t[2, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, void, void]
	as_in_alt_1	usb_interface_descriptor_fixed_t[2, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, uac3_as_iface_extra_descriptors, uac3_as_in_endpoint_descriptor]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac3_control_iface_extra_descriptors {
	header	uac3_ac_header_descriptor
	others	array[uac3_control_iface_extra_descriptor, 0:6]
} [packed]

uac3_ac_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MS_HEADER, int8]

	bCategory		flags[uac3_feature_unit_controls, int8]
	wTotalLength		len[uac3_control_iface_extra_descriptors, int16]
	bmControls		int32
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac3_as_iface_extra_descriptors {
	others	array[uac3_as_iface_extra_descriptor, 0:6]
} [packed]

uac3_as_iface_extra_descriptor [
	as_header			uac3_as_header_descriptor
	format_type_i_descriptor	uac2_format_type_i_descriptor
	format_type_i_continuous	uac_format_type_i_continuous_descriptor
	format_type_i_discrete		uac_format_type_i_discrete_descriptor
	format_type_ii_discrete		uac_format_type_ii_discrete_descriptor
	format_type_i_ext		uac2_format_type_i_ext_descriptor
	format_type_ii_ext		uac_format_type_ii_ext_descriptor
] [varlen]

# TODO: Figure out how wClusterDescrID is used in the kernel.
uac3_as_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_AS_GENERAL, int8]
	bTerminalLink		int8

	bmControls		int32
	wClusterDescrID		int16

	bmFormats		flags[uac_format_tags, int64]

	bSubslotSize		int8
	bBitResolution		int8
	bmAuxProtocols		int16
	bControlSize		int8
} [packed]

uac3_as_out_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac3_iso_endpoint_descriptor]
} [packed]

uac3_as_in_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_IN_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac3_iso_endpoint_descriptor]
} [packed]

uac3_iso_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubType	const[UAC3_CS_ENDPOINT, int8]
	bmControls		int32
	bLockDelayUnits		int8
	wLockDelay		int16
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac3_control_iface_extra_descriptor [
	input_terminal		uac3_input_terminal_descriptor
	output_terminal		uac3_output_terminal_descriptor
	mixer_unit		uac3_mixer_unit_descriptor
	selector_unit		uac3_clock_selector_descriptor
	source_unit		uac3_clock_source_descriptor
	multiply_unit		uac3_clock_multiplier_descriptor
	feature_unit		uac3_feature_unit_descriptor
	processing_unit		uac3_processing_unit_descriptor
	extension_unit		uac3_extension_unit_descriptor
	power_domain		uac3_power_domain_descriptor
	cluster_info_segment	uac3_cluster_information_segment_descriptor
# Only cluster information segment is currently used in the kernel.See: sound/usb/stream.c
# cluster_segment 		uac3_cluster_segment_descriptor
# cluster_end_segment		uac3_cluster_end_segment_descriptor
# The following units are not yet supported by the kernel.
# See audio_validators[] in sound/usb/validate.c:
#	effect_unit 		uac3_effect_unit_descriptor
#	sample_rate			uac3_sample_rate_descriptor
#	connectors_unit		uac3_connectors_unit_descriptor
#	extended_term_unit	uac3_extended_terminal_unit
] [varlen]

uac3_input_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_INPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_input_terminal_types, int16]
	bAssocTerminal		uac_id
	bCSourceID		int8

	bmControls		int32
	wClusterDescrID		int16
	wExTerminalDescrID	int16
	wConnectorsDescrID	int16
	wTerminalDescrStr	int16
} [packed]

uac3_output_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_OUTPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_output_terminal_types, int16]
	bAssocTerminal		uac_id
	bSourceID		uac_id
	bCSourceID		int8

	bmControls		int32
	wExTerminalDescrID	int16
	wConnectorsDescrID	int16
	wTerminalDescrStr	int16
} [packed]

uac3_mixer_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_MIXER_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac3_clock_selector_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_CLOCK_SELECTOR, int8]
	bClockID		int8
	bNrInPins		len[baCSourceID, int8]
	baCSourceID		array[int8, 0:8]
} [packed]

uac3_clock_source_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_CLOCK_SOURCE, int8]
	bClockID		int8
	bmAttributes		flags[uac3_clock_bmattribute_types, int8]
	bmControls		int32
	bReferenceTerminal	int8
	wClockSourceStr		int16
} [packed]

uac3_clock_bmattribute_types = UAC3_CLOCK_SOURCE_TYPE_EXT, UAC3_CLOCK_SOURCE_TYPE_INT, UAC3_CLOCK_SOURCE_ASYNC, UAC3_CLOCK_SOURCE_SYNCED_TO_SOF

uac3_clock_multiplier_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_CLOCK_MULTIPLIER, int8]
	bClockID		int8
	bCSourceID		int8
	bmControls		int32
	wCMultiplierDescrStr	int16
} [packed]

uac3_feature_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC3_FEATURE_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac3_feature_unit_controls, int32], 1:6]
} [packed]

uac3_processing_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC3_PROCESSING_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac3_processing_unit_types, int32], 1:6]
} [packed]

uac3_processing_unit_types = UAC3_PROCESS_UNDEFINED, UAC3_PROCESS_UP_DOWNMIX, UAC3_PROCESS_STEREO_EXTENDER, UAC3_PROCESS_MULTI_FUNCTION

uac3_extension_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC3_EXTENSION_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac3_processing_unit_types, int32], 1:6]
} [packed]

uac3_power_domain_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_POWER_DOMAIN, int8]

	bPowerDomainID		int8
	waRecoveryTime1		int16
	waRecoveryTime2		int16
	bNrEntities		int8
	baEntityID		array[int8, 0:8]
} [packed]

uac3_cluster_information_segment_descriptor {
	bLength		len[parent, int16]
	bSegmentType	const[UAC3_CHANNEL_INFORMATION, int8]
	bChPurpose	flags[uac3_cluster_channel_purposes, int8]
	bChRelationship	flags[uac3_cluster_channel_relationships, int8]
	bChGroupID	int8
} [packed]

uac3_cluster_channel_purposes = UAC3_PURPOSE_UNDEFINED, UAC3_PURPOSE_GENERIC_AUDIO, UAC3_PURPOSE_VOICE, UAC3_PURPOSE_SPEECH, UAC3_PURPOSE_AMBIENT, UAC3_PURPOSE_REFERENCE, UAC3_PURPOSE_ULTRASONIC, UAC3_PURPOSE_VIBROKINETIC, UAC3_PURPOSE_NON_AUDIO
uac3_cluster_channel_relationships = UAC3_CH_RELATIONSHIP_UNDEFINED, UAC3_CH_MONO, UAC3_CH_LEFT, UAC3_CH_RIGHT, UAC3_CH_ARRAY, UAC3_CH_PATTERN_X, UAC3_CH_PATTERN_Y, UAC3_CH_PATTERN_A, UAC3_CH_PATTERN_B, UAC3_CH_PATTERN_M, UAC3_CH_PATTERN_S, UAC3_CH_FRONT_LEFT, UAC3_CH_FRONT_RIGHT, UAC3_CH_FRONT_CENTER, UAC3_CH_FRONT_LEFT_OF_CENTER, UAC3_CH_FRONT_RIGHT_OF_CENTER, UAC3_CH_FRONT_WIDE_LEFT, UAC3_CH_FRONT_WIDE_RIGHT, UAC3_CH_SIDE_LEFT, UAC3_CH_SIDE_RIGHT, UAC3_CH_SURROUND_ARRAY_LEFT, UAC3_CH_SURROUND_ARRAY_RIGHT, UAC3_CH_BACK_LEFT, UAC3_CH_BACK_RIGHT, UAC3_CH_BACK_CENTER, UAC3_CH_BACK_LEFT_OF_CENTER, UAC3_CH_BACK_RIGHT_OF_CENTER, UAC3_CH_BACK_WIDE_LEFT, UAC3_CH_BACK_WIDE_RIGHT, UAC3_CH_TOP_CENTER, UAC3_CH_TOP_FRONT_LEFT, UAC3_CH_TOP_FRONT_RIGHT, UAC3_CH_TOP_FRONT_CENTER, UAC3_CH_TOP_FRONT_LOC, UAC3_CH_TOP_FRONT_ROC, UAC3_CH_TOP_FRONT_WIDE_LEFT, UAC3_CH_TOP_FRONT_WIDE_RIGHT, UAC3_CH_TOP_SIDE_LEFT, UAC3_CH_TOP_SIDE_RIGHT, UAC3_CH_TOP_SURR_ARRAY_LEFT, UAC3_CH_TOP_SURR_ARRAY_RIGHT, UAC3_CH_TOP_BACK_LEFT, UAC3_CH_TOP_BACK_RIGHT, UAC3_CH_TOP_BACK_CENTER, UAC3_CH_TOP_BACK_LOC, UAC3_CH_TOP_BACK_ROC, UAC3_CH_TOP_BACK_WIDE_LEFT, UAC3_CH_TOP_BACK_WIDE_RIGHT, UAC3_CH_BOTTOM_CENTER, UAC3_CH_BOTTOM_FRONT_LEFT, UAC3_CH_BOTTOM_FRONT_RIGHT, UAC3_CH_BOTTOM_FRONT_CENTER, UAC3_CH_BOTTOM_FRONT_LOC, UAC3_CH_BOTTOM_FRONT_ROC, UAC3_CH_BOTTOM_FRONT_WIDE_LEFT, UAC3_CH_BOTTOM_FRONT_WIDE_RIGHT, UAC3_CH_BOTTOM_SIDE_LEFT, UAC3_CH_BOTTOM_SIDE_RIGHT, UAC3_CH_BOTTOM_SURR_ARRAY_LEFT, UAC3_CH_BOTTOM_SURR_ARRAY_RIGHT, UAC3_CH_BOTTOM_BACK_LEFT, UAC3_CH_BOTTOM_BACK_RIGHT, UAC3_CH_BOTTOM_BACK_CENTER, UAC3_CH_BOTTOM_BACK_LOC, UAC3_CH_BOTTOM_BACK_ROC, UAC3_CH_BOTTOM_BACK_WIDE_LEFT, UAC3_CH_BOTTOM_BACK_WIDE_RIGHT, UAC3_CH_LOW_FREQUENCY_EFFECTS, UAC3_CH_LFE_LEFT, UAC3_CH_LFE_RIGHT, UAC3_CH_HEADPHONE_LEFT, UAC3_CH_HEADPHONE_RIGHT

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# This list consists of uac3_func_subclasses + uac3_badd_classes.
uac3_all_subclasses = UAC3_FUNCTION_SUBCLASS_UNDEFINED, UAC3_FUNCTION_SUBCLASS_FULL_ADC_3_0, UAC3_FUNCTION_SUBCLASS_GENERIC_IO, UAC3_FUNCTION_SUBCLASS_HEADPHONE, UAC3_FUNCTION_SUBCLASS_SPEAKER, UAC3_FUNCTION_SUBCLASS_MICROPHONE, UAC3_FUNCTION_SUBCLASS_HEADSET, UAC3_FUNCTION_SUBCLASS_HEADSET_ADAPTER, UAC3_FUNCTION_SUBCLASS_SPEAKERPHONE

uac3_feature_unit_controls = UAC3_FUNCTION_SUBCLASS_UNDEFINED, UAC3_FUNCTION_DESKTOP_SPEAKER, UAC3_FUNCTION_HOME_THEATER, UAC3_FUNCTION_MICROPHONE, UAC3_FUNCTION_HEADSET, UAC3_FUNCTION_TELEPHONE, UAC3_FUNCTION_CONVERTER, UAC3_FUNCTION_SOUND_RECORDER, UAC3_FUNCTION_IO_BOX, UAC3_FUNCTION_MUSICAL_INSTRUMENT, UAC3_FUNCTION_PRO_AUDIO, UAC3_FUNCTION_AUDIO_VIDEO, UAC3_FUNCTION_CONTROL_PANEL, UAC3_FUNCTION_HEADPHONE, UAC3_FUNCTION_GENERIC_SPEAKER, UAC3_FUNCTION_HEADSET_ADAPTER, UAC3_FUNCTION_SPEAKERPHONE, UAC3_FUNCTION_OTHER

# TODO: Support uac3 badd profiles. See sound/usb/mixer.c: snd_usb_mixer_controls_badd()
# uac3_badd_endpoint_descriptor {
# 	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac3_iso_endpoint_descriptor]
# } [packed]

#uac3_badd_maxsizes = UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16,UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16,UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24,UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24,UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16,UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16,UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24,UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# MIDI device class specific descriptions.
# https://www.usb.org/sites/default/files/midi10.pdf
# https://elixir.bootlin.com/linux/latest/source/sound/usb/midi.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_midi.c

syz_usb_connect$midi(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_midi], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb (timeout[3000], prog_timeout[3000], remote_cover)

usb_device_descriptor_midi {
	inner	usb_device_descriptor_t[0, 0, 0, 0x1430, 0x474b, 64, array[usb_config_descriptor_midi, 1]]
} [packed]

usb_config_descriptor_midi {
	inner	usb_config_descriptor_t[const[1, int8], const[1, int8], usb_interface_descriptors_midi]
} [packed]

usb_interface_descriptors_midi {
	inner	usb_interface_descriptors_midi_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_midi_inner {
	control	usb_interface_descriptor_eps_array_t[const[0, int8], const[0, int8], const[USB_CLASS_AUDIO, int8], const[USB_SUBCLASS_MIDISTREAMING, int8], flags[uac_version_types, int8], array[usb_midi_iface_extra], array[usb_endpoint_descriptor_midi, 0:8]]
} [packed]

usb_endpoint_descriptor_midi {
	inner	usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], flags[usb_endpoint_attributes, int8], usb_ms_endpoint_descriptor]
} [packed]

midi_jack_type = USB_MS_EMBEDDED, USB_MS_EXTERNAL
uac_version_types = UAC_VERSION_1, UAC_VERSION_2, UAC_VERSION_3

usb_ms_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubType	const[USB_MS_GENERAL, int8]
	bNumEmbMIDIJack		len[baAssocJackID, int8]
	baAssocJackID		array[int8, 0:16]
} [packed]

usb_midi_iface_extra [
	ms_header	usb_ms_header_descriptor
	midi_in_jack	usb_midi_in_jack_descriptor
	midi_out_jack	usb_midi_out_jack_descriptor
] [varlen]

usb_ms_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_HEADER, int8]
	bcdMSC			int16
	wTotalLength		len[parent, int16]
} [packed]

usb_midi_in_jack_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIDI_IN_JACK, int8]
	bJackType		flags[midi_jack_type, int8]
	bJackID			int8
	iJack			int8
} [packed]

usb_midi_out_jack_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIDI_OUT_JACK, int8]
	bJackType		flags[midi_jack_type, int8]
	bJackID			int8
	bNrInputPins		len[pins, int8]
	pins			array[usb_midi_source_pin]
	iJack			int8
} [packed]

usb_midi_source_pin {
	baSourceID	int8
	baSourcePin	int8
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# ath9k driver specific descriptions.

include <drivers/net/wireless/ath/ath9k/htc_hst.h>
include <drivers/net/wireless/ath/ath9k/hif_usb.h>

define USB_ENDPOINT_ATH9K_BULK_OUT_ADDRESS	(1)
define USB_ENDPOINT_ATH9K_BULK_IN_ADDRESS	(2 | USB_DIR_IN)
define USB_ENDPOINT_ATH9K_INT_IN_ADDRESS	(3 | USB_DIR_IN)
define USB_ENDPOINT_ATH9K_INT_OUT_ADDRESS	(4)
define USB_ENDPOINT_ATH9K_BULK_EXTRA1_ADDRESS	(5)
define USB_ENDPOINT_ATH9K_BULK_EXTRA2_ADDRESS	(6)

resource fd_usb_ath9k[fd_usb]

syz_usb_connect_ath9k(speed const[USB_SPEED_HIGH], dev_len len[dev], dev ptr[in, usb_device_descriptor_ath9k], conn_descs const[0]) fd_usb_ath9k (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_ep_write$ath9k_ep1(fd fd_usb_ath9k, ep const[USB_ENDPOINT_ATH9K_BULK_IN_ADDRESS], len bytesize[data], data ptr[in, ath9k_bulk_frame]) (timeout[300], remote_cover)
syz_usb_ep_write$ath9k_ep2(fd fd_usb_ath9k, ep const[USB_ENDPOINT_ATH9K_INT_IN_ADDRESS], len bytesize[data], data ptr[in, htc_frame]) (timeout[300], remote_cover)

usb_device_descriptor_ath9k {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0xcf3, 0x9271, 0x108, array[usb_config_descriptor_ath9k, 1]]
} [packed]

usb_config_descriptor_ath9k {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_ath9k]
} [packed]

usb_interface_descriptor_ath9k {
	iface	usb_interface_descriptor_fixed_t[0, 0, 6, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_ath9k]
} [packed]

usb_endpoint_descriptors_ath9k {
	bulk_out	usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_OUT_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
	bulk_in		usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_IN_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
	int_in		usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_INT_IN_ADDRESS, USB_ENDPOINT_ATH9K_INT_ATTRIBUTES, 64, 1, void]
	int_out		usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_INT_OUT_ADDRESS, USB_ENDPOINT_ATH9K_INT_ATTRIBUTES, 64, 1, void]
	bulk_extra1	usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_EXTRA1_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
	bulk_extra2	usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_EXTRA2_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
} [packed]

define USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_ATH9K_INT_ATTRIBUTES	(USB_ENDPOINT_XFER_INT)

ath9k_bulk_frame {
	packets	array[ath9k_bulk_packet]
} [packed]

ath9k_bulk_packet {
	pkt_len	len[data, int16]
	pkt_tag	const[ATH_USB_RX_STREAM_MODE_TAG, int16]
	data	array[int8]
} [packed, align[4]]

htc_frame [
	ready		htc_ready_frame
	conn_svc_rsp	htc_conn_svc_rsp_frame
	generic		htc_generic_frame
] [varlen]

# This is actually wrong, as the driver is buggy and doesn't skip the header
# before processing the frame payload, but let's leave it like thise for now.
htc_ready_frame {
	endpoint_id	const[0, int8]
	flags		const[0, int8]
	payload_len	len[payload, int16be]
	control		array[int8, 4]
	payload		htc_ready_msg
} [packed]

htc_ready_msg {
	message_id	const[HTC_MSG_READY_ID, int16be]
	credits		int16be
	credit_size	int16be
	max_endpoints	int8
	pad		int8
} [packed]

htc_conn_svc_rsp_frame {
	endpoint_id	const[0, int8]
	flags		const[0, int8]
	payload_len	len[payload, int16be]
	control		array[int8, 4]
	payload		htc_conn_svc_rspmsg
} [packed]

htc_conn_svc_rspmsg {
	message_id	const[HTC_MSG_CONNECT_SERVICE_RESPONSE_ID, int16be]
	service_id	flags[htc_svcs, int16be]
	status		const[HTC_SERVICE_SUCCESS, int8]
	endpoint_id	int8
	max_msg_len	int16be
	svc_meta_len	int8
	pad		int8
} [packed]

htc_svcs = HTC_CTRL_RSVD_SVC, HTC_LOOPBACK_RSVD_SVC, WMI_CONTROL_SVC, WMI_BEACON_SVC, WMI_CAB_SVC, WMI_UAPSD_SVC, WMI_MGMT_SVC, WMI_DATA_VO_SVC, WMI_DATA_VI_SVC, WMI_DATA_BE_SVC, WMI_DATA_BE_SVC

htc_generic_frame {
	endpoint_id	int8[0:8]
	flags		flags[htc_frame_flags, int8]
	payload_len	len[payload, int16be]
	control		array[int8, 4]
	payload		array[int8, 0:256]
} [packed]

htc_frame_flags = HTC_FLAGS_RECV_TRAILER

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Assorted driver-specific descriptions of generic syz_* calls' variants.

# Generic calls such as syz_usb_connect() and syz_usb_control_io() should be enough
# (in theory) to emulate a proper device and finish driver probes without a hitch.
# However, there are cases when syzkaller fails to come up with correct inputs to achieve it.
# Use fixed descriptors to quickly pass through probe() to access select drivers' post-probe functionality.

# It is important to note that, one way or another, drivers in question require multiple control requests
# between a driver and a device processed during probe(). Descriptions below do not deal with specific
# CTRL requests as such (except for basic information included in vusb_responses_XXX). Instead, rely on
# seeds, created both manually and with syzkaller's help. For examples, see sys/linux/test/vusb_XXX.

# Common constants for endpoint descriptors.
define USB_ENDPOINT_BULK_ATTR	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_INT_ATTR	(USB_ENDPOINT_XFER_INT)

define USB_FIXED_ENDPOINT_BULK_IN_ADDR	(1 | USB_DIR_IN)
define USB_FIXED_ENDPOINT_BULK_OUT_ADDR	(2)
define USB_FIXED_ENDPOINT_INT_IN_ADDR	(3 | USB_DIR_IN)

define USB_RECIP_DEVICE	0x00

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# rtl8150 driver specific descriptions.

resource fd_usb_rtl8150[fd_usb]

syz_usb_connect$rtl8150(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_rtl8150], conn_descs const[0]) fd_usb_rtl8150 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$rtl8150(fd fd_usb_rtl8150, descs ptr[in, vusb_descriptors_rtl8150], resps ptr[in, vusb_responses_rtl8150]) (timeout[300], remote_cover)

usb_device_descriptor_rtl8150 {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0xbda, 0x8150, 0, array[usb_config_descriptor_rtl8150, 1]]
} [packed]

usb_config_descriptor_rtl8150 {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_rtl8150]
} [packed]

usb_interface_descriptor_rtl8150 {
	iface	usb_interface_descriptor_fixed_t[0, 0, 3, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_rtl8150]
} [packed]

usb_endpoint_descriptors_rtl8150 {
	bulk_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_IN_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	bulk_out	usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_OUT_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	int_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_INT_IN_ADDR, USB_ENDPOINT_INT_ATTR, 64, 1, void]
} [packed]

vusb_descriptors_rtl8150 {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_rtl8150 {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	RTL8150_REQ_GET_REGS		ptr[in, vusb_response_t[RTL8150_REQT_READ, RTL8150_REQ_GET_REGS, array[int8, 0:6]]]
	RTL8150_REQ_SET_REGS		ptr[in, vusb_response_t[RTL8150_REQT_WRITE, RTL8150_REQ_SET_REGS, array[int8, 0:6]]]
} [packed]

define RTL8150_REQ_GET_REGS	0x05
define RTL8150_REQ_SET_REGS	0x05
define RTL8150_REQT_READ	0xc0
define RTL8150_REQT_WRITE	0x40

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# sierra_net driver specific descriptions.

resource fd_usb_sierra_net[fd_usb]

syz_usb_connect$sierra_net(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_sierra_net], conn_descs const[0]) fd_usb_sierra_net (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$sierra_net(fd fd_usb_sierra_net, descs ptr[in, vusb_descriptors_sierra_net], resps ptr[in, vusb_responses_sierra_net]) (timeout[300], remote_cover)

usb_device_descriptor_sierra_net {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0x1199, 0x68a3, 0, array[usb_config_descriptor_sierra_net, 1]]
} [packed]

usb_config_descriptor_sierra_net {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_sierra_net]
} [packed]

usb_interface_descriptor_sierra_net {
	iface	usb_interface_descriptor_fixed_t[7, 0, 3, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_sierra_net]
} [packed]

# sierra_net driver does not expect fixed ep addresses, so refrain from being too specific here.
# As long as we ensure there are 3 endpoints, 2 bulk and 1 int, syzkaller should figure it out.
usb_endpoint_descriptors_sierra_net {
	bulk_in		usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], const[USB_ENDPOINT_BULK_ATTR, int8], void]
	bulk_out	usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], const[USB_ENDPOINT_BULK_ATTR, int8], void]
	status		usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], const[USB_ENDPOINT_INT_ATTR, int8], void]
} [packed]

vusb_descriptors_sierra_net {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_sierra_net {
	len					len[parent, int32]
	generic					ptr[in, vusb_response_generic]

	USB_CDC_GET_ENCAPSULATED_RESPONSE	ptr[in, vusb_response_t[SIERRA_CMD_TYPE_IN, USB_CDC_GET_ENCAPSULATED_RESPONSE, array[int8, 1024]]]
	USB_CDC_SEND_ENCAPSULATED_COMMANDT	ptr[in, vusb_response_t[SIERRA_CMD_TYPE_OUT, USB_CDC_SEND_ENCAPSULATED_COMMAND, array[int8, 0:4]]]
} [packed]

define SIERRA_CMD_TYPE_IN	(USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)
define SIERRA_CMD_TYPE_OUT	(USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# lan78xx driver specific descriptions.
# While these syz_* variants noticably help with the probe() process, they are not enough.
# This is due to a high number of control requests expected between the driver and the device.

include <drivers/net/usb/smsc95xx.h>

resource fd_usb_lan78xx[fd_usb]

syz_usb_connect$lan78xx(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_lan78xx], conn_descs const[0]) fd_usb_lan78xx (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$lan78xx(fd fd_usb_lan78xx, descs ptr[in, vusb_descriptors_lan78xx], resps ptr[in, vusb_responses_lan78xx]) (timeout[300], remote_cover)

usb_device_descriptor_lan78xx {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0x424, 0x7850, 0, array[usb_config_descriptor_lan78xx, 1]]
} [packed]

usb_config_descriptor_lan78xx {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_lan78xx]
} [packed]

usb_interface_descriptor_lan78xx {
	iface	usb_interface_descriptor_fixed_t[0, 0, 3, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_lan78xx]
} [packed]

usb_endpoint_descriptors_lan78xx {
	bulk_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_IN_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	bulk_out	usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_OUT_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	int_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_INT_IN_ADDR, USB_ENDPOINT_INT_ATTR, 64, 1, void]
} [packed]

vusb_descriptors_lan78xx {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_lan78xx {
	len					len[parent, int32]
	generic					ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE			ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	USB_VENDOR_REQUEST_READ_REGISTER	ptr[in, vusb_response_t[LAN78XX_REG_TYPE_IN, USB_VENDOR_REQUEST_READ_REGISTER, int32]]
	USB_VENDOR_REQUEST_WRITE_REGISTER	ptr[in, vusb_response_t[LAN78XX_REG_TYPE_OUT, USB_VENDOR_REQUEST_WRITE_REGISTER, int32]]
	USB_VENDOR_REQUEST_GET_STATS		ptr[in, vusb_response_t[LAN78XX_REG_TYPE_IN, USB_VENDOR_REQUEST_GET_STATS, array[int8, 47]]]
} [packed]

define LAN78XX_REG_TYPE_IN	(USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
define LAN78XX_REG_TYPE_OUT	(USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
]

87/2 2026/07/30 12:23 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 139351
							output: 27
							thoughts: 2251
						

Thoughts:
**USB Device Descriptors and the au0828 Driver**

Okay, so I'm thinking about how to trigger the `au0828` driver via `syz_usb_connect`.  My initial thought is to just use `syz_usb_connect` directly with the vendor and product IDs `0x2040` and `0x7200`.  I know `syz_usb_connect` takes a `usb_device_descriptor`, which should be fine.  I'll just pass the `usb_device_descriptor_t` and set the vendor/product IDs.

I immediately need to remember that the `au0828` driver is a *media* driver, so there will likely be endpoints involved. Checking the `au0828_usb_probe` function I see endpoint access, so I know I'll need to account for that.  Specifically, it accesses `endpoint[isoc_pipe]` and there's a check for `bNumEndpoints`. So, if there are no endpoints, things will crash. I confirm that it requires at least one endpoint.

The next thought is to just craft a generic descriptor, patch the IDs in the syzkaller program, but a quick check reveals that `syzkaller` *does* allow patching of `idVendor` and `idProduct` using Go code. The note clarifies that these, along with `bDeviceClass`, `bDeviceSubClass`, `bDeviceProtocol`, and `bcdDevice` are patched by Go code. Wait, I realize I can just write the raw bytes directly. I need to use `&AUTO="..."` or `&AUTO={...}`.

I now decide to build a complete valid USB descriptor for the `au0828`.  I need a device, configuration, interface, and endpoint descriptors.  I start by constructing the device descriptor (18 bytes), then the config descriptor (9 bytes), which includes an interface association descriptor (IAD, 8 bytes).  The IAD will have `bFirstInterface = 1` which is relevant to the probe. Then a dummy interface 0, an interface 1 (which is the actual `au0828`), and finally an endpoint descriptor.  It's clear that the total length in the config descriptor needs to accommodate all the descriptors.  I need to recalculate `wTotalLength`. I remember to include the IAD and dummy interface 0. I now recalculate it, and construct it again.

Okay, I've got my hex string and I am ready to try it.  Wait, the `au0828_usb_probe` function seems to expect an Interface Association Descriptor (IAD) and the code checks `assoc_desc->bFirstInterface` against `ifnum`, which is 1. My IAD is good because it has `bFirstInterface = 1`.

Now I'm looking at `au0828_usb_probe` and I'm seeing an access to `udev->actconfig->interface[idx]`, but what is `idx` and `dev->current_pcb_config`?  Oh, wait, I'm thinking of the `cx231xx` probe, not `au0828`. Let's just focus on the `au0828` probe.



88/2 2026/07/30 12:23 tool codesearch-definition-source
0m Args:
map[Name:au0828_usb_probe]

Results:
map[SourceCode: 643:	static int au0828_usb_probe(struct usb_interface *interface,
 644:		const struct usb_device_id *id)
 645:	{
 646:		int ifnum;
 647:		int retval = 0;
 648:	
 649:		struct au0828_dev *dev;
 650:		struct usb_device *usbdev = interface_to_usbdev(interface);
 651:	
 652:		ifnum = interface->altsetting->desc.bInterfaceNumber;
 653:	
 654:		if (ifnum != 0)
 655:			return -ENODEV;
 656:	
 657:		dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__,
 658:			le16_to_cpu(usbdev->descriptor.idVendor),
 659:			le16_to_cpu(usbdev->descriptor.idProduct),
 660:			ifnum);
 661:	
 662:		/*
 663:		 * Make sure we have 480 Mbps of bandwidth, otherwise things like
 664:		 * video stream wouldn't likely work, since 12 Mbps is generally
 665:		 * not enough even for most Digital TV streams.
 666:		 */
 667:		if (usbdev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) {
 668:			pr_err("au0828: Device initialization failed.\n");
 669:			pr_err("au0828: Device must be connected to a high-speed USB 2.0 port.\n");
 670:			return -ENODEV;
 671:		}
 672:	
 673:		dev = kzalloc_obj(*dev);
 674:		if (dev == NULL) {
 675:			pr_err("%s() Unable to allocate memory\n", __func__);
 676:			return -ENOMEM;
 677:		}
 678:	
 679:		mutex_init(&dev->lock);
 680:		mutex_lock(&dev->lock);
 681:		mutex_init(&dev->mutex);
 682:		mutex_init(&dev->dvb.lock);
 683:		dev->usbdev = usbdev;
 684:		dev->boardnr = id->driver_info;
 685:		dev->board = au0828_boards[dev->boardnr];
 686:	
 687:		/* Initialize the media controller */
 688:		retval = au0828_media_device_init(dev, usbdev);
 689:		if (retval) {
 690:			pr_err("%s() au0828_media_device_init failed\n",
 691:			       __func__);
 692:			mutex_unlock(&dev->lock);
 693:			kfree(dev);
 694:			return retval;
 695:		}
 696:	
 697:		retval = au0828_v4l2_device_register(interface, dev);
 698:		if (retval) {
 699:			au0828_usb_v4l2_media_release(dev);
 700:			mutex_unlock(&dev->lock);
 701:			kfree(dev);
 702:			return retval;
 703:		}
 704:	
 705:		/* Power Up the bridge */
 706:		au0828_write(dev, REG_600, 1 << 4);
 707:	
 708:		/* Bring up the GPIO's and supporting devices */
 709:		au0828_gpio_setup(dev);
 710:	
 711:		/* I2C */
 712:		au0828_i2c_register(dev);
 713:	
 714:		/* Setup */
 715:		au0828_card_setup(dev);
 716:	
 717:		/*
 718:		 * Store the pointer to the au0828_dev so it can be accessed in
 719:		 * au0828_usb_disconnect
 720:		 */
 721:		usb_set_intfdata(interface, dev);
 722:	
 723:		/* Analog TV */
 724:		retval = au0828_analog_register(dev, interface);
 725:		if (retval) {
 726:			pr_err("%s() au0828_analog_register failed to register on V4L2\n",
 727:				__func__);
 728:			mutex_unlock(&dev->lock);
 729:			goto done;
 730:		}
 731:	
 732:		/* Digital TV */
 733:		retval = au0828_dvb_register(dev);
 734:		if (retval)
 735:			pr_err("%s() au0828_dvb_register failed\n",
 736:			       __func__);
 737:	
 738:		/* Remote controller */
 739:		au0828_rc_register(dev);
 740:	
 741:		pr_info("Registered device AU0828 [%s]\n",
 742:			dev->board.name == NULL ? "Unset" : dev->board.name);
 743:	
 744:		mutex_unlock(&dev->lock);
 745:	
 746:		retval = au0828_media_device_register(dev, usbdev);
 747:	
 748:	done:
 749:		if (retval < 0)
 750:			au0828_usb_disconnect(interface);
 751:	
 752:		return retval;
 753:	}
 SourceFile:drivers/media/usb/au0828/au0828-core.c]

89/2 2026/07/30 12:23 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 144037
							output: 25
							thoughts: 3477
						

Thoughts:
**Analyzing the USB Probe and I2C Adapter Bug**

Okay, so the initial plan hinges on getting `au0828_usb_probe` to trigger. I've realized that it expects a specific USB configuration: a single interface (0) and high speed. With this knowledge, I've constructed the necessary USB descriptors (device, config, interface, and endpoint) in hex format, which will be passed to `syz_usb_connect`. The connection will be at `USB_SPEED_HIGH`, or 3, according to the `vusb.txt` documentation.

Now I'm looking at `syz_usb_connect`. It seems like I need to supply some `conn_descs`. Although `conn_descs` appears to be optional, it is defined as a pointer, which means it could crash if null, so I'll pass a zeroed-out `&AUTO` structure for it.

The next issue is keeping the `au0828_dev` alive. I'm going to attempt to reproduce the bug by opening some `/dev/videoX` and `/dev/i2c-X` devices. It's likely that a dynamic I2C adapter assignment will be needed, so I'll open several. I'll need to call `ioctl(fd, I2C_SMBUS, ...)` on the opened I2C devices to interact with the USB device.

I've crafted a syzkaller program that first connects a USB device using the previously constructed descriptors and a high speed setting. Then, it opens and holds open a few video and I2C devices. Finally, it disconnects the USB device and attempts the `I2C_SMBUS` ioctl calls.

After reviewing the code again, I've ensured that the `I2C_SMBUS` command code is 0x720. I've also made sure I understand the `i2c_smbus_ioctl_data` structure and will pass the appropriate arguments to it with the syzkaller calls.

However, I've had a thought that the target driver, `au0828`, may not be the culprit, so I've been considering other candidates. I've been analyzing the KASAN report and matching the allocation sizes in the report with USB driver data structures, specifically the `i2c_adapter` and its link to the `usb_device` structure. I've deduced that the error may not be in the `dvb_usb` or `dvb_usb_v2`, nor `hdpvr`, drivers because of how they handle the I2C adapter removal. It seems, based on the allocation sizes in the KASAN report, that `pvrusb2` is the likely cause. It would appear that the disconnecting of the USB device may free the underlying `usb_device` structure while the I2C adapter is still registered. I'll need to double check the USB IDs used by `pvrusb2`.



90/2 2026/07/30 12:23 tool codesearch-definition-source
0m Args:
map[Name:pvr2_device_table]

Results:
map[SourceCode: 684:	struct usb_device_id pvr2_device_table[] = {
 685:		{ USB_DEVICE(0x2040, 0x2900),
 686:		  .driver_info = (kernel_ulong_t)&pvr2_device_29xxx},
 687:		{ USB_DEVICE(0x2040, 0x2950), /* Logically identical to 2900 */
 688:		  .driver_info = (kernel_ulong_t)&pvr2_device_29xxx},
 689:		{ USB_DEVICE(0x2040, 0x2400),
 690:		  .driver_info = (kernel_ulong_t)&pvr2_device_24xxx},
 691:		{ USB_DEVICE(0x1164, 0x0622),
 692:		  .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2},
 693:		{ USB_DEVICE(0x1164, 0x0602),
 694:		  .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2d},
 695:		{ USB_DEVICE(0x11ba, 0x1003),
 696:		  .driver_info = (kernel_ulong_t)&pvr2_device_onair_creator},
 697:		{ USB_DEVICE(0x11ba, 0x1001),
 698:		  .driver_info = (kernel_ulong_t)&pvr2_device_onair_usb2},
 699:		{ USB_DEVICE(0x2040, 0x7300),
 700:		  .driver_info = (kernel_ulong_t)&pvr2_device_73xxx},
 701:		{ USB_DEVICE(0x2040, 0x7500),
 702:		  .driver_info = (kernel_ulong_t)&pvr2_device_750xx},
 703:		{ USB_DEVICE(0x2040, 0x7501),
 704:		  .driver_info = (kernel_ulong_t)&pvr2_device_751xx},
 705:		{ USB_DEVICE(0x0ccd, 0x0039),
 706:		  .driver_info = (kernel_ulong_t)&pvr2_device_av400},
 707:		{ USB_DEVICE(0x2040, 0x7502),
 708:		  .driver_info = (kernel_ulong_t)&pvr2_device_160111},
 709:		{ USB_DEVICE(0x2040, 0x7510),
 710:		  .driver_info = (kernel_ulong_t)&pvr2_device_160000},
 711:		{ }
 712:	};
 SourceFile:drivers/media/usb/pvrusb2/pvrusb2-devattr.c]

91/2 2026/07/30 12:23 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 149027
							output: 23
							thoughts: 84
						

Thoughts:
Here's my thought process, as it stands:

**Device Identification and Requirements**

Okay, so I'm cross-referencing some device IDs against known drivers. I've got `0x2040, 0x2900` – that's definitely `pvrusb2`. And then there's `0x2040, 0x7200` – ah, that's `au0828`. Not surprising, I see those quite a bit.

Now I'm diving deeper into the nuances... Right, the `au0828` driver. I recall now that this chipset *demands* a high-speed USB connection, represented by `USB_SPEED_HIGH`, and that it always seems to like being on interface number 0, indicated by `ifnum == 0`. It's finicky, that one.

But what about `pvrusb2`? I know *what* it is, but what are its specific USB requirements? I need to quickly recall what it needs in terms of USB speed and interface assignments to make sure things are configured correctly. I need to refresh that in my head.



92/2 2026/07/30 12:24 tool codesearch-definition-source
0m Error:
log-in to see details

Args:
map[Name:pvr2_probe]

Results:
map[SourceCode: SourceFile:]

93/2 2026/07/30 12:24 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 149408
							output: 35
							thoughts: 13
						

Thoughts:
Here's my attempt at summarizing the thought process, tailored for an expert audience:

**Diving into the `pvrusb2` Probe Function**

Okay, time to get my hands dirty. Let's start with the `pvrusb2` probe function. I need to refresh my memory on the initialization sequence and resource allocation, particularly around the interaction with the USB subsystem. What are the key points of the device matching and the driver registration within this function? I want to trace the hardware identification process and understand how it negotiates the interface settings, endpoint configuration and how it interacts with the firmware loading process (if applicable). I also need to make a note of potential race conditions or locking issues within the function. I should also check the error handling and debugging outputs of the probe, as it will be useful during bring-up. Where is it handling any specific vendor or device IDs? That's always a good place to begin.



94/2 2026/07/30 12:24 tool grepper
0m Args:
map[Expression:\.probe.*= PathPrefix:drivers/media/usb/pvrusb2/]

Results:
map[Output:drivers/media/usb/pvrusb2/pvrusb2-devattr.c=310=static struct tda829x_config tda829x_no_probe = {
drivers/media/usb/pvrusb2/pvrusb2-devattr.c:311:	.probe_tuner = TDA829X_DONT_PROBE,
drivers/media/usb/pvrusb2/pvrusb2-devattr.c-312-};
--
drivers/media/usb/pvrusb2/pvrusb2-main.c=85=static struct usb_driver pvr_driver = {
--
drivers/media/usb/pvrusb2/pvrusb2-main.c-87-	.id_table =     pvr2_device_table,
drivers/media/usb/pvrusb2/pvrusb2-main.c:88:	.probe =        pvr_probe,
drivers/media/usb/pvrusb2/pvrusb2-main.c-89-	.disconnect =   pvr_disconnect
]

95/2 2026/07/30 12:24 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 149927
							output: 22
							thoughts: 10
						

Thoughts:
Okay, here's my interpretation of that thought process, tailored for an expert audience, and written in the first person:

**Initial Diagnostic Step**

Right, let's start with a sanity check. Before diving too deep, I'll begin by verifying the primary sensor's behavior. I need to examine the function of `pvr_probe`. It's the go-to first step for most of these issues, so I'll see if it's returning anything immediately, or throwing errors. This is usually where I can tell, within a few seconds, if the problem is fundamental or not. I'm going to look at the logs and make a determination.



96/2 2026/07/30 12:24 tool codesearch-definition-source
0m Args:
map[Name:pvr_probe]

Results:
map[SourceCode:  48:	static int pvr_probe(struct usb_interface *intf,
  49:			     const struct usb_device_id *devid)
  50:	{
  51:		struct pvr2_context *pvr;
  52:	
  53:		/* Create underlying hardware interface */
  54:		pvr = pvr2_context_create(intf,devid,pvr_setup_attach);
  55:		if (!pvr) {
  56:			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
  57:				   "Failed to create hdw handler");
  58:			return -ENOMEM;
  59:		}
  60:	
  61:		pvr2_trace(PVR2_TRACE_INIT,"pvr_probe(pvr=%p)",pvr);
  62:	
  63:		usb_set_intfdata(intf, pvr);
  64:	
  65:		return 0;
  66:	}
 SourceFile:drivers/media/usb/pvrusb2/pvrusb2-main.c]

97/2 2026/07/30 12:24 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 150409
							output: 25
							thoughts: 45
						

Thoughts:
Okay, here's my interpretation of those thoughts, framed as my own:

**Analyzing the `pvrusb2` Driver's Probing Mechanism**

Right, let me see... I'm looking at this `pvrusb2` driver and its probing routine. It seems like it's taking a more straightforward approach compared to some others I've seen. Specifically, it doesn't appear to explicitly validate the `ifnum` or `speed` parameters directly within the `pvr_probe` function. That's interesting; it's definitely a simpler approach at this initial stage. I wonder if this simplification has advantages, or potential downsides, down the road.

Hang on a minute… it just clicked! My gut tells me that `pvr2_context_create` is the function that likely handles those specific checks of interface number and device speed. Let me double check, I might have the function name wrong... yes, that's it. It would make sense to defer those validations until the context is actually being created. Okay, that makes more sense.



98/2 2026/07/30 12:24 tool codesearch-definition-source
0m Args:
map[Name:pvr2_context_create]

Results:
map[SourceCode: 201:	struct pvr2_context *pvr2_context_create(
 202:		struct usb_interface *intf,
 203:		const struct usb_device_id *devid,
 204:		void (*setup_func)(struct pvr2_context *))
 205:	{
 206:		struct pvr2_context *mp = NULL;
 207:		mp = kzalloc_obj(*mp);
 208:		if (!mp) goto done;
 209:		pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (create)",mp);
 210:		mp->setup_func = setup_func;
 211:		mutex_init(&mp->mutex);
 212:		mutex_lock(&pvr2_context_mutex);
 213:		mp->exist_prev = pvr2_context_exist_last;
 214:		mp->exist_next = NULL;
 215:		pvr2_context_exist_last = mp;
 216:		if (mp->exist_prev) {
 217:			mp->exist_prev->exist_next = mp;
 218:		} else {
 219:			pvr2_context_exist_first = mp;
 220:		}
 221:		mutex_unlock(&pvr2_context_mutex);
 222:		mp->hdw = pvr2_hdw_create(intf,devid);
 223:		if (!mp->hdw) {
 224:			pvr2_context_destroy(mp);
 225:			mp = NULL;
 226:			goto done;
 227:		}
 228:		pvr2_context_set_notify(mp, !0);
 229:	 done:
 230:		return mp;
 231:	}
 SourceFile:drivers/media/usb/pvrusb2/pvrusb2-context.c]

99/2 2026/07/30 12:24 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 151249
							output: 26
							thoughts: 15
						

Thoughts:
Okay, here's my take on those thoughts, framed as an expert's internal monologue:

**Hardware Context Creation - `pvr2_hdw_create`**

Right, let's break this down. `pvr2_hdw_create`. Straight away, I'm thinking about the low-level hardware context. It's the foundation, the scaffolding, the root from which everything else in the graphics pipeline will grow. This function, `pvr2_hdw_create`, is absolutely critical. It's the point where we instantiate the hardware resources needed for our rendering operations.

I'm imagining all the underlying setup: allocating memory, initializing registers, ensuring proper communication channels, and configuring whatever PVR-specific hardware is involved. Is it a unified memory architecture? Discrete? What clock rates are we dealing with? Is there a need for cache configuration or memory aliasing? Depending on the architecture it could be allocating command buffers, setting up DMA channels, or enabling interrupt vectors.

There are many design considerations to think about. What error handling is in place? What access controls are there to ensure safe operation? `pvr2_hdw_create` would need to be robust – you can't have a flaky foundation. You've got to ensure the structure, the drivers, the devices, can work together. This is where it all begins. And without a properly functioning hardware context, nothing else will work. So, this function's got to be bulletproof.



100/2 2026/07/30 12:24 tool codesearch-definition-source
0m Args:
map[Name:pvr2_hdw_create]

Results:
map[SourceCode:2344:	/* Create, set up, and return a structure for interacting with the
2345:	   underlying hardware.  */
2346:	struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
2347:					 const struct usb_device_id *devid)
2348:	{
2349:		unsigned int idx,cnt1,cnt2,m;
2350:		struct pvr2_hdw *hdw = NULL;
2351:		int valid_std_mask;
2352:		struct pvr2_ctrl *cptr;
2353:		struct usb_device *usb_dev;
2354:		const struct pvr2_device_desc *hdw_desc;
2355:		__u8 ifnum;
2356:		struct v4l2_queryctrl qctrl;
2357:		struct pvr2_ctl_info *ciptr;
2358:	
2359:		usb_dev = interface_to_usbdev(intf);
2360:	
2361:		hdw_desc = (const struct pvr2_device_desc *)(devid->driver_info);
2362:	
2363:		if (hdw_desc == NULL) {
2364:			pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_create: No device description pointer, unable to continue.");
2365:			pvr2_trace(PVR2_TRACE_INIT,
2366:				   "If you have a new device type, please contact Mike Isely <isely@pobox.com> to get it included in the driver");
2367:			goto fail;
2368:		}
2369:	
2370:		hdw = kzalloc_obj(*hdw);
2371:		pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"",
2372:			   hdw,hdw_desc->description);
2373:		pvr2_trace(PVR2_TRACE_INFO, "Hardware description: %s",
2374:			hdw_desc->description);
2375:		if (hdw_desc->flag_is_experimental) {
2376:			pvr2_trace(PVR2_TRACE_INFO, "**********");
2377:			pvr2_trace(PVR2_TRACE_INFO,
2378:				   "***WARNING*** Support for this device (%s) is experimental.",
2379:								      hdw_desc->description);
2380:			pvr2_trace(PVR2_TRACE_INFO,
2381:				   "Important functionality might not be entirely working.");
2382:			pvr2_trace(PVR2_TRACE_INFO,
2383:				   "Please consider contacting the driver author to help with further stabilization of the driver.");
2384:			pvr2_trace(PVR2_TRACE_INFO, "**********");
2385:		}
2386:		if (!hdw) goto fail;
2387:	
2388:		timer_setup(&hdw->quiescent_timer, pvr2_hdw_quiescent_timeout, 0);
2389:	
2390:		timer_setup(&hdw->decoder_stabilization_timer,
2391:			    pvr2_hdw_decoder_stabilization_timeout, 0);
2392:	
2393:		timer_setup(&hdw->encoder_wait_timer, pvr2_hdw_encoder_wait_timeout,
2394:			    0);
2395:	
2396:		timer_setup(&hdw->encoder_run_timer, pvr2_hdw_encoder_run_timeout, 0);
2397:	
2398:		hdw->master_state = PVR2_STATE_DEAD;
2399:	
2400:		init_waitqueue_head(&hdw->state_wait_data);
2401:	
2402:		hdw->tuner_signal_stale = !0;
2403:		cx2341x_fill_defaults(&hdw->enc_ctl_state);
2404:	
2405:		/* Calculate which inputs are OK */
2406:		m = 0;
2407:		if (hdw_desc->flag_has_analogtuner) m |= 1 << PVR2_CVAL_INPUT_TV;
2408:		if (hdw_desc->digital_control_scheme != PVR2_DIGITAL_SCHEME_NONE) {
2409:			m |= 1 << PVR2_CVAL_INPUT_DTV;
2410:		}
2411:		if (hdw_desc->flag_has_svideo) m |= 1 << PVR2_CVAL_INPUT_SVIDEO;
2412:		if (hdw_desc->flag_has_composite) m |= 1 << PVR2_CVAL_INPUT_COMPOSITE;
2413:		if (hdw_desc->flag_has_fmradio) m |= 1 << PVR2_CVAL_INPUT_RADIO;
2414:		hdw->input_avail_mask = m;
2415:		hdw->input_allowed_mask = hdw->input_avail_mask;
2416:	
2417:		/* If not a hybrid device, pathway_state never changes.  So
2418:		   initialize it here to what it should forever be. */
2419:		if (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_DTV))) {
2420:			hdw->pathway_state = PVR2_PATHWAY_ANALOG;
2421:		} else if (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_TV))) {
2422:			hdw->pathway_state = PVR2_PATHWAY_DIGITAL;
2423:		}
2424:	
2425:		hdw->control_cnt = CTRLDEF_COUNT;
2426:		hdw->control_cnt += MPEGDEF_COUNT;
2427:		hdw->controls = kzalloc_objs(struct pvr2_ctrl, hdw->control_cnt);
2428:		if (!hdw->controls) goto fail;
2429:		hdw->hdw_desc = hdw_desc;
2430:		hdw->ir_scheme_active = hdw->hdw_desc->ir_scheme;
2431:		for (idx = 0; idx < hdw->control_cnt; idx++) {
2432:			cptr = hdw->controls + idx;
2433:			cptr->hdw = hdw;
2434:		}
2435:		for (idx = 0; idx < 32; idx++) {
2436:			hdw->std_mask_ptrs[idx] = hdw->std_mask_names[idx];
2437:		}
2438:		for (idx = 0; idx < CTRLDEF_COUNT; idx++) {
2439:			cptr = hdw->controls + idx;
2440:			cptr->info = control_defs+idx;
2441:		}
2442:	
2443:		/* Ensure that default input choice is a valid one. */
2444:		m = hdw->input_avail_mask;
2445:		if (m) for (idx = 0; idx < (sizeof(m) << 3); idx++) {
2446:			if (!((1UL << idx) & m)) continue;
2447:			hdw->input_val = idx;
2448:			break;
2449:		}
2450:	
2451:		/* Define and configure additional controls from cx2341x module. */
2452:		hdw->mpeg_ctrl_info = kzalloc_objs(*(hdw->mpeg_ctrl_info),
2453:						   MPEGDEF_COUNT);
2454:		if (!hdw->mpeg_ctrl_info) goto fail;
2455:		for (idx = 0; idx < MPEGDEF_COUNT; idx++) {
2456:			cptr = hdw->controls + idx + CTRLDEF_COUNT;
2457:			ciptr = &(hdw->mpeg_ctrl_info[idx].info);
2458:			ciptr->desc = hdw->mpeg_ctrl_info[idx].desc;
2459:			ciptr->name = mpeg_ids[idx].strid;
2460:			ciptr->v4l_id = mpeg_ids[idx].id;
2461:			ciptr->skip_init = !0;
2462:			ciptr->get_value = ctrl_cx2341x_get;
2463:			ciptr->get_v4lflags = ctrl_cx2341x_getv4lflags;
2464:			ciptr->is_dirty = ctrl_cx2341x_is_dirty;
2465:			if (!idx) ciptr->clear_dirty = ctrl_cx2341x_clear_dirty;
2466:			qctrl.id = ciptr->v4l_id;
2467:			cx2341x_ctrl_query(&hdw->enc_ctl_state,&qctrl);
2468:			if (!(qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY)) {
2469:				ciptr->set_value = ctrl_cx2341x_set;
2470:			}
2471:			strscpy(hdw->mpeg_ctrl_info[idx].desc, qctrl.name,
2472:				sizeof(hdw->mpeg_ctrl_info[idx].desc));
2473:			ciptr->default_value = qctrl.default_value;
2474:			switch (qctrl.type) {
2475:			default:
2476:			case V4L2_CTRL_TYPE_INTEGER:
2477:				ciptr->type = pvr2_ctl_int;
2478:				ciptr->def.type_int.min_value = qctrl.minimum;
2479:				ciptr->def.type_int.max_value = qctrl.maximum;
2480:				break;
2481:			case V4L2_CTRL_TYPE_BOOLEAN:
2482:				ciptr->type = pvr2_ctl_bool;
2483:				break;
2484:			case V4L2_CTRL_TYPE_MENU:
2485:				ciptr->type = pvr2_ctl_enum;
2486:				ciptr->def.type_enum.value_names =
2487:					cx2341x_ctrl_get_menu(&hdw->enc_ctl_state,
2488:									ciptr->v4l_id);
2489:				for (cnt1 = 0;
2490:				     ciptr->def.type_enum.value_names[cnt1] != NULL;
2491:				     cnt1++) { }
2492:				ciptr->def.type_enum.count = cnt1;
2493:				break;
2494:			}
2495:			cptr->info = ciptr;
2496:		}
2497:	
2498:		// Initialize control data regarding video standard masks
2499:		valid_std_mask = pvr2_std_get_usable();
2500:		for (idx = 0; idx < 32; idx++) {
2501:			if (!(valid_std_mask & (1UL << idx))) continue;
2502:			cnt1 = pvr2_std_id_to_str(
2503:				hdw->std_mask_names[idx],
2504:				sizeof(hdw->std_mask_names[idx])-1,
2505:				1UL << idx);
2506:			hdw->std_mask_names[idx][cnt1] = 0;
2507:		}
2508:		cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDAVAIL);
2509:		if (cptr) {
2510:			memcpy(&hdw->std_info_avail,cptr->info,
2511:			       sizeof(hdw->std_info_avail));
2512:			cptr->info = &hdw->std_info_avail;
2513:			hdw->std_info_avail.def.type_bitmask.bit_names =
2514:				hdw->std_mask_ptrs;
2515:			hdw->std_info_avail.def.type_bitmask.valid_bits =
2516:				valid_std_mask;
2517:		}
2518:		cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR);
2519:		if (cptr) {
2520:			memcpy(&hdw->std_info_cur,cptr->info,
2521:			       sizeof(hdw->std_info_cur));
2522:			cptr->info = &hdw->std_info_cur;
2523:			hdw->std_info_cur.def.type_bitmask.bit_names =
2524:				hdw->std_mask_ptrs;
2525:			hdw->std_info_cur.def.type_bitmask.valid_bits =
2526:				valid_std_mask;
2527:		}
2528:		cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDDETECT);
2529:		if (cptr) {
2530:			memcpy(&hdw->std_info_detect,cptr->info,
2531:			       sizeof(hdw->std_info_detect));
2532:			cptr->info = &hdw->std_info_detect;
2533:			hdw->std_info_detect.def.type_bitmask.bit_names =
2534:				hdw->std_mask_ptrs;
2535:			hdw->std_info_detect.def.type_bitmask.valid_bits =
2536:				valid_std_mask;
2537:		}
2538:	
2539:		hdw->cropcap_stale = !0;
2540:		hdw->eeprom_addr = -1;
2541:		hdw->unit_number = -1;
2542:		hdw->v4l_minor_number_video = -1;
2543:		hdw->v4l_minor_number_vbi = -1;
2544:		hdw->v4l_minor_number_radio = -1;
2545:		hdw->ctl_write_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL);
2546:		if (!hdw->ctl_write_buffer) goto fail;
2547:		hdw->ctl_read_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL);
2548:		if (!hdw->ctl_read_buffer) goto fail;
2549:		hdw->ctl_write_urb = usb_alloc_urb(0,GFP_KERNEL);
2550:		if (!hdw->ctl_write_urb) goto fail;
2551:		hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL);
2552:		if (!hdw->ctl_read_urb) goto fail;
2553:	
2554:		if (v4l2_device_register(&intf->dev, &hdw->v4l2_dev) != 0) {
2555:			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
2556:				   "Error registering with v4l core, giving up");
2557:			goto fail;
2558:		}
2559:		mutex_lock(&pvr2_unit_mtx);
2560:		do {
2561:			for (idx = 0; idx < PVR_NUM; idx++) {
2562:				if (unit_pointers[idx]) continue;
2563:				hdw->unit_number = idx;
2564:				unit_pointers[idx] = hdw;
2565:				break;
2566:			}
2567:		} while (0);
2568:		mutex_unlock(&pvr2_unit_mtx);
2569:	
2570:		INIT_WORK(&hdw->workpoll, pvr2_hdw_worker_poll);
2571:	
2572:		if (hdw->unit_number == -1)
2573:			goto fail;
2574:	
2575:		cnt1 = 0;
2576:		cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"pvrusb2");
2577:		cnt1 += cnt2;
2578:		if (hdw->unit_number >= 0) {
2579:			cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"_%c",
2580:					 ('a' + hdw->unit_number));
2581:			cnt1 += cnt2;
2582:		}
2583:		if (cnt1 >= sizeof(hdw->name)) cnt1 = sizeof(hdw->name)-1;
2584:		hdw->name[cnt1] = 0;
2585:	
2586:		pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s",
2587:			   hdw->unit_number,hdw->name);
2588:	
2589:		hdw->tuner_type = -1;
2590:		hdw->flag_ok = !0;
2591:	
2592:		hdw->usb_intf = intf;
2593:		hdw->usb_dev = usb_dev;
2594:	
2595:		usb_make_path(hdw->usb_dev, hdw->bus_info, sizeof(hdw->bus_info));
2596:	
2597:		ifnum = hdw->usb_intf->cur_altsetting->desc.bInterfaceNumber;
2598:		usb_set_interface(hdw->usb_dev,ifnum,0);
2599:	
2600:		mutex_init(&hdw->ctl_lock_mutex);
2601:		mutex_init(&hdw->big_lock_mutex);
2602:	
2603:		return hdw;
2604:	 fail:
2605:		if (hdw) {
2606:			timer_shutdown_sync(&hdw->quiescent_timer);
2607:			timer_shutdown_sync(&hdw->decoder_stabilization_timer);
2608:			timer_shutdown_sync(&hdw->encoder_run_timer);
2609:			timer_shutdown_sync(&hdw->encoder_wait_timer);
2610:			flush_work(&hdw->workpoll);
2611:			v4l2_device_unregister(&hdw->v4l2_dev);
2612:			usb_free_urb(hdw->ctl_read_urb);
2613:			usb_free_urb(hdw->ctl_write_urb);
2614:			kfree(hdw->ctl_read_buffer);
2615:			kfree(hdw->ctl_write_buffer);
2616:			kfree(hdw->controls);
2617:			kfree(hdw->mpeg_ctrl_info);
2618:			kfree(hdw);
2619:		}
2620:		return NULL;
2621:	}
 SourceFile:drivers/media/usb/pvrusb2/pvrusb2-hdw.c]

101/2 2026/07/30 12:24 llm crash-repro-finder
2m Model:
gemini-3.1-pro-preview

Tokens:
							input: 156964
							output: 1361
							thoughts: 10608
						

Thoughts:
**Reproducer Refinement for I2C Race Condition**

Okay, so here's the game plan, based on everything I've seen so far. The initial idea of exploiting `pvrusb2` is simpler, but that one is asynchronous and I'm still trying to figure it out. `au0828` looks much more promising because it's synchronous during device registration. I'm going with it for now. The device descriptor I have should work fine.

First, the key is to trigger a race condition between the device unregistration on USB disconnect and an I2C operation.  I've got a way to make it more likely.  The `au0828` driver registers the I2C adapter *before* the video device.  So if I can successfully open a `/dev/videoX` device, I know the I2C adapter has been registered.  That's my "synchronization" signal – opening a video device means the I2C part is ready.

The core steps are:

1.  **Connect the USB device:** `syz_usb_connect`.  I'm using the `au0828` descriptors. This one is synchronous, but the probe might execute in a workqueue later, but not before the devices are registered.
2.  **Open video and I2C devices concurrently:** I'll *immediately* start opening `/dev/video0` through `/dev/video3` and `/dev/i2c-0` through `/dev/i2c-3`, then `/dev/i2c-4` to `/dev/i2c-7` a few times to get more coverage. I'll open all the video and I2C devices to maximize the probability of success.
3.  **Disconnect USB:** `syz_usb_disconnect`. This should trigger unregistration and thus cause the race condition.
4.  **Execute the `I2C_SMBUS` ioctl:**  Run `ioctl(I2C_SMBUS)` on each of the I2C devices I opened.  If the disconnect happened at the right time, this should hit the vulnerability.

To improve reliability, I'm repeating the `openat` calls. It gives the kernel more time to register the I2C device before the disconnect. Also, even if an `openat` call fails, the next one may succeed if the driver managed to register the device. The multiple attempts will improve the probability of hitting the race.

The reproducer looks like this:

```
r0 = syz_usb_connect(3, 0x2b, &AUTO="\x12\x01\x00\x02\x00\x00\x00\x40\x40\x20\x00\x72\x00\x00\x01\x02\x03\x01\x09\x02\x19\x00\x01\x01\x00\x80\xfa\x09\x04\x00\x00\x01\xff\x00\x00\x00\x07\x05\x81\x02\x00\x02\x00", 0)
r1 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r2 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r3 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r4 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r5 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r6 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
r7 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r8 = openat$video1(0xffffff


102/2 2026/07/30 12:27 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0x2b, &AUTO="\x12\x01\x00\x02\x00\x00\x00\x40\x40\x20\x00\x72\x00\x00\x01\x02\x03\x01\x09\x02\x19\x00\x01\x01\x00\x80\xfa\x09\x04\x00\x00\x01\xff\x00\x00\x00\x07\x05\x81\x02\x00\x02\x00", 0)
r1 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r2 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r3 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r4 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r5 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r6 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
r7 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r8 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r9 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r10 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r11 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r12 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
r13 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r14 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r15 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r16 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r17 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r18 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r3, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r4, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r9, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r10, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r11, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r12, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r15, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r16, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r17, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r18, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

103/2 2026/07/30 12:27 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 170182
							output: 1277
							thoughts: 273
						

Thoughts:
**My Thought Process on the `&AUTO` Syntax**

Okay, it seems I've stumbled upon an invalid syntax attempt with `&AUTO="..."`. That won't fly. I'm pretty sure it needs to be `&AUTO='\x12\x01...'` (using single quotes for raw bytes) or potentially `&AUTO="1201..."` (using double quotes for a hex string). Let's double-check the documentation, always the best approach.

Ah, here it is: `string-arg = "'" escaped-string "'" | "\"" escaped-string "\"" | "\"$" escaped-string "\""`. Okay, the syntax clearly outlines the acceptable string arguments. Now, am I right in thinking that `&AUTO="01010101"` is indeed a hex string? Time to verify...

Yep, let's look at a concrete example. The documentation gives: `# Perform a write operation` `write(r0, &AUTO="01010101", 0x4)`. That seals it; double quotes *do* mean hex strings! Excellent.

Right, so I'll try the hex string approach with double quotes. I'm going to feed the code: `&AUTO="1201000200000040402000720000010203010902190001010080fa0904000001ff00000007058102000200"`.

Wait, just a sanity check: I need to verify the length of the hex string – it *should* correspond to the intended byte size. Length check... Yup, it's 43 bytes = 0x2b, which I was hoping for. Now, I'll attempt to run this code.



104/2 2026/07/30 12:27 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0x2b, &AUTO="1201000200000040402000720000010203010902190001010080fa0904000001ff00000007058102000200", 0)
r1 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r2 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r3 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r4 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r5 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r6 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
r7 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r8 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r9 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r10 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r11 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r12 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
r13 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r14 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r15 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r16 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r17 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r18 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r3, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r4, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r9, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r10, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r11, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r12, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r15, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r16, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r17, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r18, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

105/2 2026/07/30 12:27 llm crash-repro-finder-compressor
0m Model:
gemini-3.5-flash

Reply:
### 1. Approaches Tried and Results
*   **KASAN Report Analysis**: 
    *   Analyzed the slab-use-after-free read of size 8 at offset 264 (`0x108`) inside a `kmalloc-4k` object.
    *   The allocation/free stack traces in the report point to `skb->head` allocated/freed by `netdevsim` (`nsim_dev_trap_skb_build`). This is a reallocation noise/red herring; the original object was a `struct usb_device` (size ~2251 bytes, fits in `kmalloc-4k`).
    *   Mapped the offsets: `usb_device->dev` is at offset 176 (`0xb0`). The crash occurs in `i2c_adapter_depth` at `if (parent->type == &i2c_adapter_type)`. `parent` is `adapter->dev.parent` which points to `&usb_device->dev` (offset 176). `parent->type` is at offset 88 inside `struct device`, making the final offset `176 + 88 = 264` (`0x108`), perfectly matching the KASAN report.
*   **Driver Code Auditing**:
    *   Searched for USB drivers setting `adapter->dev.parent = &usb_device->dev` and deferring `i2c_del_adapter` on disconnect.
    *   `cx231xx` was ruled out because it sets `parent` to `usb_interface` (allocated in `kmalloc-2k`).
    *   `dvb_usb` and `dvb_usb_v2` were ruled out because they free their private context `d` (which embeds `i2c_adapter`) directly in `disconnect`, which would trigger a UAF on `dvb_usb_device` (`kmalloc-16k`) instead of `usb_device`.
    *   `au0828` and `pvrusb2` are highly viable candidates. Both set `adapter->dev.parent = &usb_device->dev` and defer the unregistration of the I2C adapter (via `i2c_del_adapter`) to a release callback that is only triggered when all V4L2 users (e.g., `/dev/videoX`) close their file descriptors.

### 2. Current Hypotheses
*   **Deferred Cleanup Race**:
    1.  A USB media device (e.g., `au0828` or `pvrusb2`) is connected.
    2.  User space opens `/dev/video0` (incrementing the driver's private context refcount) and `/dev/i2c-0` (incrementing the I2C adapter's refcount).
    3.  The USB device is disconnected.
    4.  The driver's `disconnect` callback runs. Because `/dev/video0` is open, the driver defers resource release (including `i2c_del_adapter`) and returns.
    5.  The USB core proceeds to delete the interface and eventually frees the `struct usb_device`.
    6.  The I2C adapter remains registered because `i2c_del_adapter` was never called. Its `dev.parent` still points to the now-freed `usb_device`.
    7.  User space calls `ioctl(fd_i2c, I2C_SMBUS, ...)` on `/dev/i2c-0`. This triggers `i2c_adapter_depth` which dereferences `adapter->dev.parent->type`, causing the UAF.

### 3. Critical Code and Configuration Values
*   **Dangling Parent Pointer Dereference**:
    ```c
    // drivers/i2c/i2c-core-base.c
    unsigned int i2c_adapter_depth(struct i2c_adapter *adapter)
    {
        unsigned int depth = 0;
        struct device *parent;

        for (parent = adapter->dev.parent; parent; parent = parent->parent)
            if (parent->type == &i2c_adapter_type) // UAF here: parent points to freed usb_device
                depth++;
        ...
    }
    ```
*   **Deferred Release in `au0828`**:
    ```c
    // drivers/media/usb/au0828/au0828-core.c
    static void au0828_usb_disconnect(struct usb_interface *interface)
    {
        ...
        if (au0828_analog_unregister(dev)) {
            return; // Returns early if V4L2 is open, deferring au0828_usb_release
        }
        au0828_usb_release(dev);
    }

    void au0828_usb_release(struct au0828_dev *dev)
    {
        ...
        au0828_i2c_unregister(dev); // Calls i2c_del_adapter
        kfree(dev);
    }
    ```
*   **USB IDs**:
    *   `au0828`: Vendor `0x2040`, Product `0x7200`
    *   `pvrusb2`: Vendor `0x2040`, Product `0x2900`

### 4. Syzkaller Program Structure (Draft)
```syzlang
# Connect au0828 USB device (High Speed, Interface 0)
r0 = syz_usb_connect(3, 0x2b, &AUTO="\x12\x01\x00\x02\x00\x00\x00\x40\x40\x20\x00\x72\x00\x00\x01\x02\x03\x01\x09\x02\x19\x00\x01\x01\x00\x80\xfa\x09\x04\x00\x00\x01\xff\x00\x00\x00\x07\x05\x81\x02\x00\x02\x00", 0)

# Open video device to hold driver context
r1 = openat(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)

# Open I2C device
r2 = openat(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)

# Disconnect USB device to trigger deferred disconnect
syz_usb_disconnect(r0)

# Trigger I2C transaction to execute i2c_adapter_depth
ioctl$I2C_SMBUS(r2, 0x720, &AUTO={0, 0, 0, 0})
```

Tokens:
							input: 171501
							output: 1616
							thoughts: 1802
						

106/2 2026/07/30 12:28 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 35773
							output: 1361
							thoughts: 768
						

Thoughts:
**Debugging USB Connection Descriptors**

Okay, wait a minute, I think I messed up that `&AUTO="1201..."` value. That doesn't seem right. Right, let me check `syz_usb_connect` again. Ah, right, it takes `conn_descs`, which is a pointer to a `vusb_connect_descriptors` struct. Okay, so it looks like it is expecting the following structure.

```c
vusb_connect_descriptors {
	qual_len	len[qual, int32]
	qual		ptr[in, usb_qualifier_descriptor]
	bos_len		len[bos, int32]
	bos		ptr[in, usb_bos_descriptor]
	strs_len	len[strs, int32]
	strs		array[vusb_connect_string_descriptor]
} [packed]
```

So, the third argument of `syz_usb_connect` is `conn_descs ptr[in, vusb_connect_descriptors]`. Therefore I should probably pass either `0` or something like `&AUTO={0, 0, 0, 0, 0, []}`. But hang on, where do I pass the actual raw descriptors?

Okay, let's look at the full signature of `syz_usb_connect`:

`syz_usb_connect(speed flags[usb_device_speed], dev_len len[dev, int32], dev ptr[in, string], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb`

Wait, the third argument is `dev ptr[in, string]`! Okay, so `&AUTO="1201..."` *is* correct for the third argument. Why did it say "wrong string arg" then?

Aha! `dev ptr[in, string]` expects a string, and `&AUTO="1201..."` is a pointer to a string. Actually, `&AUTO="1201..."` is a pointer to a *hex* string. That's probably the problem. Maybe I need to use `&AUTO='\x12\x01...'`?  Let me double-check the documentation on how strings should be handled.

Okay, the docs say `string-arg = "'" escaped-string "'" | "\"" escaped-string "\"" | "\"$" escaped-string "\""`.

Right, `&AUTO="01010101"` *is* a pointer to a string. But, again, the `syz_usb_connect` signature is:

`syz_usb_connect(speed flags[usb_device_speed], dev_len len[dev, int32], dev ptr[in, string], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb`

So `dev` is `ptr[in, string]`. If I use `&AUTO='\x12\x01...'`, that *is* a pointer to a string, and a valid one, I think.

Alright, let's try `&AUTO='\x12\x01\x00\x02\x00\x00\x00\x40\x40\x20\x00\x72\x00\x00\x01\x02\x03\x01\x09\x02\x19\x00\x01\x01\x00\x80\xfa\x09\x04\x00\x00\x01\xff\x00\x00\x00\x07\x05\x81\x02\x00\x02\x00'` (with single quotes) and see if that works.



107/2 2026/07/30 12:28 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0x2b, &AUTO='\x12\x01\x00\x02\x00\x00\x00\x40\x40\x20\x00\x72\x00\x00\x01\x02\x03\x01\x09\x02\x19\x00\x01\x01\x00\x80\xfa\x09\x04\x00\x00\x01\xff\x00\x00\x00\x07\x05\x81\x02\x00\x02\x00', 0)
r1 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r2 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r3 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r4 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r5 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r6 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
r7 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r8 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r9 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r10 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r11 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r12 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
r13 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r14 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r15 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r16 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r17 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r18 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r3, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r4, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r9, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r10, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r11, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r12, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r15, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r16, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r17, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r18, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

108/2 2026/07/30 12:28 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 38991
							output: 1277
							thoughts: 756
						

Thoughts:
**Debugging a Syzkaller String Argument**

Okay, let's see. Right, the third argument for this function is `dev ptr[in, string]`. Hmm, wait. I need to remember the syzkaller string literal syntax.  I know that `&AUTO="1201..."` is for hex strings, but I'm wondering if the parser might be expecting a struct or array instead? No, it's definitely a `string`. Okay, so if it's a `string` maybe I can skip the `&AUTO=`, but no,  `ptr[in, string]` *needs* `&AUTO=...` or `&(0x7f...)=...`.

Let me see how this function, `syz_usb_connect`, is used elsewhere to get some ideas. Wait, right, it's defined in `vusb.txt`. Let me check... Ah, here it is: `dev ptr[in, string]`, confirms what I suspected. Okay.

Maybe the string is incorrectly formatted. Let's try this: `&(0x7f0000000000)='\x12\x01\x00\x02\x00...'`. Ah, that failed with a "wrong string arg" error. Let's consult the documentation: `string-arg = "'" escaped-string "'" | "\"" escaped-string "\"" | "\"$" escaped-string "\""`.

Okay, so maybe the hex string needs to be `&AUTO="1201000200000040..."`? I tried that, it failed too. Let's try again with the documentation in mind. Wait, what if I simply try `&AUTO=""`, which does not work.  Hmm, no, I need the actual byte values.

Ah, in syzkaller, isn't it true that a hex string is denoted by `$"1201..."`? Let's verify... yes, `"\"$" escaped-string "\""` means `"$1201..."`. Okay, let's try this: `&AUTO="$1201000200000040402000720000010203010902190001010080fa0904000001ff00000007058102000200"`.



109/2 2026/07/30 12:29 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0x2b, &AUTO="$1201000200000040402000720000010203010902190001010080fa0904000001ff00000007058102000200", 0)
r1 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r2 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r3 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r4 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r5 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r6 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
r7 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r8 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r9 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r10 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r11 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r12 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
r13 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r14 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r15 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r16 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r17 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r18 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r3, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r4, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r9, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r10, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r11, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r12, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r15, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r16, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r17, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r18, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

110/2 2026/07/30 12:29 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 41709
							output: 19
							thoughts: 514
						

Thoughts:
**Debugging a Syzkaller USB Fuzzing Scenario**

Okay, so I'm trying to craft a specific USB connection setup using Syzkaller. My initial thought was, "Can I just use `&AUTO=""` and then manually set the bytes with `syz_usb_connect`?" Seems like a good way to be explicit. But then I remembered, wait, isn't the string syntax for `&AUTO` something like `"01010101"`? And isn't that a *string*? Right, the documentation shows that `&AUTO` is used with `write`, like `write(r0, &AUTO="01010101", 0x4)`. That's not quite what I'm after here.

So, if I want to pass actual hex bytes, I should be using `&AUTO='\x12\x01...'`. That makes sense. But, I just got a "wrong string arg" error. Let me check the error message again... Ah, there it is!

`line #1:36: r0 = syz_usb_connect(3, 0x2b, &AUTO=<<<!!ERROR!!>>>'\x12\x01\x00\x02\x00\x00\x00\x40\x40\x20\x00\x72\x00\x00\x01\x02\x03\x01\x09\x02\x19\x00\x01\x01\x00\x80\xfa\x09\x04\x00\x00\x01\xff\x00\x00\x00\x07\x05\x81\x02\x00\x02\x00', 0)`

Right. The error is still "wrong string arg" but let's carefully consider the structure. The issue is with the third argument to `syz_usb_connect`, which is a `dev ptr[in, string]`. I need to figure out how Syzkaller expects to handle that.

Aha! `dev` is a pointer to a string. So, maybe I don't need `&AUTO=` at all? But I am fairly certain that pointer arguments to Syzkaller need to start with `&` or be `AUTO` or `0`. Shoot, what if I could pass an array? Like `&AUTO={'12', '01', ...}`? No, I'm pretty sure that would also trigger a similar error.

Okay, time to consult `vusb.txt` and see exactly how the `dev` parameter is defined. Hopefully, there is more clarity there to understand the correct syntax.



111/2 2026/07/30 12:29 tool read-description
0m Args:
map[File:vusb.txt]

Results:
map[Output:# Copyright 2019 syzkaller project authors. All rights reserved.
# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

include <linux/types.h>
include <linux/byteorder/generic.h>

include <uapi/linux/usb/ch9.h>
include <uapi/linux/usb/ch11.h>

include <uapi/linux/usb/midi.h>
include <uapi/linux/usb/audio.h>
include <linux/usb/audio-v2.h>
include <linux/usb/audio-v3.h>
include <uapi/linux/hid.h>
include <linux/hid.h>
include <uapi/linux/usb/cdc.h>
include <uapi/linux/if_ether.h>
include <linux/interrupt.h>
include <linux/usb/cdc_ncm.h>
include <drivers/net/usb/asix.h>

# This is a special fd for USB fuzzing and should only be used with syz_usb_* pseudo-syscalls.
# We don't inherit it from the fd resource, to discourage syzkaller calling raw ioctls on it.
resource fd_usb[int32]: -1

# These are generic pseudo-syscalls for emulating arbitrary USB devices.
# They are mostly targeted to cover the enumeration process.
syz_usb_connect(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io(fd fd_usb, descs ptr[in, vusb_descriptors], resps ptr[in, vusb_responses]) (timeout[300], remote_cover)
syz_usb_ep_write(fd fd_usb, ep int8, len len[data], data ptr[in, array[int8, 0:256]]) (timeout[300], remote_cover)
syz_usb_ep_read(fd fd_usb, ep int8, len len[data], data buffer[out]) (timeout[300], remote_cover)
syz_usb_disconnect(fd fd_usb) (timeout[300], remote_cover)

usb_device_speed = USB_SPEED_UNKNOWN, USB_SPEED_LOW, USB_SPEED_FULL, USB_SPEED_HIGH, USB_SPEED_WIRELESS, USB_SPEED_SUPER, USB_SPEED_SUPER_PLUS

# TODO: consider patching idVendor and idProduct for all class specific descriptions in Go code to cover more drivers.
# TODO: custom syz_usb_ep_write() descriptions for all class specific descriptions.
# TODO: consider adding custom vusb_connect_descriptors definitions to all class specific descriptions.

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

type usb_device_descriptor_verbose_t[USB, CLASS, SUBCLASS, PROTOCOL, PACKET, VENDOR, PRODUCT, DEVICE, CFS] {
	bLength			const[USB_DT_DEVICE_SIZE, int8]
	bDescriptorType		const[USB_DT_DEVICE, int8]

	bcdUSB			USB
	bDeviceClass		const[CLASS, int8]
	bDeviceSubClass		const[SUBCLASS, int8]
	bDeviceProtocol		const[PROTOCOL, int8]
	bMaxPacketSize0		PACKET
	idVendor		const[VENDOR, int16]
	idProduct		const[PRODUCT, int16]
	bcdDevice		const[DEVICE, int16]
	iManufacturer		const[1, int8]
	iProduct		const[2, int8]
	iSerialNumber		const[3, int8]
	bNumConfigurations	len[configs, int8]

	configs			CFS
} [packed]

type usb_device_descriptor_t[CLASS, SUBCLASS, PROTOCOL, VENDOR, PRODUCT, DEVICE, CFS] usb_device_descriptor_verbose_t[flags[usb_versions, int16], CLASS, SUBCLASS, PROTOCOL, flags[usb_device_max_packet_sizes, int8], VENDOR, PRODUCT, DEVICE, CFS]
type usb_device_descriptor_fixed_t[USB, CLASS, SUBCLASS, PROTOCOL, PACKET, VENDOR, PRODUCT, DEVICE, CFS] usb_device_descriptor_verbose_t[const[USB, int16], CLASS, SUBCLASS, PROTOCOL, const[PACKET, int8], VENDOR, PRODUCT, DEVICE, CFS]

usb_versions = 0x110, 0x200, 0x201, 0x250, 0x300, 0x310

# https://elixir.bootlin.com/linux/v5.1.7/source/drivers/usb/core/hub.c#L4661
usb_device_max_packet_sizes = 8, 16, 32, 64, 255

type usb_config_descriptor_verbose_t[NUM, IFSNUM, ICONFIG, ATTRS, POWER, EXTRA, IFS] {
	bLength			const[USB_DT_CONFIG_SIZE, int8]
	bDescriptorType		const[USB_DT_CONFIG, int8]

	wTotalLength		len[parent, int16]
	bNumInterfaces		IFSNUM
	bConfigurationValue	NUM
	iConfiguration		ICONFIG
	bmAttributes		ATTRS
	bMaxPower		POWER

	extra			EXTRA
	interfaces		IFS
} [packed]

type usb_config_descriptor_t[NUM, IFSNUM, IFS] usb_config_descriptor_verbose_t[NUM, IFSNUM, int8, flags[usb_config_attributes, int8], int8, void, IFS]
type usb_config_descriptor_ifaces_array_t[NUM, IFS] usb_config_descriptor_t[NUM, len[interfaces, int8], IFS]
type usb_config_descriptor_fixed_t[NUM, IFSNUM, ATTRS, POWER, IFS] usb_config_descriptor_verbose_t[const[NUM, int8], const[IFSNUM, int8], const[0, int8], const[ATTRS, int8], const[POWER, int8], void, IFS]
type usb_config_descriptor_extra_t[NUM, IFSNUM, EXTRA, IFS] usb_config_descriptor_verbose_t[NUM, IFSNUM, int8, flags[usb_config_attributes, int8], int8, EXTRA, IFS]

type usb_interface_descriptor_verbose_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, IIF, EXTRA, EPS] {
	bLength			const[USB_DT_INTERFACE_SIZE, int8]
	bDescriptorType		const[USB_DT_INTERFACE, int8]

	bInterfaceNumber	IFNUM
	bAlternateSetting	ALTNUM
	bNumEndpoints		EPSNUM
	bInterfaceClass		CLASS
	bInterfaceSubClass	SUBCLASS
	bInterfaceProtocol	PROTOCOL
	iInterface		IIF

	extra			EXTRA
	endpoints		EPS
} [packed]

type usb_interface_descriptor_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS] usb_interface_descriptor_verbose_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, int8, EXTRA, EPS]
type usb_interface_descriptor_eps_array_t[IFNUM, ALTNUM, CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS] usb_interface_descriptor_t[IFNUM, ALTNUM, len[endpoints, int8], CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS]
type usb_interface_descriptor_fixed_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS] usb_interface_descriptor_verbose_t[const[IFNUM, int8], const[ALTNUM, int8], const[EPSNUM, int8], const[CLASS, int8], const[SUBCLASS, int8], const[PROTOCOL, int8], const[0, int8], EXTRA, EPS]

# TODO: non-audio endpoints have USB_DT_ENDPOINT_SIZE.
type usb_endpoint_descriptor_verbose_t[ADDR, ATTRS, PACKET, INTERVAL, REFRESH, SYNCH, EXTRA] {
	bLength			const[USB_DT_ENDPOINT_AUDIO_SIZE, int8]
	bDescriptorType		const[USB_DT_ENDPOINT, int8]

	bEndpointAddress	ADDR
	bmAttributes		ATTRS
	wMaxPacketSize		PACKET
	bInterval		INTERVAL

	bRefresh		REFRESH
	bSynchAddress		SYNCH

	extra			EXTRA
} [packed]

type usb_endpoint_descriptor_t[ADDR, ATTRS, EXTRA] usb_endpoint_descriptor_verbose_t[ADDR, ATTRS, flags[usb_endpoint_max_packet_sizes, int16], int8, int8, int8, EXTRA]
type usb_endpoint_descriptor_fixed_t[ADDR, ATTRS, PACKET, INTERVAL, EXTRA] usb_endpoint_descriptor_verbose_t[const[ADDR, int8], const[ATTRS, int8], const[PACKET, int16], const[INTERVAL, int8], const[0, int8], const[0, int8], EXTRA]

# TODO: dummy driver has complex requirements for packet sizes, account for those:
# https://elixir.bootlin.com/linux/v5.3.6/source/drivers/usb/gadget/udc/dummy_hcd.c#L497
usb_endpoint_max_packet_sizes = 8, 16, 32, 64, 512, 1023, 1024

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Generic USB device, configuration, interface and endpoint descriptors.

# We only support one configuration per device.
# bDeviceClass, bDeviceSubClass, bDeviceProtocol, idVendor, idProduct
# and bcdDevice are patched by Go code, see sys/linux/init_vusb.go.
usb_device_descriptor {
	inner	usb_device_descriptor_t[0, 0, 0, 0, 0, 0, array[usb_config_descriptor, 1]]
} [packed]

usb_config_descriptor {
	inner	usb_config_descriptor_ifaces_array_t[int8, array[usb_interface_descriptor, 1:4]]
} [packed]

usb_config_attributes = USB_CONFIG_ATT_ONE, USB_CONFIG_ATT_SELFPOWER, USB_CONFIG_ATT_WAKEUP, USB_CONFIG_ATT_BATTERY

# bInterfaceNumber, bInterfaceClass, bInterfaceSubClass and bInterfaceProtocol
# are patched by Go code, see sys/linux/init_vusb.go.
usb_interface_descriptor {
	inner	usb_interface_descriptor_eps_array_t[int8, int8, const[0, int8], const[0, int8], const[0, int8], array[usb_interface_extra_descriptor, 0:2], array[usb_endpoint_descriptor, 0:16]]
} [packed]

usb_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], flags[usb_endpoint_attributes, int8], array[usb_endpoint_extra_descriptor, 0:2]]
} [packed]

usb_endpoint_addresses = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, USB_DIR_OUT, USB_DIR_IN

usb_endpoint_attributes = USB_ENDPOINT_XFER_CONTROL, USB_ENDPOINT_XFER_ISOC, USB_ENDPOINT_XFER_BULK, USB_ENDPOINT_XFER_INT, USB_ENDPOINT_INTR_PERIODIC, USB_ENDPOINT_INTR_NOTIFICATION, USB_ENDPOINT_SYNC_NONE, USB_ENDPOINT_SYNC_ASYNC, USB_ENDPOINT_SYNC_ADAPTIVE, USB_ENDPOINT_SYNC_SYNC, USB_ENDPOINT_USAGE_DATA, USB_ENDPOINT_USAGE_FEEDBACK, USB_ENDPOINT_USAGE_FEEDBACK

vusb_connect_descriptors {
	qual_len	len[qual, int32]
	qual		ptr[in, usb_qualifier_descriptor]
	bos_len		len[bos, int32]
	bos		ptr[in, usb_bos_descriptor]
	strs_len	len[strs, int32]
	strs		array[vusb_connect_string_descriptor]
} [packed]

vusb_connect_string_descriptor {
	len	len[str, int32]
	str	ptr[in, usb_string_descriptor]
} [packed]

vusb_descriptors {
	len	len[parent, int32]
	generic	ptr[in, vusb_descriptor_generic]

	string	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
	bos	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_BOS, usb_bos_descriptor]]

	hub_hs	ptr[in, vusb_descriptor_t[USB_TYPE_CLASS, USB_DT_HUB, usb_hub_descriptor_hs]]
	hub_ss	ptr[in, vusb_descriptor_t[USB_TYPE_CLASS, USB_DT_SS_HUB, usb_hub_descriptor_ss]]
} [packed]

vusb_descriptor_generic {
	req_type	flags[usb_request_types, int8]
	desc_type	flags[usb_descriptor_types, int8]
	len		bytesize[data, int32]
	data		usb_generic_descriptor
} [packed]

usb_request_types = USB_TYPE_STANDARD, USB_TYPE_CLASS, USB_TYPE_VENDOR

type vusb_descriptor_t[CLASS, REQ, DATA] {
	type	const[CLASS, int8]
	req	const[REQ, int8]
	len	bytesize[data, int32]
	data	DATA
} [packed]

# TODO: consider doing lookups based on USB_RECIP values.
vusb_responses {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	get_interface			ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	get_configuration		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

# TODO: move these into custom descriptions for hub class when they are added.
	hub_USB_REQ_GET_STATUS_hub	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_REQ_GET_STATUS, usb_hub_status]]
	hub_USB_REQ_GET_STATUS_port	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_REQ_GET_STATUS, usb_port_status]]

# TODO: move these into custom descriptions for asix driver when they are added.
	asix_AX_CMD_READ_MII_REG	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_MII_REG, int16]]
	asix_AX_CMD_STATMNGSTS_REG	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_STATMNGSTS_REG, int8]]
	asix_AX_CMD_READ_EEPROM		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_EEPROM, array[int8, 2]]]
	asix_AX_CMD_READ_RX_CTL		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_RX_CTL, int16]]
	asix_AX_CMD_READ_NODE_ID	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_NODE_ID, mac_addr]]
	asix_AX88172_CMD_READ_NODE_ID	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX88172_CMD_READ_NODE_ID, mac_addr]]
	asix_AX_CMD_READ_PHY_ID		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_PHY_ID, array[int8, 2]]]
	asix_AX_CMD_READ_MEDIUM_STATUS	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_MEDIUM_STATUS, int16]]
	asix_AX_CMD_READ_MONITOR_MODE	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_MONITOR_MODE, int8]]
	asix_AX_CMD_READ_GPIOS		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_GPIOS, int8]]
	asix_AX_CMD_SW_PHY_STATUS	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_SW_PHY_STATUS, int8]]
} [packed]

vusb_response_generic {
	type	flags[usb_request_types, int8]
	req	flags[usb_requests, int8]
	len	bytesize[data, int32]
	data	array[int8, 0:256]
} [packed]

usb_requests = USB_REQ_GET_STATUS, USB_REQ_CLEAR_FEATURE, USB_REQ_SET_FEATURE, USB_REQ_SET_ADDRESS, USB_REQ_GET_DESCRIPTOR, USB_REQ_SET_DESCRIPTOR, USB_REQ_GET_CONFIGURATION, USB_REQ_SET_CONFIGURATION, USB_REQ_GET_INTERFACE, USB_REQ_SET_INTERFACE, USB_REQ_SYNCH_FRAME, USB_REQ_SET_SEL, USB_REQ_SET_ISOCH_DELAY, USB_REQ_SET_ENCRYPTION, USB_REQ_GET_ENCRYPTION, USB_REQ_RPIPE_ABORT, USB_REQ_SET_HANDSHAKE, USB_REQ_RPIPE_RESET, USB_REQ_GET_HANDSHAKE, USB_REQ_SET_CONNECTION, USB_REQ_SET_SECURITY_DATA, USB_REQ_GET_SECURITY_DATA, USB_REQ_SET_WUSB_DATA, USB_REQ_LOOPBACK_DATA_WRITE, USB_REQ_LOOPBACK_DATA_READ, USB_REQ_SET_INTERFACE_DS, USB_REQ_GET_PARTNER_PDO, USB_REQ_GET_BATTERY_STATUS, USB_REQ_SET_PDO, USB_REQ_GET_VDM, USB_REQ_SEND_VDM

type vusb_response_t[CLASS, REQ, DATA] {
	type	const[CLASS, int8]
	req	const[REQ, int8]
	len	bytesize[data, int32]
	data	DATA
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# USB descriptors requested by the kernel before the SET_CONFIGURATION request.

# TODO: figure out when is the USB_DT_OTG descriptor used.
# TODO: figure out when is the USB_DT_INTERFACE_ASSOCIATION descriptor used.
# TODO: figure out when is the USB_DT_BOS descriptor used.

type usb_string_descriptor_t[DATA] {
	bLength		len[parent, int8]
	bDescriptorType	const[USB_DT_STRING, int8]

	data		DATA
} [packed]

usb_string_descriptor [
	lang_id	usb_string_descriptor_t[flags[usb_lang_ids, int16]]
	string	usb_string_descriptor_t[array[int8, 0:256]]
] [varlen]

usb_lang_ids = 0x436, 0x41c, 0x401, 0x801, 0xc01, 0x1001, 0x1401, 0x1801, 0x1c01, 0x2001, 0x2401, 0x2801, 0x2c01, 0x3001, 0x3401, 0x3801, 0x3c01, 0x4001, 0x42b, 0x44d, 0x42c, 0x82c, 0x42d, 0x423, 0x445, 0x402, 0x455, 0x403, 0x404, 0x804, 0xc04, 0x1004, 0x1404, 0x41a, 0x405, 0x406, 0x413, 0x813, 0x409, 0x809, 0xc09, 0x1009, 0x1409, 0x1809, 0x1c09, 0x2009, 0x2409, 0x2809, 0x2c09, 0x3009, 0x3409, 0x425, 0x438, 0x429, 0x40b, 0x40c, 0x80c, 0xc0c, 0x100c, 0x140c, 0x180c, 0x437, 0x407, 0x807, 0xc07, 0x1007, 0x1407, 0x408, 0x447, 0x40d, 0x439, 0x40e, 0x40f, 0x421, 0x410, 0x810, 0x411, 0x44b, 0x860, 0x43f, 0x457, 0x412, 0x812, 0x426, 0x427, 0x827, 0x42f, 0x43e, 0x83e, 0x44c, 0x458, 0x44e, 0x861, 0x414, 0x814, 0x448, 0x415, 0x416, 0x816, 0x446, 0x418, 0x419, 0x44f, 0xc1a, 0x81a, 0x459, 0x41b, 0x424, 0x40a, 0x80a, 0xc0a, 0x100a, 0x140a, 0x180a, 0x1c0a, 0x200a, 0x240a, 0x280a, 0x2c0a, 0x300a, 0x340a, 0x380a, 0x3c0a, 0x400a, 0x440a, 0x480a, 0x4c0a, 0x500a, 0x430, 0x441, 0x41d, 0x81d, 0x449, 0x444, 0x44a, 0x41e, 0x41f, 0x422, 0x420, 0x820, 0x443, 0x843, 0x42a, 0x4ff, 0xf0ff, 0xf4ff, 0xf8ff, 0xfcff

usb_qualifier_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_QUALIFIER, int8]

	bcdUSB			flags[usb_versions, int16]
	bDeviceClass		int8
	bDeviceSubClass		int8
	bDeviceProtocol		int8
	bMaxPacketSize0		flags[usb_device_max_packet_sizes, int8]
	bNumConfigurations	int8
	bRESERVED		const[0, int8]
} [packed]

usb_bos_descriptor {
	bLength		const[USB_DT_BOS_SIZE, int8]
	bDescriptorType	const[USB_DT_BOS, int8]

	wTotalLength	len[parent, int16]
	bNumDeviceCaps	len[caps, int8]

	caps		array[usb_dev_cap, 0:6]
} [packed]

usb_dev_cap [
	generic		usb_generic_cap_descriptor
	wireless	usb_wireless_cap_descriptor
	ext_cap		usb_ext_cap_descriptor
	ss_cap		usb_ss_cap_descriptor
	ss_container_id	usb_ss_container_id_descriptor
	ssp_cap		usb_ssp_cap_descriptor
	ptm_cap		usb_ptm_cap_descriptor
] [varlen]

usb_generic_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	flags[usb_capability_types, int8]

	data			array[int8, 0:256]
} [packed]

usb_capability_types = USB_CAP_TYPE_WIRELESS_USB, USB_CAP_TYPE_EXT, USB_SS_CAP_TYPE, USB_SSP_CAP_TYPE, CONTAINER_ID_TYPE, USB_PTM_CAP_TYPE

usb_wireless_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_CAP_TYPE_WIRELESS_USB, int8]

	bmAttributes		flags[usb_wireless_cap_attributes, int8]
	wPHYRates		flags[usb_wireless_cap_phyrates, int16]
	bmTFITXPowerInfo	int8
	bmFFITXPowerInfo	int8
	bmBandGroup		int16
	bReserved		int8
} [packed]

usb_wireless_cap_attributes = USB_WIRELESS_P2P_DRD, USB_WIRELESS_BEACON_MASK, USB_WIRELESS_BEACON_SELF, USB_WIRELESS_BEACON_DIRECTED, USB_WIRELESS_BEACON_NONE

usb_wireless_cap_phyrates = USB_WIRELESS_PHY_53, USB_WIRELESS_PHY_80, USB_WIRELESS_PHY_107, USB_WIRELESS_PHY_160, USB_WIRELESS_PHY_200, USB_WIRELESS_PHY_320, USB_WIRELESS_PHY_400, USB_WIRELESS_PHY_480

usb_ext_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_CAP_TYPE_EXT, int8]

	bmAttributes1		flags[usb_ext_cap_attributes, int32:8]
	bmAttributes2		int32:4
	bmAttributes3		int32:4
	bmAttributes4		int32:16
} [packed]

usb_ext_cap_attributes = USB_LPM_SUPPORT, USB_BESL_SUPPORT, USB_BESL_BASELINE_VALID, USB_BESL_DEEP_VALID

usb_ss_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_SS_CAP_TYPE, int8]

	bmAttributes		flags[usb_ss_cap_attributes, int8]
	wSpeedSupported		flags[usb_ss_cap_speed, int16]
	bFunctionalitySupport	int8
	bU1devExitLat		int8
	bU2DevExitLat		int16
} [packed]

usb_ss_cap_attributes = USB_LTM_SUPPORT

usb_ss_cap_speed = USB_LOW_SPEED_OPERATION, USB_FULL_SPEED_OPERATION, USB_HIGH_SPEED_OPERATION, USB_5GBPS_OPERATION

usb_ss_container_id_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[CONTAINER_ID_TYPE, int8]

	bReserved		int8
	ContainerID		array[int8, 16]
} [packed]

usb_ssp_cap_descriptor {
	bLength				len[parent, int8]
	bDescriptorType			const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType		const[USB_SSP_CAP_TYPE, int8]

	bReserved			int8
	bmAttributesSublinkSpeeds	len[bmSublinkSpeedAttr, int32:5]
	bmAttributesSpeedIDs		int32:27
	wFunctionalitySupport		flags[usb_ssp_cap_funcs, int16]
	wReserved			int16
	bmSublinkSpeedAttr		array[flags[usb_ssp_cap_sublink_speeds, int32], 0:6]
} [packed]

usb_ssp_cap_funcs = USB_SSP_MIN_SUBLINK_SPEED_ATTRIBUTE_ID, USB_SSP_MIN_RX_LANE_COUNT, USB_SSP_MIN_TX_LANE_COUNT

usb_ssp_cap_sublink_speeds = USB_SSP_SUBLINK_SPEED_SSID, USB_SSP_SUBLINK_SPEED_LSE, USB_SSP_SUBLINK_SPEED_ST, USB_SSP_SUBLINK_SPEED_RSVD, USB_SSP_SUBLINK_SPEED_LP, USB_SSP_SUBLINK_SPEED_LSM

usb_ptm_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_PTM_CAP_TYPE, int8]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Extra USB descriptors that come after an interface or an endpoint descriptor.

# TODO: consider removing class specific descriptors here for described classes.
usb_interface_extra_descriptor [
	generic		usb_generic_descriptor
	hid_hid		usb_hid_descriptor_hid
	cdc_ecm		usb_cdc_header_ecm
	cdc_ncm		usb_cdc_header_ncm
	uac_control	uac_control_iface_extra_descriptors
	uac_as		uac_as_iface_extra_descriptors
] [varlen]

usb_endpoint_extra_descriptor [
	generic	usb_generic_descriptor
	uac_iso	uac_iso_endpoint_descriptor
] [varlen]

usb_generic_descriptor {
	bLength		len[parent, int8]
	bDescriptorType	flags[usb_descriptor_types, int8]

	data		array[int8, 0:256]
} [packed]

usb_descriptor_types = USB_DT_DEVICE, USB_DT_CONFIG, USB_DT_STRING, USB_DT_INTERFACE, USB_DT_ENDPOINT, USB_DT_DEVICE_QUALIFIER, USB_DT_OTHER_SPEED_CONFIG, USB_DT_INTERFACE_POWER, USB_DT_OTG, USB_DT_DEBUG, USB_DT_INTERFACE_ASSOCIATION, USB_DT_SECURITY, USB_DT_KEY, USB_DT_ENCRYPTION_TYPE, USB_DT_BOS, USB_DT_DEVICE_CAPABILITY, USB_DT_WIRELESS_ENDPOINT_COMP, USB_DT_WIRE_ADAPTER, USB_DT_RPIPE, USB_DT_CS_RADIO_CONTROL, USB_DT_PIPE_USAGE, USB_DT_SS_ENDPOINT_COMP, USB_DT_SSP_ISOC_ENDPOINT_COMP, HID_DT_HID, HID_DT_REPORT, HID_DT_PHYSICAL

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# USB descriptors requested after the SET_CONFIGURATION request.

usb_hub_descriptor_hs {
	bDescLength		len[parent, int8]
	bDescriptorType		const[USB_DT_HUB, int8]

	bNbrPorts		int8
	wHubCharacteristics	flags[usb_hub_characteristics, int16]
	bPwrOn2PwrGood		int8
	bHubContrCurrent	int8

	DeviceRemovable		array[int8, USB_HUB_PORTS_BITS]
	PortPwrCtrlMask		array[int8, USB_HUB_PORTS_BITS]
} [packed]

usb_hub_descriptor_ss {
	bDescLength		len[parent, int8]
	bDescriptorType		const[USB_DT_SS_HUB, int8]

	bNbrPorts		int8
	wHubCharacteristics	flags[usb_hub_characteristics, int16]
	bPwrOn2PwrGood		int8
	bHubContrCurrent	int8

	bHubHdrDecLat		int8
	wHubDelay		int16
	DeviceRemovable		int16
} [packed]

define USB_HUB_PORTS_BITS	((USB_MAXCHILDREN + 1 + 7) / 8)

usb_hub_characteristics = HUB_CHAR_LPSM, HUB_CHAR_COMMON_LPSM, HUB_CHAR_INDV_PORT_LPSM, HUB_CHAR_NO_LPSM, HUB_CHAR_COMPOUND, HUB_CHAR_OCPM, HUB_CHAR_COMMON_OCPM, HUB_CHAR_INDV_PORT_OCPM, HUB_CHAR_NO_OCPM, HUB_CHAR_TTTT, HUB_CHAR_PORTIND

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Replies to USB control requests requested after the SET_CONFIGURATION request.

usb_port_status {
	wPortStatus	flags[usb_port_status_flags, int16]
	wPortChange	flags[usb_port_change_flags, int16]
	dwExtPortStatus	array[flags[usb_ext_port_status_flags, int32], 0:1]
} [packed]

usb_port_status_flags = USB_PORT_STAT_CONNECTION, USB_PORT_STAT_ENABLE, USB_PORT_STAT_SUSPEND, USB_PORT_STAT_OVERCURRENT, USB_PORT_STAT_RESET, USB_PORT_STAT_L1, USB_PORT_STAT_POWER, USB_PORT_STAT_LOW_SPEED, USB_PORT_STAT_HIGH_SPEED, USB_PORT_STAT_TEST, USB_PORT_STAT_INDICATOR, USB_PORT_STAT_LINK_STATE, USB_SS_PORT_STAT_POWER, USB_SS_PORT_STAT_SPEED, USB_PORT_STAT_SPEED_5GBPS, USB_SS_PORT_LS_U0, USB_SS_PORT_LS_U1, USB_SS_PORT_LS_U2, USB_SS_PORT_LS_U3, USB_SS_PORT_LS_SS_DISABLED, USB_SS_PORT_LS_RX_DETECT, USB_SS_PORT_LS_SS_INACTIVE, USB_SS_PORT_LS_POLLING, USB_SS_PORT_LS_RECOVERY, USB_SS_PORT_LS_HOT_RESET, USB_SS_PORT_LS_COMP_MOD, USB_SS_PORT_LS_LOOPBACK

usb_port_change_flags = USB_PORT_STAT_C_CONNECTION, USB_PORT_STAT_C_ENABLE, USB_PORT_STAT_C_SUSPEND, USB_PORT_STAT_C_OVERCURRENT, USB_PORT_STAT_C_RESET, USB_PORT_STAT_C_L1, USB_PORT_STAT_C_BH_RESET, USB_PORT_STAT_C_LINK_STATE, USB_PORT_STAT_C_CONFIG_ERROR

usb_ext_port_status_flags = USB_EXT_PORT_STAT_RX_SPEED_ID, USB_EXT_PORT_STAT_TX_SPEED_ID, USB_EXT_PORT_STAT_RX_LANES, USB_EXT_PORT_STAT_TX_LANES

usb_hub_status {
	wHubStatus	flags[usb_hub_status_flags, int16]
	wHubChange	flags[usb_hub_change_flags, int16]
} [packed]

usb_hub_status_flags = HUB_STATUS_LOCAL_POWER, HUB_STATUS_OVERCURRENT

usb_hub_change_flags = HUB_CHANGE_LOCAL_POWER, HUB_CHANGE_OVERCURRENT

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# HID device class specific descriptions.
# https://www.usb.org/sites/default/files/documents/hid1_11.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/hid/usbhid/hid-core.c
# https://elixir.bootlin.com/linux/latest/source/drivers/hid/hid-core.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/hid.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_hid.c

# Connected HID devices are known to create the following /dev/ files:
# /dev/hidraw#, /dev/usb/hiddev# and /dev/input/event#.

resource fd_usb_hid[fd_usb]

syz_usb_connect$hid(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_hid], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_hid (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$hid(fd fd_usb_hid, descs ptr[in, vusb_descriptors_hid], resps ptr[in, vusb_responses_hid]) (timeout[300], remote_cover)

# idVendor and idProduct are patched by Go code, see sys/linux/init_vusb.go.
usb_device_descriptor_hid {
	inner	usb_device_descriptor_t[0, 0, 0, 0, 0, 64, array[usb_config_descriptor_hid, 1]]
} [packed]

usb_config_descriptor_hid {
	inner	usb_config_descriptor_ifaces_array_t[const[1, int8], array[usb_interface_descriptor_hid, 1]]
} [packed]

usb_interface_descriptor_hid {
	inner	usb_interface_descriptor_t[const[0, int8], int8, int8[1:2], const[USB_CLASS_HID, int8], const[USB_INTERFACE_SUBCLASS_BOOT, int8], flags[usb_hid_protocols, int8], usb_hid_descriptor_hid, usb_endpoint_descriptors_hid]
} [packed]

usb_hid_protocols = USB_INTERFACE_PROTOCOL_KEYBOARD, USB_INTERFACE_PROTOCOL_MOUSE

usb_endpoint_descriptors_hid {
	in	usb_endpoint_descriptor_hid_in
	out	array[usb_endpoint_descriptor_hid_out, 0:1]
} [packed]

usb_endpoint_descriptor_hid_in {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_HID_IN_ADDRESS, int8], const[USB_ENDPOINT_HID_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_hid_out {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_HID_OUT_ADDRESS, int8], const[USB_ENDPOINT_HID_ATTRIBUTES, int8], void]
} [packed]

define USB_ENDPOINT_HID_ATTRIBUTES	(USB_ENDPOINT_XFER_INT)
define USB_ENDPOINT_HID_IN_ADDRESS	(1 | USB_DIR_IN)
define USB_ENDPOINT_HID_OUT_ADDRESS	(2)

vusb_descriptors_hid {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]

# For unknown reasons these are requested as USB_TYPE_STANDARD and not as USB_TYPE_CLASS.
# Linux doesn't request HID_DT_HID, but some hosts might do that.
	HID_DT_REPORT	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, HID_DT_REPORT, hid_descriptor_report]]
	HID_DT_HID	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, HID_DT_HID, usb_hid_descriptor_hid]]
} [packed]

vusb_responses_hid {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	HID_REQ_GET_REPORT		ptr[in, vusb_response_t[USB_TYPE_CLASS, HID_REQ_GET_REPORT, array[int8, 0:256]]]
	HID_REQ_GET_PROTOCOL		ptr[in, vusb_response_t[USB_TYPE_CLASS, HID_REQ_GET_PROTOCOL, int8]]
} [packed]

# USB HID specifications allows for multiple report and physical descriptors
# to be present, but I don't see any support for them in the Linux kernel,
# except for a single report descriptor.
usb_hid_descriptor_hid {
	bLength		len[parent, int8]
	bDescriptorType	const[HID_DT_HID, int8]

	bcdHID		int16
	bCountryCode	int8
	bNumDescriptors	const[1, int8]

	report_desc	usb_hid_class_descriptor_report
} [packed]

usb_hid_class_descriptor_report {
	bDescriptorType		const[HID_DT_REPORT, int8]
	wDescriptorLength	int16[0:HID_MAX_DESCRIPTOR_SIZE]
} [packed]

# TODO: it's hard to describe the REPORT descriptor structure via syzkaller
# descriptions, so consider generating it in Go code.
# TODO: the length of REPORT descriptor must match the value in HID descriptor.
# TODO: there are vendor specific REPORT descriptor formats (Logitech HID++).

# Linux HID stack doesn't support long items.
hid_descriptor_report {
	items	array[hid_report_item_short]
} [packed]

type hid_report_item_short_012_t[TYPE, TAGS] {
	bSize	len[data, int8:2]
	bType	const[TYPE, int8:2]
	bTag	flags[TAGS, int8:4]
	data	array[int8, 0:2]
} [packed]

type hid_report_item_short_4_t[TYPE, TAGS] {
	bSize	const[3, int8:2]
	bType	const[TYPE, int8:2]
	bTag	flags[TAGS, int8:4]
	data	array[int8, 4]
} [packed]

type hid_report_item_short_t[TYPE, TAGS] [
	item_012	hid_report_item_short_012_t[TYPE, TAGS]
	item_4		hid_report_item_short_4_t[TYPE, TAGS]
] [varlen]

hid_report_item_short [
	main	hid_report_item_short_t[HID_ITEM_TYPE_MAIN, hid_report_item_main_tags]
	global	hid_report_item_short_t[HID_ITEM_TYPE_GLOBAL, hid_report_item_global_tags]
	local	hid_report_item_short_t[HID_ITEM_TYPE_LOCAL, hid_report_item_local_tags]
] [varlen]

hid_report_item_main_tags = HID_MAIN_ITEM_TAG_INPUT, HID_MAIN_ITEM_TAG_OUTPUT, HID_MAIN_ITEM_TAG_FEATURE, HID_MAIN_ITEM_TAG_BEGIN_COLLECTION, HID_MAIN_ITEM_TAG_END_COLLECTION
hid_report_item_global_tags = HID_GLOBAL_ITEM_TAG_USAGE_PAGE, HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM, HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM, HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM, HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM, HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT, HID_GLOBAL_ITEM_TAG_UNIT, HID_GLOBAL_ITEM_TAG_REPORT_SIZE, HID_GLOBAL_ITEM_TAG_REPORT_ID, HID_GLOBAL_ITEM_TAG_REPORT_COUNT, HID_GLOBAL_ITEM_TAG_PUSH, HID_GLOBAL_ITEM_TAG_POP
hid_report_item_local_tags = HID_LOCAL_ITEM_TAG_USAGE, HID_LOCAL_ITEM_TAG_USAGE_MINIMUM, HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM, HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX, HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM, HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM, HID_LOCAL_ITEM_TAG_STRING_INDEX, HID_LOCAL_ITEM_TAG_STRING_MINIMUM, HID_LOCAL_ITEM_TAG_STRING_MAXIMUM, HID_LOCAL_ITEM_TAG_DELIMITER

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# PRINTER device class specific descriptions.
# https://www.usb.org/sites/default/files/usbprint11a021811.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/class/usblp.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/printer.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_printer.c

# Connected PRINTER devices are known to create the following /dev/ files:
# /dev/usb/lp#.
# TODO: write descriptions for those.

# drivers/usb/class/usblp.c
define USBLP_REQ_GET_ID	0x00
define USBLP_REQ_GET_STATUS	0x01
define USBLP_REQ_RESET	0x02
define USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST	0x00
define USBLP_FIRST_PROTOCOL	1
define USBLP_LAST_PROTOCOL	3

resource fd_usb_printer[fd_usb]

syz_usb_connect$printer(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_printer], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_printer (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$printer(fd fd_usb_printer, descs ptr[in, vusb_descriptors_printer], resps ptr[in, vusb_responses_printer]) (timeout[300], remote_cover)

usb_device_descriptor_printer {
	inner	usb_device_descriptor_t[0, 0, 0, 0x525, 0xa4a8, 64, array[usb_config_descriptor_printer, 1]]
} [packed]

usb_config_descriptor_printer {
	inner	usb_config_descriptor_ifaces_array_t[const[1, int8], array[usb_interface_descriptor_printer, 1]]
} [packed]

usb_interface_descriptor_printer {
	inner	usb_interface_descriptor_t[const[0, int8], int8, int8[1:2], const[USB_CLASS_PRINTER, int8], const[1, int8], int8[USBLP_FIRST_PROTOCOL:USBLP_LAST_PROTOCOL], void, usb_endpoint_descriptors_printer]
} [packed]

usb_endpoint_descriptors_printer {
	in	usb_endpoint_descriptor_printer_out
	out	array[usb_endpoint_descriptor_printer_in, 0:1]
} [packed]

usb_endpoint_descriptor_printer_out {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_PRINTER_OUT_ADDRESS, int8], const[USB_ENDPOINT_PRINTER_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_printer_in {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_PRINTER_IN_ADDRESS, int8], const[USB_ENDPOINT_PRINTER_ATTRIBUTES, int8], void]
} [packed]

define USB_ENDPOINT_PRINTER_ATTRIBUTES	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_PRINTER_OUT_ADDRESS	(1)
define USB_ENDPOINT_PRINTER_IN_ADDRESS	(2 | USB_DIR_IN)

vusb_descriptors_printer {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_printer {
	len					len[parent, int32]
	generic					ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE			ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	USBLP_REQ_GET_ID			ptr[in, vusb_response_t[USB_TYPE_CLASS, USBLP_REQ_GET_ID, usb_printer_get_id_response]]
	USBLP_REQ_GET_STATUS			ptr[in, vusb_response_t[USB_TYPE_CLASS, USBLP_REQ_GET_STATUS, int8]]
	USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST	ptr[in, vusb_response_t[USB_TYPE_CLASS, USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST, int8]]
} [packed]

usb_printer_get_id_response {
	length	len[id, int16be]
	id	array[int8, 0:256]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# CDC ECM (Ethernet) device class specific descriptions.
# https://www.usb.org/document-library/class-definitions-communication-devices-12
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/cdc_ether.c
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/usbnet.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/ether.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_ecm.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/u_ether.c

# Connected CDC ECM devices are known to create usbN network interfaces.
# TODO: write descriptions for those.

resource fd_usb_cdc_ecm[fd_usb]

syz_usb_connect$cdc_ecm(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_cdc_ecm], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_cdc_ecm (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$cdc_ecm(fd fd_usb_cdc_ecm, descs ptr[in, vusb_descriptors_cdc_ecm], resps ptr[in, vusb_responses_cdc_ecm]) (timeout[300], remote_cover)

usb_device_descriptor_cdc_ecm {
	inner	usb_device_descriptor_t[USB_CLASS_COMM, 0, 0, 0x525, 0xa4a1, 64, array[usb_config_descriptor_cdc_ecm, 1]]
} [packed]

usb_config_descriptor_cdc_ecm {
	inner	usb_config_descriptor_ifaces_array_t[const[1, int8], array[usb_interface_descriptor_cdc_ecm, 1]]
} [packed]

# Per specification CDC ECM devices have two interfaces (control and data),
# but here we're merging them into one for simplicity since Linux supports that.
usb_interface_descriptor_cdc_ecm {
	inner	usb_interface_descriptor_t[const[0, int8], int8, int8[2:3], const[USB_CLASS_COMM, int8], const[USB_CDC_SUBCLASS_ETHERNET, int8], const[USB_CDC_PROTO_NONE, int8], usb_cdc_header_ecm, usb_endpoint_descriptors_cdc_ecm]
} [packed]

usb_endpoint_descriptors_cdc_ecm {
	notify	array[usb_endpoint_descriptor_cdc_ecm_notify, 0:1]
	in	usb_endpoint_descriptor_cdc_ecm_in
	out	usb_endpoint_descriptor_cdc_ecm_out
} [packed]

usb_endpoint_descriptor_cdc_ecm_notify {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_CDC_ECM_NOTIFY_ADDRESS, int8], const[USB_ENDPOINT_CDC_ECM_NOTIFY_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_cdc_ecm_in {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_CDC_ECM_IN_ADDRESS, int8], const[USB_ENDPOINT_CDC_ECM_DATA_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_cdc_ecm_out {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_CDC_ECM_OUT_ADDRESS, int8], const[USB_ENDPOINT_CDC_ECM_DATA_ATTRIBUTES, int8], void]
} [packed]

define USB_ENDPOINT_CDC_ECM_NOTIFY_ATTRIBUTES	(USB_ENDPOINT_XFER_INT)
define USB_ENDPOINT_CDC_ECM_DATA_ATTRIBUTES	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_CDC_ECM_NOTIFY_ADDRESS	(1 | USB_DIR_IN)
define USB_ENDPOINT_CDC_ECM_IN_ADDRESS	(2 | USB_DIR_IN)
define USB_ENDPOINT_CDC_ECM_OUT_ADDRESS	(3)

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/usb/core/message.c#L2137
# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/cdc_ether.c#L155
usb_cdc_header_ecm {
	union	usb_cdc_union_desc_t[0, 0]
	header	usb_cdc_header_desc
	ether	usb_cdc_ether_desc

	other	array[usb_cdc_header_ecm_other, 0:6]
} [packed]

usb_cdc_header_ecm_other [
	call_mgmt		usb_cdc_call_mgmt_descriptor
	acm			usb_cdc_acm_descriptor
	country_functional	usb_cdc_country_functional_desc
	network_terminal	usb_cdc_network_terminal_desc
	dmm			usb_cdc_dmm_desc
	mdlm			usb_cdc_mdlm_desc
	mdlm_detail		usb_cdc_mdlm_detail_desc
	obex			usb_cdc_obex_desc
	ncm			usb_cdc_ncm_desc
	mbim			usb_cdc_mbim_desc
	mbim_extended		usb_cdc_mbim_extended_desc
] [varlen]

usb_cdc_header_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_HEADER_TYPE, int8]

	bcdCDC			int16
} [packed]

usb_cdc_call_mgmt_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_CALL_MANAGEMENT_TYPE, int8]

	bmCapabilities		flags[usb_cdc_call_mgmt_caps, int8]
	bDataInterface		int8
} [packed]

usb_cdc_call_mgmt_caps = USB_CDC_CALL_MGMT_CAP_CALL_MGMT, USB_CDC_CALL_MGMT_CAP_DATA_INTF

usb_cdc_acm_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_ACM_TYPE, int8]

	bmCapabilities		flags[usb_cdc_acm_caps, int8]
} [packed]

usb_cdc_acm_caps = USB_CDC_COMM_FEATURE, USB_CDC_CAP_LINE, USB_CDC_CAP_BRK, USB_CDC_CAP_NOTIFY

type usb_cdc_union_desc_t[MASTER, SLAVE] {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_UNION_TYPE, int8]

	bMasterInterface0	const[MASTER, int8]
	bSlaveInterface0	const[SLAVE, int8]
	slave_interfaces	array[int8, 0:6]
} [packed]

usb_cdc_country_functional_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_COUNTRY_TYPE, int8]

	iCountryCodeRelDate	int8
	wCountyCode0		int16
	country_codes		array[int16, 0:6]
} [packed]

usb_cdc_network_terminal_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_NETWORK_TERMINAL_TYPE, int8]

	bEntityId		int8
	iName			int8
	bChannelIndex		int8
	bPhysicalInterface	int8
} [packed]

usb_cdc_ether_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_ETHERNET_TYPE, int8]

	iMACAddress		const[1, int8]
	bmEthernetStatistics	int32
	wMaxSegmentSize		int16
	wNumberMCFilters	int16
	bNumberPowerFilters	int8
} [packed]

usb_cdc_dmm_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_DMM_TYPE, int8]

	bcdVersion		int16
	wMaxCommand		int16
} [packed]

usb_cdc_mdlm_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_MDLM_TYPE, int8]

	bcdVersion		int16
	bGUID			usb_cdc_ecm_mbm_guid
} [packed]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/cdc_ether.c#L61
usb_cdc_ecm_mbm_guid {
	id0	const[0x14f5e048ba817a3, int64]
	id1	const[0x2a397ecbffc007a6, int64]
} [packed]

usb_cdc_mdlm_detail_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_MDLM_DETAIL_TYPE, int8]

	bGuidDescriptorType	int8
	bDetailData		array[int8, 0:256]
} [packed]

usb_cdc_obex_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_OBEX_TYPE, int8]

	bcdVersion		int16
} [packed]

usb_cdc_ncm_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_NCM_TYPE, int8]

	bcdNcmVersion		int16
	bmNetworkCapabilities	flags[usb_cdc_ncm_ncaps, int8]
} [packed]

usb_cdc_ncm_ncaps = USB_CDC_NCM_NCAP_ETH_FILTER, USB_CDC_NCM_NCAP_NET_ADDRESS, USB_CDC_NCM_NCAP_ENCAP_COMMAND, USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE, USB_CDC_NCM_NCAP_CRC_MODE, USB_CDC_NCM_NCAP_NTB_INPUT_SIZE

usb_cdc_mbim_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_MBIM_TYPE, int8]

	bcdMBIMVersion		int16
	wMaxControlMessage	int16
	bNumberFilters		int8
	bMaxFilterSize		int8
	wMaxSegmentSize		int16
	bmNetworkCapabilities	int8
} [packed]

usb_cdc_mbim_extended_desc {
	bLength				len[parent, int8]
	bDescriptorType			const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType		const[USB_CDC_MBIM_EXTENDED_TYPE, int8]

	bcdMBIMExtendedVersion		int16
	bMaxOutstandingCommandMessages	int8
	wMTU				int16
} [packed]

vusb_descriptors_cdc_ecm {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/usbnet.c#L147
	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor_t[usb_cdc_ecm_mac]]]
} [packed]

usb_cdc_ecm_mac {
# This is a UTF16 encoded string "424242424242".
	data0	const[0x3400320034003200, int64be]
	data1	const[0x3400320034003200, int64be]
	data2	const[0x3400320034003200, int64be]
} [packed]

vusb_responses_cdc_ecm {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# CDC NCM class specific descriptions.
# CDC NCM is based on CDC ECM, so some of the descriptions are reused.
# https://www.usb.org/document-library/network-control-model-devices-specification-v10-and-errata-and-adopters-agreement
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/cdc_ncm.c
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/usbnet.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/ncm.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_ncm.c

resource fd_usb_cdc_ncm[fd_usb]

syz_usb_connect$cdc_ncm(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_cdc_ncm], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_cdc_ncm (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$cdc_ncm(fd fd_usb_cdc_ncm, descs ptr[in, vusb_descriptors_cdc_ncm], resps ptr[in, vusb_responses_cdc_ncm]) (timeout[300], remote_cover)

usb_device_descriptor_cdc_ncm {
	inner	usb_device_descriptor_t[USB_CLASS_COMM, 0, 0, 0x525, 0xa4a1, 64, array[usb_config_descriptor_cdc_ncm, 1]]
} [packed]

usb_config_descriptor_cdc_ncm {
	inner	usb_config_descriptor_t[const[1, int8], const[2, int8], usb_interface_descriptors_cdc_ncm]
} [packed]

usb_interface_descriptors_cdc_ncm {
	control		usb_interface_descriptor_fixed_t[0, CDC_NCM_COMM_ALTSETTING_NCM, 1, USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE, usb_cdc_header_ncm, usb_endpoint_descriptor_cdc_ecm_notify]
	data_nop	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE, void, void]
	data		usb_interface_descriptor_fixed_t[1, CDC_NCM_DATA_ALTSETTING_NCM, 2, USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE, void, usb_endpoint_descriptors_cdc_ncm_data]
} [packed]

usb_endpoint_descriptors_cdc_ncm_data {
	in	usb_endpoint_descriptor_cdc_ecm_in
	out	usb_endpoint_descriptor_cdc_ecm_out
} [packed]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/usb/core/message.c#L2137
# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/cdc_ncm.c#L798
usb_cdc_header_ncm {
	union	usb_cdc_union_desc_t[0, 1]
	header	usb_cdc_header_desc
	ether	usb_cdc_ether_desc
	ncm	usb_cdc_ncm_desc

	other	array[usb_cdc_header_ncm_other, 0:6]
} [packed]

usb_cdc_header_ncm_other [
	call_mgmt		usb_cdc_call_mgmt_descriptor
	acm			usb_cdc_acm_descriptor
	country_functional	usb_cdc_country_functional_desc
	network_terminal	usb_cdc_network_terminal_desc
	dmm			usb_cdc_dmm_desc
	mdlm			usb_cdc_mdlm_desc
	mdlm_detail		usb_cdc_mdlm_detail_desc
	obex			usb_cdc_obex_desc
	mbim			usb_cdc_mbim_desc
	mbim_extended		usb_cdc_mbim_extended_desc
] [varlen]

vusb_descriptors_cdc_ncm {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/usbnet.c#L147
	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor_t[usb_cdc_ecm_mac]]]
} [packed]

vusb_responses_cdc_ncm {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	USB_CDC_GET_NTB_PARAMETERS	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_NTB_PARAMETERS, usb_cdc_ncm_ntb_parameters]]
	USB_CDC_GET_NTB_INPUT_SIZE	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_NTB_INPUT_SIZE, int32]]
	USB_CDC_GET_NTB_FORMAT		ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_NTB_FORMAT, int16[0:1]]]
	USB_CDC_GET_MAX_DATAGRAM_SIZE	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_MAX_DATAGRAM_SIZE, int16]]
	USB_CDC_GET_CRC_MODE		ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_CRC_MODE, int16[0:1]]]
} [packed]

usb_cdc_ncm_ntb_parameters {
	wLength			int16
	bmNtbFormatsSupported	int16
	dwNtbInMaxSize		int32
	wNdpInDivisor		int16
	wNdpInPayloadRemainder	int16
	wNdpInAlignment		int16
	wPadding1		int16
	dwNtbOutMaxSize		int32
	wNdpOutDivisor		int16
	wNdpOutPayloadRemainder	int16
	wNdpOutAlignment	int16
	wNtbOutMaxDatagrams	int16
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC1 device class specific descriptions.
# https://www.usb.org/sites/default/files/audio10.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/audio.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac1.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac1_legacy.c
# https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/usb/audio.h

# TODO: find out which /dev/ files are created by connected UAC1 devices and add descriptions for those.

resource fd_usb_uac1[fd_usb]

syz_usb_connect$uac1(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_uac1], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_uac1 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$uac1(fd fd_usb_uac1, descs ptr[in, vusb_descriptors_uac1], resps ptr[in, vusb_responses_uac1]) (timeout[300], remote_cover)

usb_device_descriptor_uac1 {
	inner	usb_device_descriptor_t[0, 0, 0, 0x1d6b, 0x101, 64, array[usb_config_descriptor_uac1, 1]]
} [packed]

usb_config_descriptor_uac1 {
	inner	usb_config_descriptor_t[const[1, int8], const[3, int8], usb_interface_descriptors_uac1]
} [packed]

# TODO: control interface might have and optional interrupt endpoint.
usb_interface_descriptors_uac1 {
	inner	usb_interface_descriptors_uac1_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_uac1_inner {
	control		usb_interface_descriptor_fixed_t[0, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOCONTROL, 0, uac_control_iface_extra_descriptors, void]
	as_out_alt_0	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, void, void]
	as_out_alt_1	usb_interface_descriptor_fixed_t[1, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, uac_as_iface_extra_descriptors, uac_as_out_endpoint_descriptor]
	as_in_alt_0	usb_interface_descriptor_fixed_t[2, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, void, void]
	as_in_alt_1	usb_interface_descriptor_fixed_t[2, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, uac_as_iface_extra_descriptors, uac_as_in_endpoint_descriptor]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC uses IDs to make it possible for terminals and units to refer to each other.
# We don't have a way to describe this, so just use a limited number of ids.
type uac_id int8[1:6]

uac_control_iface_extra_descriptors {
	header	uac1_ac_header_descriptor
	others	array[uac_control_iface_extra_descriptor, 0:6]
} [packed]

uac1_ac_header_descriptor {
	bLength			const[UAC_DT_AC_HEADER_LENGTH, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_HEADER, int8]

	bcdADC			int16
	wTotalLength		len[uac_control_iface_extra_descriptors, int16]
	bInCollection		const[F_AUDIO_NUM_INTERFACES, int8]

# These must match interfaces numbers.
	baInterfaceNr0		const[1, int8]
	baInterfaceNr1		const[2, int8]
} [packed]

uac_control_iface_extra_descriptor [
	input_terminal	uac_input_terminal_descriptor
	output_terminal	uac1_output_terminal_descriptor
	mixer_unit	uac_mixer_unit_descriptor
	selector_unit	uac_selector_unit_descriptor
	feature_unit	uac_feature_unit_descriptor
	processing_unit	uac_processing_unit_descriptor
	extension_unit	uac_extension_unit_descriptor
] [varlen]

define F_AUDIO_NUM_INTERFACES	2
define UAC_DT_AC_HEADER_LENGTH	UAC_DT_AC_HEADER_SIZE(F_AUDIO_NUM_INTERFACES)

uac_input_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_INPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_input_terminal_types, int16]
	bAssocTerminal		uac_id
	bNrChannels		int8
	wChannelConfig		int16
	iChannelNames		int8
	iTerminal		int8
} [packed]

# The following list contains input terminal types and inout terminal types.
uac_input_terminal_types = UAC_TERMINAL_UNDEFINED, UAC_TERMINAL_STREAMING, UAC_TERMINAL_VENDOR_SPEC, UAC_INPUT_TERMINAL_UNDEFINED, UAC_INPUT_TERMINAL_MICROPHONE, UAC_INPUT_TERMINAL_DESKTOP_MICROPHONE, UAC_INPUT_TERMINAL_PERSONAL_MICROPHONE, UAC_INPUT_TERMINAL_OMNI_DIR_MICROPHONE, UAC_INPUT_TERMINAL_MICROPHONE_ARRAY, UAC_INPUT_TERMINAL_PROC_MICROPHONE_ARRAY, UAC_BIDIR_TERMINAL_UNDEFINED, UAC_BIDIR_TERMINAL_HANDSET, UAC_BIDIR_TERMINAL_HEADSET, UAC_BIDIR_TERMINAL_SPEAKER_PHONE, UAC_BIDIR_TERMINAL_ECHO_SUPPRESSING, UAC_BIDIR_TERMINAL_ECHO_CANCELING
# The following list contains output terminal types and inout terminal types.
uac_output_terminal_types = UAC_TERMINAL_UNDEFINED, UAC_TERMINAL_STREAMING, UAC_TERMINAL_VENDOR_SPEC, UAC_OUTPUT_TERMINAL_UNDEFINED, UAC_OUTPUT_TERMINAL_SPEAKER, UAC_OUTPUT_TERMINAL_HEADPHONES, UAC_OUTPUT_TERMINAL_HEAD_MOUNTED_DISPLAY_AUDIO, UAC_OUTPUT_TERMINAL_DESKTOP_SPEAKER, UAC_OUTPUT_TERMINAL_ROOM_SPEAKER, UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER, UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER, UAC_BIDIR_TERMINAL_UNDEFINED, UAC_BIDIR_TERMINAL_HANDSET, UAC_BIDIR_TERMINAL_HEADSET, UAC_BIDIR_TERMINAL_SPEAKER_PHONE, UAC_BIDIR_TERMINAL_ECHO_SUPPRESSING, UAC_BIDIR_TERMINAL_ECHO_CANCELING

uac1_output_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_OUTPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_output_terminal_types, int16]
	bAssocTerminal		uac_id
	bSourceID		uac_id
	iTerminal		int8
} [packed]

uac_mixer_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIXER_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac_selector_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_SELECTOR_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac_feature_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FEATURE_UNIT, int8]

	bUnitID			uac_id
	bSourceID		uac_id
	bControlSize		len[bmaControls, int8]
	bmaControls		array[flags[uac_feature_unit_controls, int16], 1:6]
	iFeature		int8
} [packed]

uac_feature_unit_controls = UAC_FU_MUTE, UAC_FU_VOLUME, UAC_FU_BASS, UAC_FU_MID, UAC_FU_TREBLE, UAC_FU_GRAPHIC_EQUALIZER, UAC_FU_AUTOMATIC_GAIN, UAC_FU_DELAY, UAC_FU_BASS_BOOST, UAC_FU_LOUDNESS

uac_processing_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC1_PROCESSING_UNIT, int8]

	bUnitID			uac_id
	wProcessType		flags[uac_processing_unit_types, int16]
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac_processing_unit_types = UAC_PROCESS_UNDEFINED, UAC_PROCESS_UP_DOWNMIX, UAC_PROCESS_DOLBY_PROLOGIC, UAC_PROCESS_STEREO_EXTENDER, UAC_PROCESS_REVERB, UAC_PROCESS_CHORUS, UAC_PROCESS_DYN_RANGE_COMP

uac_extension_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC1_EXTENSION_UNIT, int8]

	bUnitID			uac_id
	wProcessType		int16
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac_as_iface_extra_descriptors {
	others	array[uac_as_iface_extra_descriptor, 0:6]
} [packed]

uac_as_iface_extra_descriptor [
	as_header			uac1_as_header_descriptor
	format_type_i_continuous	uac_format_type_i_continuous_descriptor
	format_type_i_discrete		uac_format_type_i_discrete_descriptor
	format_type_ii_discrete		uac_format_type_ii_discrete_descriptor
	format_type_ii_ext		uac_format_type_ii_ext_descriptor
	format_type_i_ext		uac_format_type_i_ext_descriptor
] [varlen]

uac1_as_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_AS_GENERAL, int8]

	bTerminalLink		int8
	bDelay			int8
	wFormatTag		flags[uac_format_tags, int16]
} [packed]

uac_format_tags = UAC_FORMAT_TYPE_I_UNDEFINED, UAC_FORMAT_TYPE_I_PCM, UAC_FORMAT_TYPE_I_PCM8, UAC_FORMAT_TYPE_I_IEEE_FLOAT, UAC_FORMAT_TYPE_I_ALAW, UAC_FORMAT_TYPE_I_MULAW, UAC_FORMAT_TYPE_II_MPEG, UAC_FORMAT_TYPE_II_AC3
uac_usb_format_types_i = UAC_FORMAT_TYPE_I, UAC_FORMAT_TYPE_II, UAC_FORMAT_TYPE_III, UAC_FORMAT_TYPE_UNDEFINED

uac_format_type_i_continuous_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bNrChannels		int8
	bSubframeSize		int8[1:4]
	bBitResolution		int8
	bSamFreqType		int8
	tLowerSamFreq		array[int8, 0:3]
	tUpperSamFreq		array[int8, 0:3]
} [packed]

uac_format_type_i_discrete_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bNrChannels		int8
	bSubframeSize		int8[1:4]
	bBitResolution		int8
	bSamFreqType		int8
	tSamFreq		array[int8, 0:9]
} [packed]

uac_format_type_ii_discrete_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_II, int8]
	wMaxBitRate		int16
	wSamplesPerFrame	int16
	bSamFreqType		int8
	tSamFreq		array[int8, 0:9]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac_as_out_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac_iso_endpoint_descriptor]
} [packed]

uac_as_in_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_IN_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac_iso_endpoint_descriptor]
} [packed]

define USB_ENDPOINT_UAC1_AS_OUT_ADDRESS	(1 | USB_DIR_OUT)
define USB_ENDPOINT_UAC1_AS_IN_ADDRESS	(2 | USB_DIR_IN)
define USB_ENDPOINT_UAC1_AS_ATTRIBUTES	(USB_ENDPOINT_SYNC_ADAPTIVE | USB_ENDPOINT_XFER_ISOC)

uac_iso_ep_attributes = USB_ENDPOINT_SYNCTYPE, USB_ENDPOINT_SYNC_NONE, USB_ENDPOINT_SYNC_ASYNC, USB_ENDPOINT_SYNC_ADAPTIVE, USB_ENDPOINT_SYNC_SYNC

uac_iso_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubType	const[UAC_EP_GENERAL, int8]

	bmAttributes		flags[uac_iso_ep_attributes, int8]
	bLockDelayUnits		int8
	wLockDelay		int16
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

vusb_descriptors_uac1 {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_uac1 {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	audio_UAC_GET_CUR		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_CUR, array[int8, 1:3]]]
	audio_UAC_GET_MIN		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_MIN, array[int8, 1:3]]]
	audio_UAC_GET_MAX		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_MAX, array[int8, 1:3]]]
	audio_UAC_GET_RES		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_RES, array[int8, 1:4]]]
	audio_UAC_GET_MEM		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_MEM, array[int8, 3]]]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC2 device class specific descriptions.
# https://www.usb.org/sites/default/files/audio10.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/audio.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac2.c
# https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/usb/audio.h

resource fd_usb_uac2[fd_usb]

syz_usb_connect$uac2(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_uac2], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_uac2 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$uac2(fd fd_usb_uac2, descs ptr[in, vusb_descriptors_uac1], resps ptr[in, vusb_responses_uac1]) (timeout[300], remote_cover)

usb_device_descriptor_uac2 {
	inner	usb_device_descriptor_t[0, 0, 0, 0x41e, 0x3000, 64, array[usb_config_descriptor_uac2, 1]]
} [packed]

usb_config_descriptor_uac2 {
	inner	usb_config_descriptor_extra_t[const[1, int8], const[3, int8], uac2_interface_assoc_descriptor, usb_interface_descriptors_uac2]
} [packed]

uac2_interface_assoc_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_INTERFACE_ASSOCIATION, int8]

	bFirstInterface		int8[0:2]
	bInterfaceCount		int8[0:2]
	bFunctionClass		const[USB_CLASS_AUDIO, int8]
	bFunctionSubClass	flags[audio_function_category_types, int8]
	bFunctionProtocol	const[UAC_VERSION_2, int8]
	iFunction		int8
} [packed]

audio_function_category_types = UAC2_FUNCTION_SUBCLASS_UNDEFINED, UAC2_FUNCTION_DESKTOP_SPEAKER, UAC2_FUNCTION_HOME_THEATER, UAC2_FUNCTION_MICROPHONE, UAC2_FUNCTION_HEADSET, UAC2_FUNCTION_TELEPHONE, UAC2_FUNCTION_CONVERTER, UAC2_FUNCTION_SOUND_RECORDER, UAC2_FUNCTION_IO_BOX, UAC2_FUNCTION_MUSICAL_INSTRUMENT, UAC2_FUNCTION_PRO_AUDIO, UAC2_FUNCTION_AUDIO_VIDEO, UAC2_FUNCTION_CONTROL_PANEL, UAC2_FUNCTION_OTHER

usb_interface_descriptors_uac2 {
	inner	usb_interface_descriptors_uac2_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_uac2_inner {
	control		usb_interface_descriptor_fixed_t[0, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOCONTROL, UAC_VERSION_2, uac2_control_iface_extra_descriptors, void]
	as_out_alt_0	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, void, void]
	as_out_alt_1	usb_interface_descriptor_fixed_t[1, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, uac2_as_iface_extra_descriptors, uac2_as_out_endpoint_descriptor]
	as_in_alt_0	usb_interface_descriptor_fixed_t[2, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, void, void]
	as_in_alt_1	usb_interface_descriptor_fixed_t[2, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, uac2_as_iface_extra_descriptors, uac2_as_in_endpoint_descriptor]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac2_control_iface_extra_descriptors {
	header	uac2_ac_header_descriptor
	others	array[uac2_control_iface_extra_descriptor, 0:6]
} [packed]

uac2_ac_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MS_HEADER, int8]
	bcdADC			int16
	bCategory		flags[uac2_feature_unit_controls, int8]
	wTotalLength		len[uac2_control_iface_extra_descriptors, int16]
	bmControls		int8
} [packed]

uac2_feature_unit_controls = UAC2_FUNCTION_SUBCLASS_UNDEFINED, UAC2_FUNCTION_DESKTOP_SPEAKER, UAC2_FUNCTION_HOME_THEATER, UAC2_FUNCTION_MICROPHONE, UAC2_FUNCTION_HEADSET, UAC2_FUNCTION_TELEPHONE, UAC2_FUNCTION_CONVERTER, UAC2_FUNCTION_SOUND_RECORDER, UAC2_FUNCTION_IO_BOX, UAC2_FUNCTION_MUSICAL_INSTRUMENT, UAC2_FUNCTION_PRO_AUDIO, UAC2_FUNCTION_AUDIO_VIDEO, UAC2_FUNCTION_CONTROL_PANEL, UAC2_FUNCTION_OTHER, uac_feature_unit_controls

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac2_as_iface_extra_descriptors {
	others	array[uac2_as_iface_extra_descriptor, 0:6]
} [packed]

uac2_as_iface_extra_descriptor [
	as_header			uac2_as_header_descriptor
	format_type_i_descriptor	uac2_format_type_i_descriptor
	format_type_i_continuous	uac_format_type_i_continuous_descriptor
	format_type_i_discrete		uac_format_type_i_discrete_descriptor
	format_type_ii_discrete		uac_format_type_ii_discrete_descriptor
	format_type_i_ext		uac2_format_type_i_ext_descriptor
	format_type_ii_ext		uac_format_type_ii_ext_descriptor
] [varlen]

uac2_as_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_AS_GENERAL, int8]
	bTerminalLink		int8
	bmControls		int8
	bFormatType		flags[uac_usb_format_types_i, int8]
	bmFormats		flags[uac_format_tags, int32]
	bNrChannels		int8
	bmChannelConfig		int32
	iChannelNames		int8
} [packed]

b_sub_slot_sizes = 1, 2, 3, 4

uac2_format_type_i_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]
	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bSubslotSize		flags[b_sub_slot_sizes, int8]
	bBitResolution		int8
} [packed]

uac2_format_type_i_ext_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bSubslotSize		int8
	bBitResolution		int8
	bHeaderLength		int8
	bControlSize		int8
	bSideBandProtocol	int8
} [packed]

uac_format_type_ii_ext_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]
	bFormatType		const[UAC_FORMAT_TYPE_II, int8]
	wMaxBitRate		int16
	wSamplesPerFrame	int16
	bHeaderLength		int8
	bSideBandProtocol	int8
} [packed]

uac_format_type_i_ext_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]
	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bSubslotSize		int8
	bBitResolution		int8
	bHeaderLength		int8
	bControlSize		int8
	bSideBandProtocol	int8
} [packed]

uac2_as_out_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac2_iso_endpoint_descriptor]
} [packed]

uac2_as_in_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_IN_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac2_iso_endpoint_descriptor]
} [packed]

uac2_iso_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubtype	const[UAC_EP_GENERAL, int8]

	bmAttributes		flags[csep_bm_attributes, int8]
	bmControls		flags[csep_bm_controls, int8]
	bLockDelayUnits		int8
	wLockDelay		int16
} [packed]

csep_bm_attributes = UAC_EP_CS_ATTR_SAMPLE_RATE, UAC_EP_CS_ATTR_PITCH_CONTROL, UAC_EP_CS_ATTR_FILL_MAX
csep_bm_controls = UAC2_CONTROL_PITCH, UAC2_CONTROL_DATA_OVERRUN, UAC2_CONTROL_DATA_UNDERRUN

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac2_control_iface_extra_descriptor [
	input_terminal	uac2_input_terminal_descriptor
	output_terminal	uac2_output_terminal_descriptor
	mixer_unit	uac2_mixer_unit_descriptor
	selector_unit	uac2_clock_selector_descriptor

	feature_unit	uac2_feature_unit_descriptor
	processing_unit	uac2_processing_unit_descriptor
	extension_unit	uac2_extension_unit_descriptor

	effect_unit	uac2_effect_unit_descriptor
	sample_rate	uac2_sample_rate_descriptor
	source_unit	uac2_clock_source_descriptor
	multiply_unit	uac2_clock_multiplier_descriptor
] [varlen]

uac2_input_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_INPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_input_terminal_types, int16]
	bAssocTerminal		uac_id
	bCSourceID		int8
	bNrChannels		int8
	bmChannelConfig		int32
	iChannelNames		int8
	bmControls		int8
	iTerminal		int8
} [packed]

uac2_output_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_OUTPUT_TERMINAL, int8]
	bTerminalID		uac_id
	wTerminalType		flags[uac_output_terminal_types, int16]
	bAssocTerminal		int8
	bSourceID		uac_id
	bCSourceID		int8
	bmControls		int16
	iTerminal		int8
} [packed]

uac2_mixer_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIXER_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

# TODO: Figure out if bmControls and iClockSelector should be a part of this structure.
uac2_clock_selector_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_CLOCK_SELECTOR, int8]
	bClockID		int8
	bNrInPins		len[baCSourceID, int8]
	baCSourceID		array[int8, 0:8]
} [packed]

# TODO: Verify coverage.
uac2_processing_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC2_PROCESSING_UNIT_V2, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac2_processing_unit_types, int16], 1:6]
} [packed]

uac2_processing_unit_types = UAC2_PROCESS_UNDEFINED, UAC2_PROCESS_UP_DOWNMIX, UAC2_PROCESS_DOLBY_PROLOCIC, UAC2_PROCESS_STEREO_EXTENDER

uac2_extension_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_EXTENSION_UNIT_V2, int8]

	bUnitID			uac_id
	wProcessType		int16
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

# TODO: Verify coverage.
uac2_effect_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC2_EFFECT_UNIT, int8]
	bUnitID			uac_id
	wEffectType		flags[uac2_effect_unit_types, int16]
	bSourceID		uac_id
	bmaControls		array[flags[uac2_processing_unit_types, int16], 1:6]
} [packed]

uac2_effect_unit_types = UAC2_EFFECT_UNDEFINED, UAC2_EFFECT_PARAM_EQ, UAC2_EFFECT_REVERB, UAC2_EFFECT_MOD_DELAY, UAC2_EFFECT_DYN_RANGE_COMP

uac2_sample_rate_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC2_SAMPLE_RATE_CONVERTER, int8]
	bUnitID			uac_id
	wProcessType		flags[uac2_processing_unit_types, int16]
	bSourceID		uac_id
	bmaControls		array[flags[uac2_processing_unit_types, int16], 1:6]
} [packed]

uac2_feature_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_FEATURE_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac2_feature_unit_controls, int16], 1:6]
} [packed]

uac2_clock_source_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_CLOCK_SOURCE, int8]
	bClockID		int8
	bmAttributes		flags[uac2_clock_bmattribute_types, int8]
	bmControls		int8
	bAssocTerminal		int8
	iClockSource		flags[uac2_clock_source_types, int8]
} [packed]

uac2_clock_bmattribute_types = UAC_CLOCK_SOURCE_TYPE_EXT, UAC_CLOCK_SOURCE_TYPE_INT_FIXED, UAC_CLOCK_SOURCE_TYPE_INT_VAR, UAC_CLOCK_SOURCE_TYPE_INT_PROG, UAC_CLOCK_SOURCE_SYNCED_TO_SOF
uac2_clock_source_types = UAC_CLOCK_SOURCE_TYPE_EXT, UAC_CLOCK_SOURCE_TYPE_INT_FIXED, UAC_CLOCK_SOURCE_TYPE_INT_VAR, UAC_CLOCK_SOURCE_TYPE_INT_PROG, UAC_CLOCK_SOURCE_SYNCED_TO_SOF

uac2_clock_multiplier_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_CLOCK_MULTIPLIER, int8]
	bClockID		int8
	bCSourceID		int8
	bmControls		int8
	iClockMultiplier	int8
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC3 device class specific descriptions.
# https://www.usb.org/sites/default/files/audio10.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/audio.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac3.c
# https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/usb/audio.h

resource fd_usb_uac3[fd_usb]

syz_usb_connect$uac3(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_uac3], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_uac3 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$uac3(fd fd_usb_uac3, descs ptr[in, vusb_descriptors_uac1], resps ptr[in, vusb_responses_uac1]) (timeout[300], remote_cover)

usb_device_descriptor_uac3 {
	inner	usb_device_descriptor_t[0, 0, 0, 0x582, 0x582, 64, array[usb_config_descriptor_uac3, 1]]
} [packed]

usb_config_descriptor_uac3 {
	inner	usb_config_descriptor_extra_t[const[1, int8], const[3, int8], uac3_interface_assoc_descriptor, usb_interface_descriptors_uac3]
} [packed]

uac3_interface_assoc_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_INTERFACE_ASSOCIATION, int8]

	bFirstInterface		int8[0:2]
	bInterfaceCount		int8[0:2]
	bFunctionClass		const[USB_CLASS_AUDIO, int8]
	bFunctionSubClass	flags[uac3_all_subclasses, int8]
	bFunctionProtocol	const[UAC_VERSION_3, int8]
	iFunction		int8
} [packed]

usb_interface_descriptors_uac3 {
	inner	usb_interface_descriptors_uac3_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_uac3_inner {
	control		usb_interface_descriptor_fixed_t[0, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOCONTROL, UAC_VERSION_3, uac3_control_iface_extra_descriptors, void]
	as_out_alt_0	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, void, void]
	as_out_alt_1	usb_interface_descriptor_fixed_t[1, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, uac3_as_iface_extra_descriptors, uac3_as_out_endpoint_descriptor]
	as_in_alt_0	usb_interface_descriptor_fixed_t[2, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, void, void]
	as_in_alt_1	usb_interface_descriptor_fixed_t[2, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, uac3_as_iface_extra_descriptors, uac3_as_in_endpoint_descriptor]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac3_control_iface_extra_descriptors {
	header	uac3_ac_header_descriptor
	others	array[uac3_control_iface_extra_descriptor, 0:6]
} [packed]

uac3_ac_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MS_HEADER, int8]

	bCategory		flags[uac3_feature_unit_controls, int8]
	wTotalLength		len[uac3_control_iface_extra_descriptors, int16]
	bmControls		int32
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac3_as_iface_extra_descriptors {
	others	array[uac3_as_iface_extra_descriptor, 0:6]
} [packed]

uac3_as_iface_extra_descriptor [
	as_header			uac3_as_header_descriptor
	format_type_i_descriptor	uac2_format_type_i_descriptor
	format_type_i_continuous	uac_format_type_i_continuous_descriptor
	format_type_i_discrete		uac_format_type_i_discrete_descriptor
	format_type_ii_discrete		uac_format_type_ii_discrete_descriptor
	format_type_i_ext		uac2_format_type_i_ext_descriptor
	format_type_ii_ext		uac_format_type_ii_ext_descriptor
] [varlen]

# TODO: Figure out how wClusterDescrID is used in the kernel.
uac3_as_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_AS_GENERAL, int8]
	bTerminalLink		int8

	bmControls		int32
	wClusterDescrID		int16

	bmFormats		flags[uac_format_tags, int64]

	bSubslotSize		int8
	bBitResolution		int8
	bmAuxProtocols		int16
	bControlSize		int8
} [packed]

uac3_as_out_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac3_iso_endpoint_descriptor]
} [packed]

uac3_as_in_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_IN_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac3_iso_endpoint_descriptor]
} [packed]

uac3_iso_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubType	const[UAC3_CS_ENDPOINT, int8]
	bmControls		int32
	bLockDelayUnits		int8
	wLockDelay		int16
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac3_control_iface_extra_descriptor [
	input_terminal		uac3_input_terminal_descriptor
	output_terminal		uac3_output_terminal_descriptor
	mixer_unit		uac3_mixer_unit_descriptor
	selector_unit		uac3_clock_selector_descriptor
	source_unit		uac3_clock_source_descriptor
	multiply_unit		uac3_clock_multiplier_descriptor
	feature_unit		uac3_feature_unit_descriptor
	processing_unit		uac3_processing_unit_descriptor
	extension_unit		uac3_extension_unit_descriptor
	power_domain		uac3_power_domain_descriptor
	cluster_info_segment	uac3_cluster_information_segment_descriptor
# Only cluster information segment is currently used in the kernel.See: sound/usb/stream.c
# cluster_segment 		uac3_cluster_segment_descriptor
# cluster_end_segment		uac3_cluster_end_segment_descriptor
# The following units are not yet supported by the kernel.
# See audio_validators[] in sound/usb/validate.c:
#	effect_unit 		uac3_effect_unit_descriptor
#	sample_rate			uac3_sample_rate_descriptor
#	connectors_unit		uac3_connectors_unit_descriptor
#	extended_term_unit	uac3_extended_terminal_unit
] [varlen]

uac3_input_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_INPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_input_terminal_types, int16]
	bAssocTerminal		uac_id
	bCSourceID		int8

	bmControls		int32
	wClusterDescrID		int16
	wExTerminalDescrID	int16
	wConnectorsDescrID	int16
	wTerminalDescrStr	int16
} [packed]

uac3_output_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_OUTPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_output_terminal_types, int16]
	bAssocTerminal		uac_id
	bSourceID		uac_id
	bCSourceID		int8

	bmControls		int32
	wExTerminalDescrID	int16
	wConnectorsDescrID	int16
	wTerminalDescrStr	int16
} [packed]

uac3_mixer_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_MIXER_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac3_clock_selector_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_CLOCK_SELECTOR, int8]
	bClockID		int8
	bNrInPins		len[baCSourceID, int8]
	baCSourceID		array[int8, 0:8]
} [packed]

uac3_clock_source_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_CLOCK_SOURCE, int8]
	bClockID		int8
	bmAttributes		flags[uac3_clock_bmattribute_types, int8]
	bmControls		int32
	bReferenceTerminal	int8
	wClockSourceStr		int16
} [packed]

uac3_clock_bmattribute_types = UAC3_CLOCK_SOURCE_TYPE_EXT, UAC3_CLOCK_SOURCE_TYPE_INT, UAC3_CLOCK_SOURCE_ASYNC, UAC3_CLOCK_SOURCE_SYNCED_TO_SOF

uac3_clock_multiplier_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_CLOCK_MULTIPLIER, int8]
	bClockID		int8
	bCSourceID		int8
	bmControls		int32
	wCMultiplierDescrStr	int16
} [packed]

uac3_feature_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC3_FEATURE_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac3_feature_unit_controls, int32], 1:6]
} [packed]

uac3_processing_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC3_PROCESSING_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac3_processing_unit_types, int32], 1:6]
} [packed]

uac3_processing_unit_types = UAC3_PROCESS_UNDEFINED, UAC3_PROCESS_UP_DOWNMIX, UAC3_PROCESS_STEREO_EXTENDER, UAC3_PROCESS_MULTI_FUNCTION

uac3_extension_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC3_EXTENSION_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac3_processing_unit_types, int32], 1:6]
} [packed]

uac3_power_domain_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_POWER_DOMAIN, int8]

	bPowerDomainID		int8
	waRecoveryTime1		int16
	waRecoveryTime2		int16
	bNrEntities		int8
	baEntityID		array[int8, 0:8]
} [packed]

uac3_cluster_information_segment_descriptor {
	bLength		len[parent, int16]
	bSegmentType	const[UAC3_CHANNEL_INFORMATION, int8]
	bChPurpose	flags[uac3_cluster_channel_purposes, int8]
	bChRelationship	flags[uac3_cluster_channel_relationships, int8]
	bChGroupID	int8
} [packed]

uac3_cluster_channel_purposes = UAC3_PURPOSE_UNDEFINED, UAC3_PURPOSE_GENERIC_AUDIO, UAC3_PURPOSE_VOICE, UAC3_PURPOSE_SPEECH, UAC3_PURPOSE_AMBIENT, UAC3_PURPOSE_REFERENCE, UAC3_PURPOSE_ULTRASONIC, UAC3_PURPOSE_VIBROKINETIC, UAC3_PURPOSE_NON_AUDIO
uac3_cluster_channel_relationships = UAC3_CH_RELATIONSHIP_UNDEFINED, UAC3_CH_MONO, UAC3_CH_LEFT, UAC3_CH_RIGHT, UAC3_CH_ARRAY, UAC3_CH_PATTERN_X, UAC3_CH_PATTERN_Y, UAC3_CH_PATTERN_A, UAC3_CH_PATTERN_B, UAC3_CH_PATTERN_M, UAC3_CH_PATTERN_S, UAC3_CH_FRONT_LEFT, UAC3_CH_FRONT_RIGHT, UAC3_CH_FRONT_CENTER, UAC3_CH_FRONT_LEFT_OF_CENTER, UAC3_CH_FRONT_RIGHT_OF_CENTER, UAC3_CH_FRONT_WIDE_LEFT, UAC3_CH_FRONT_WIDE_RIGHT, UAC3_CH_SIDE_LEFT, UAC3_CH_SIDE_RIGHT, UAC3_CH_SURROUND_ARRAY_LEFT, UAC3_CH_SURROUND_ARRAY_RIGHT, UAC3_CH_BACK_LEFT, UAC3_CH_BACK_RIGHT, UAC3_CH_BACK_CENTER, UAC3_CH_BACK_LEFT_OF_CENTER, UAC3_CH_BACK_RIGHT_OF_CENTER, UAC3_CH_BACK_WIDE_LEFT, UAC3_CH_BACK_WIDE_RIGHT, UAC3_CH_TOP_CENTER, UAC3_CH_TOP_FRONT_LEFT, UAC3_CH_TOP_FRONT_RIGHT, UAC3_CH_TOP_FRONT_CENTER, UAC3_CH_TOP_FRONT_LOC, UAC3_CH_TOP_FRONT_ROC, UAC3_CH_TOP_FRONT_WIDE_LEFT, UAC3_CH_TOP_FRONT_WIDE_RIGHT, UAC3_CH_TOP_SIDE_LEFT, UAC3_CH_TOP_SIDE_RIGHT, UAC3_CH_TOP_SURR_ARRAY_LEFT, UAC3_CH_TOP_SURR_ARRAY_RIGHT, UAC3_CH_TOP_BACK_LEFT, UAC3_CH_TOP_BACK_RIGHT, UAC3_CH_TOP_BACK_CENTER, UAC3_CH_TOP_BACK_LOC, UAC3_CH_TOP_BACK_ROC, UAC3_CH_TOP_BACK_WIDE_LEFT, UAC3_CH_TOP_BACK_WIDE_RIGHT, UAC3_CH_BOTTOM_CENTER, UAC3_CH_BOTTOM_FRONT_LEFT, UAC3_CH_BOTTOM_FRONT_RIGHT, UAC3_CH_BOTTOM_FRONT_CENTER, UAC3_CH_BOTTOM_FRONT_LOC, UAC3_CH_BOTTOM_FRONT_ROC, UAC3_CH_BOTTOM_FRONT_WIDE_LEFT, UAC3_CH_BOTTOM_FRONT_WIDE_RIGHT, UAC3_CH_BOTTOM_SIDE_LEFT, UAC3_CH_BOTTOM_SIDE_RIGHT, UAC3_CH_BOTTOM_SURR_ARRAY_LEFT, UAC3_CH_BOTTOM_SURR_ARRAY_RIGHT, UAC3_CH_BOTTOM_BACK_LEFT, UAC3_CH_BOTTOM_BACK_RIGHT, UAC3_CH_BOTTOM_BACK_CENTER, UAC3_CH_BOTTOM_BACK_LOC, UAC3_CH_BOTTOM_BACK_ROC, UAC3_CH_BOTTOM_BACK_WIDE_LEFT, UAC3_CH_BOTTOM_BACK_WIDE_RIGHT, UAC3_CH_LOW_FREQUENCY_EFFECTS, UAC3_CH_LFE_LEFT, UAC3_CH_LFE_RIGHT, UAC3_CH_HEADPHONE_LEFT, UAC3_CH_HEADPHONE_RIGHT

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# This list consists of uac3_func_subclasses + uac3_badd_classes.
uac3_all_subclasses = UAC3_FUNCTION_SUBCLASS_UNDEFINED, UAC3_FUNCTION_SUBCLASS_FULL_ADC_3_0, UAC3_FUNCTION_SUBCLASS_GENERIC_IO, UAC3_FUNCTION_SUBCLASS_HEADPHONE, UAC3_FUNCTION_SUBCLASS_SPEAKER, UAC3_FUNCTION_SUBCLASS_MICROPHONE, UAC3_FUNCTION_SUBCLASS_HEADSET, UAC3_FUNCTION_SUBCLASS_HEADSET_ADAPTER, UAC3_FUNCTION_SUBCLASS_SPEAKERPHONE

uac3_feature_unit_controls = UAC3_FUNCTION_SUBCLASS_UNDEFINED, UAC3_FUNCTION_DESKTOP_SPEAKER, UAC3_FUNCTION_HOME_THEATER, UAC3_FUNCTION_MICROPHONE, UAC3_FUNCTION_HEADSET, UAC3_FUNCTION_TELEPHONE, UAC3_FUNCTION_CONVERTER, UAC3_FUNCTION_SOUND_RECORDER, UAC3_FUNCTION_IO_BOX, UAC3_FUNCTION_MUSICAL_INSTRUMENT, UAC3_FUNCTION_PRO_AUDIO, UAC3_FUNCTION_AUDIO_VIDEO, UAC3_FUNCTION_CONTROL_PANEL, UAC3_FUNCTION_HEADPHONE, UAC3_FUNCTION_GENERIC_SPEAKER, UAC3_FUNCTION_HEADSET_ADAPTER, UAC3_FUNCTION_SPEAKERPHONE, UAC3_FUNCTION_OTHER

# TODO: Support uac3 badd profiles. See sound/usb/mixer.c: snd_usb_mixer_controls_badd()
# uac3_badd_endpoint_descriptor {
# 	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac3_iso_endpoint_descriptor]
# } [packed]

#uac3_badd_maxsizes = UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16,UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16,UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24,UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24,UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16,UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16,UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24,UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# MIDI device class specific descriptions.
# https://www.usb.org/sites/default/files/midi10.pdf
# https://elixir.bootlin.com/linux/latest/source/sound/usb/midi.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_midi.c

syz_usb_connect$midi(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_midi], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb (timeout[3000], prog_timeout[3000], remote_cover)

usb_device_descriptor_midi {
	inner	usb_device_descriptor_t[0, 0, 0, 0x1430, 0x474b, 64, array[usb_config_descriptor_midi, 1]]
} [packed]

usb_config_descriptor_midi {
	inner	usb_config_descriptor_t[const[1, int8], const[1, int8], usb_interface_descriptors_midi]
} [packed]

usb_interface_descriptors_midi {
	inner	usb_interface_descriptors_midi_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_midi_inner {
	control	usb_interface_descriptor_eps_array_t[const[0, int8], const[0, int8], const[USB_CLASS_AUDIO, int8], const[USB_SUBCLASS_MIDISTREAMING, int8], flags[uac_version_types, int8], array[usb_midi_iface_extra], array[usb_endpoint_descriptor_midi, 0:8]]
} [packed]

usb_endpoint_descriptor_midi {
	inner	usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], flags[usb_endpoint_attributes, int8], usb_ms_endpoint_descriptor]
} [packed]

midi_jack_type = USB_MS_EMBEDDED, USB_MS_EXTERNAL
uac_version_types = UAC_VERSION_1, UAC_VERSION_2, UAC_VERSION_3

usb_ms_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubType	const[USB_MS_GENERAL, int8]
	bNumEmbMIDIJack		len[baAssocJackID, int8]
	baAssocJackID		array[int8, 0:16]
} [packed]

usb_midi_iface_extra [
	ms_header	usb_ms_header_descriptor
	midi_in_jack	usb_midi_in_jack_descriptor
	midi_out_jack	usb_midi_out_jack_descriptor
] [varlen]

usb_ms_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_HEADER, int8]
	bcdMSC			int16
	wTotalLength		len[parent, int16]
} [packed]

usb_midi_in_jack_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIDI_IN_JACK, int8]
	bJackType		flags[midi_jack_type, int8]
	bJackID			int8
	iJack			int8
} [packed]

usb_midi_out_jack_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIDI_OUT_JACK, int8]
	bJackType		flags[midi_jack_type, int8]
	bJackID			int8
	bNrInputPins		len[pins, int8]
	pins			array[usb_midi_source_pin]
	iJack			int8
} [packed]

usb_midi_source_pin {
	baSourceID	int8
	baSourcePin	int8
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# ath9k driver specific descriptions.

include <drivers/net/wireless/ath/ath9k/htc_hst.h>
include <drivers/net/wireless/ath/ath9k/hif_usb.h>

define USB_ENDPOINT_ATH9K_BULK_OUT_ADDRESS	(1)
define USB_ENDPOINT_ATH9K_BULK_IN_ADDRESS	(2 | USB_DIR_IN)
define USB_ENDPOINT_ATH9K_INT_IN_ADDRESS	(3 | USB_DIR_IN)
define USB_ENDPOINT_ATH9K_INT_OUT_ADDRESS	(4)
define USB_ENDPOINT_ATH9K_BULK_EXTRA1_ADDRESS	(5)
define USB_ENDPOINT_ATH9K_BULK_EXTRA2_ADDRESS	(6)

resource fd_usb_ath9k[fd_usb]

syz_usb_connect_ath9k(speed const[USB_SPEED_HIGH], dev_len len[dev], dev ptr[in, usb_device_descriptor_ath9k], conn_descs const[0]) fd_usb_ath9k (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_ep_write$ath9k_ep1(fd fd_usb_ath9k, ep const[USB_ENDPOINT_ATH9K_BULK_IN_ADDRESS], len bytesize[data], data ptr[in, ath9k_bulk_frame]) (timeout[300], remote_cover)
syz_usb_ep_write$ath9k_ep2(fd fd_usb_ath9k, ep const[USB_ENDPOINT_ATH9K_INT_IN_ADDRESS], len bytesize[data], data ptr[in, htc_frame]) (timeout[300], remote_cover)

usb_device_descriptor_ath9k {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0xcf3, 0x9271, 0x108, array[usb_config_descriptor_ath9k, 1]]
} [packed]

usb_config_descriptor_ath9k {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_ath9k]
} [packed]

usb_interface_descriptor_ath9k {
	iface	usb_interface_descriptor_fixed_t[0, 0, 6, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_ath9k]
} [packed]

usb_endpoint_descriptors_ath9k {
	bulk_out	usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_OUT_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
	bulk_in		usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_IN_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
	int_in		usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_INT_IN_ADDRESS, USB_ENDPOINT_ATH9K_INT_ATTRIBUTES, 64, 1, void]
	int_out		usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_INT_OUT_ADDRESS, USB_ENDPOINT_ATH9K_INT_ATTRIBUTES, 64, 1, void]
	bulk_extra1	usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_EXTRA1_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
	bulk_extra2	usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_EXTRA2_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
} [packed]

define USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_ATH9K_INT_ATTRIBUTES	(USB_ENDPOINT_XFER_INT)

ath9k_bulk_frame {
	packets	array[ath9k_bulk_packet]
} [packed]

ath9k_bulk_packet {
	pkt_len	len[data, int16]
	pkt_tag	const[ATH_USB_RX_STREAM_MODE_TAG, int16]
	data	array[int8]
} [packed, align[4]]

htc_frame [
	ready		htc_ready_frame
	conn_svc_rsp	htc_conn_svc_rsp_frame
	generic		htc_generic_frame
] [varlen]

# This is actually wrong, as the driver is buggy and doesn't skip the header
# before processing the frame payload, but let's leave it like thise for now.
htc_ready_frame {
	endpoint_id	const[0, int8]
	flags		const[0, int8]
	payload_len	len[payload, int16be]
	control		array[int8, 4]
	payload		htc_ready_msg
} [packed]

htc_ready_msg {
	message_id	const[HTC_MSG_READY_ID, int16be]
	credits		int16be
	credit_size	int16be
	max_endpoints	int8
	pad		int8
} [packed]

htc_conn_svc_rsp_frame {
	endpoint_id	const[0, int8]
	flags		const[0, int8]
	payload_len	len[payload, int16be]
	control		array[int8, 4]
	payload		htc_conn_svc_rspmsg
} [packed]

htc_conn_svc_rspmsg {
	message_id	const[HTC_MSG_CONNECT_SERVICE_RESPONSE_ID, int16be]
	service_id	flags[htc_svcs, int16be]
	status		const[HTC_SERVICE_SUCCESS, int8]
	endpoint_id	int8
	max_msg_len	int16be
	svc_meta_len	int8
	pad		int8
} [packed]

htc_svcs = HTC_CTRL_RSVD_SVC, HTC_LOOPBACK_RSVD_SVC, WMI_CONTROL_SVC, WMI_BEACON_SVC, WMI_CAB_SVC, WMI_UAPSD_SVC, WMI_MGMT_SVC, WMI_DATA_VO_SVC, WMI_DATA_VI_SVC, WMI_DATA_BE_SVC, WMI_DATA_BE_SVC

htc_generic_frame {
	endpoint_id	int8[0:8]
	flags		flags[htc_frame_flags, int8]
	payload_len	len[payload, int16be]
	control		array[int8, 4]
	payload		array[int8, 0:256]
} [packed]

htc_frame_flags = HTC_FLAGS_RECV_TRAILER

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Assorted driver-specific descriptions of generic syz_* calls' variants.

# Generic calls such as syz_usb_connect() and syz_usb_control_io() should be enough
# (in theory) to emulate a proper device and finish driver probes without a hitch.
# However, there are cases when syzkaller fails to come up with correct inputs to achieve it.
# Use fixed descriptors to quickly pass through probe() to access select drivers' post-probe functionality.

# It is important to note that, one way or another, drivers in question require multiple control requests
# between a driver and a device processed during probe(). Descriptions below do not deal with specific
# CTRL requests as such (except for basic information included in vusb_responses_XXX). Instead, rely on
# seeds, created both manually and with syzkaller's help. For examples, see sys/linux/test/vusb_XXX.

# Common constants for endpoint descriptors.
define USB_ENDPOINT_BULK_ATTR	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_INT_ATTR	(USB_ENDPOINT_XFER_INT)

define USB_FIXED_ENDPOINT_BULK_IN_ADDR	(1 | USB_DIR_IN)
define USB_FIXED_ENDPOINT_BULK_OUT_ADDR	(2)
define USB_FIXED_ENDPOINT_INT_IN_ADDR	(3 | USB_DIR_IN)

define USB_RECIP_DEVICE	0x00

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# rtl8150 driver specific descriptions.

resource fd_usb_rtl8150[fd_usb]

syz_usb_connect$rtl8150(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_rtl8150], conn_descs const[0]) fd_usb_rtl8150 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$rtl8150(fd fd_usb_rtl8150, descs ptr[in, vusb_descriptors_rtl8150], resps ptr[in, vusb_responses_rtl8150]) (timeout[300], remote_cover)

usb_device_descriptor_rtl8150 {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0xbda, 0x8150, 0, array[usb_config_descriptor_rtl8150, 1]]
} [packed]

usb_config_descriptor_rtl8150 {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_rtl8150]
} [packed]

usb_interface_descriptor_rtl8150 {
	iface	usb_interface_descriptor_fixed_t[0, 0, 3, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_rtl8150]
} [packed]

usb_endpoint_descriptors_rtl8150 {
	bulk_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_IN_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	bulk_out	usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_OUT_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	int_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_INT_IN_ADDR, USB_ENDPOINT_INT_ATTR, 64, 1, void]
} [packed]

vusb_descriptors_rtl8150 {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_rtl8150 {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	RTL8150_REQ_GET_REGS		ptr[in, vusb_response_t[RTL8150_REQT_READ, RTL8150_REQ_GET_REGS, array[int8, 0:6]]]
	RTL8150_REQ_SET_REGS		ptr[in, vusb_response_t[RTL8150_REQT_WRITE, RTL8150_REQ_SET_REGS, array[int8, 0:6]]]
} [packed]

define RTL8150_REQ_GET_REGS	0x05
define RTL8150_REQ_SET_REGS	0x05
define RTL8150_REQT_READ	0xc0
define RTL8150_REQT_WRITE	0x40

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# sierra_net driver specific descriptions.

resource fd_usb_sierra_net[fd_usb]

syz_usb_connect$sierra_net(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_sierra_net], conn_descs const[0]) fd_usb_sierra_net (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$sierra_net(fd fd_usb_sierra_net, descs ptr[in, vusb_descriptors_sierra_net], resps ptr[in, vusb_responses_sierra_net]) (timeout[300], remote_cover)

usb_device_descriptor_sierra_net {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0x1199, 0x68a3, 0, array[usb_config_descriptor_sierra_net, 1]]
} [packed]

usb_config_descriptor_sierra_net {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_sierra_net]
} [packed]

usb_interface_descriptor_sierra_net {
	iface	usb_interface_descriptor_fixed_t[7, 0, 3, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_sierra_net]
} [packed]

# sierra_net driver does not expect fixed ep addresses, so refrain from being too specific here.
# As long as we ensure there are 3 endpoints, 2 bulk and 1 int, syzkaller should figure it out.
usb_endpoint_descriptors_sierra_net {
	bulk_in		usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], const[USB_ENDPOINT_BULK_ATTR, int8], void]
	bulk_out	usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], const[USB_ENDPOINT_BULK_ATTR, int8], void]
	status		usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], const[USB_ENDPOINT_INT_ATTR, int8], void]
} [packed]

vusb_descriptors_sierra_net {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_sierra_net {
	len					len[parent, int32]
	generic					ptr[in, vusb_response_generic]

	USB_CDC_GET_ENCAPSULATED_RESPONSE	ptr[in, vusb_response_t[SIERRA_CMD_TYPE_IN, USB_CDC_GET_ENCAPSULATED_RESPONSE, array[int8, 1024]]]
	USB_CDC_SEND_ENCAPSULATED_COMMANDT	ptr[in, vusb_response_t[SIERRA_CMD_TYPE_OUT, USB_CDC_SEND_ENCAPSULATED_COMMAND, array[int8, 0:4]]]
} [packed]

define SIERRA_CMD_TYPE_IN	(USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)
define SIERRA_CMD_TYPE_OUT	(USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# lan78xx driver specific descriptions.
# While these syz_* variants noticably help with the probe() process, they are not enough.
# This is due to a high number of control requests expected between the driver and the device.

include <drivers/net/usb/smsc95xx.h>

resource fd_usb_lan78xx[fd_usb]

syz_usb_connect$lan78xx(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_lan78xx], conn_descs const[0]) fd_usb_lan78xx (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$lan78xx(fd fd_usb_lan78xx, descs ptr[in, vusb_descriptors_lan78xx], resps ptr[in, vusb_responses_lan78xx]) (timeout[300], remote_cover)

usb_device_descriptor_lan78xx {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0x424, 0x7850, 0, array[usb_config_descriptor_lan78xx, 1]]
} [packed]

usb_config_descriptor_lan78xx {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_lan78xx]
} [packed]

usb_interface_descriptor_lan78xx {
	iface	usb_interface_descriptor_fixed_t[0, 0, 3, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_lan78xx]
} [packed]

usb_endpoint_descriptors_lan78xx {
	bulk_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_IN_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	bulk_out	usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_OUT_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	int_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_INT_IN_ADDR, USB_ENDPOINT_INT_ATTR, 64, 1, void]
} [packed]

vusb_descriptors_lan78xx {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_lan78xx {
	len					len[parent, int32]
	generic					ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE			ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	USB_VENDOR_REQUEST_READ_REGISTER	ptr[in, vusb_response_t[LAN78XX_REG_TYPE_IN, USB_VENDOR_REQUEST_READ_REGISTER, int32]]
	USB_VENDOR_REQUEST_WRITE_REGISTER	ptr[in, vusb_response_t[LAN78XX_REG_TYPE_OUT, USB_VENDOR_REQUEST_WRITE_REGISTER, int32]]
	USB_VENDOR_REQUEST_GET_STATS		ptr[in, vusb_response_t[LAN78XX_REG_TYPE_IN, USB_VENDOR_REQUEST_GET_STATS, array[int8, 47]]]
} [packed]

define LAN78XX_REG_TYPE_IN	(USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
define LAN78XX_REG_TYPE_OUT	(USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
]

112/2 2026/07/30 12:29 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 83035
							output: 1292
							thoughts: 2179
						

Thoughts:
**Navigating the `syz_usb_connect` Challenge**

Okay, so I'm trying to work with `syz_usb_connect`, and the first thing that jumps out is the `dev ptr[in, usb_device_descriptor]` argument. Right, it's a struct, not just a string, so I can't simply pass in raw bytes as I initially thought. But wait, checking the vusb.txt definition, I see this third argument is indeed a `usb_device_descriptor`, confirming that it needs a structured input, not just a bare string literal like `&AUTO="\x12\x01..."`. 

So, I need to figure out how to give this pseudo-syscall the structure it expects.  Using `&AUTO=""` doesn't work directly because of the type mismatch.  And `&AUTO=""/43` doesn't seem right either. The best approach is clearly to construct the struct using `&AUTO={...}`. The tricky part is the manual construction of the complex `usb_device_descriptor` struct.

While `syz_usb_connect` is pseudo-syscall, I can see the advantage of pre-populating memory. So, could I just use `syz_usb_connect(3, 0x2b, &(0x7f0000000000)="", 0)`? No, that still presents it as a string. Syzkaller needs raw bytes for the struct. But is it even possible to just write bytes directly to a memory location and then pass a pointer?  Can I just use `&AUTO={{0x12, 0x1, 0x200, 0, 0, 0, 0x40, 0x2040, 0x7200, 0, 1, 2, 3, 1, ...}}`? But this seems so cumbersome.

Okay, let's explore if I can just write raw bytes somewhere in memory and then pass a pointer to `syz_usb_connect`.  I can't directly use a `memcpy` in syzkaller.  But can I use write syscall for that purpose? I could try: `write(-1, &(0x7f0000000000)="1201...", 43)`.

However, the problem is that when I call syz_usb_connect, if I just pass a pointer, `syzkaller` will try to fill the `usb_device_descriptor` struct at that address, overwriting my carefully crafted bytes! So I need some way to tell `syzkaller` to just use the bytes at the location, not initialize it with default values.

Aha! `syzkaller` initializes memory for pointers before the program runs. So, if I use `&(0x7f0000000000)={...}`, it will initialize. And maybe if I use `&(0x7f0000000000)=ANY` it will work?  But `ANY` is only for `ptr[in, ANY]`. Ah, but I can use a hex string to give `syzkaller` my raw bytes! Based on the documentation `pointer-arg = "&" pointer-arg-addr ["=ANY"] "=" arg` and `arg` can be a hex string. So:  `&(0x7f0000000000)=ANY="1201000200000040402000720000010203010902190001010080fa0904000001ff00000007058102000200"`. Let's test that!



113/2 2026/07/30 12:29 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0x2b, &(0x7f0000000000)=ANY="1201000200000040402000720000010203010902190001010080fa0904000001ff00000007058102000200", 0)
r1 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r2 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r3 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r4 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r5 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r6 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
r7 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r8 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r9 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r10 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r11 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r12 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
r13 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r14 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r15 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r16 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r17 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r18 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r3, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r4, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r9, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r10, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r11, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r12, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r15, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r16, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r17, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r18, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

114/2 2026/07/30 12:29 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 87516
							output: 40
							thoughts: 151
						

Thoughts:
**Debugging a String Argument for syz_usb_connect**

Okay, here we go again, encountering this pesky "`wrong string arg`" error. I need to figure out what's causing this. Let's start by double-checking the documentation for `ANY`. Right, it shows `pointer-arg = "&" pointer-arg-addr ["=ANY"] "=" arg`. I remember now, if the argument, `arg`, is a string, then it should be formatted as `&AUTO=ANY="..."`. But hang on, `syz_usb_connect` takes `dev ptr[in, usb_device_descriptor]`. Does using `ANY` mean it's expecting a hex string? I'm pretty sure that's how it works.

I should probably confirm that with some examples. The best approach is to check how `syz_usb_connect` is currently used in the syzkaller tests themselves. I'll fire up `git log` and search for usages of `syz_usb_connect` within the `sys/linux/test/` directory. That'll give me some real-world examples to see how this function is correctly invoked and what its arguments should look like. That'll give me the best clue to solve this issue.



115/2 2026/07/30 12:29 tool git-log
0m Args:
map[CodeRegexp:syz_usb_connect Count:10 PathPrefix:sys/linux/test/]

Results:
map[Output:]

116/2 2026/07/30 12:29 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 87990
							output: 1461
							thoughts: 3637
						

Thoughts:
**Constructing a USB Device Descriptor in Syzkaller**

Okay, first things first, I need to remember that the `sys/linux/test/` directory isn't in the kernel tree, it's actually in the syzkaller tree. And since I don't have direct access to that syzkaller tree, I'll have to build this descriptor from scratch. Good, I can do this. I've got a grasp of the `usb_device_descriptor` structure. I need to make sure the nested structures, especially `usb_config_descriptor`, `usb_interface_descriptor` and `usb_endpoint_descriptor` are correct.

Let's break it down. I've reconstructed the `usb_device_descriptor` from its definitions. Now, I need to build the struct literal.  I see how the descriptors chain together.  There is the initial `usb_device_descriptor`, which contains `usb_config_descriptor`. The `usb_config_descriptor` contains `usb_interface_descriptor` and the  `usb_interface_descriptor` contains  `usb_endpoint_descriptor`. I've got the hierarchy laid out.

I need to handle `void` fields in `usb_config_descriptor`. Ah, right, in syzkaller, `void` fields are omitted from struct literals, so I won't need to specify anything there. The `extra` field of the other descriptors is defined as array, and the array can be empty, which is how I need to treat it.

Okay, let's try using `AUTO` for the `const` and `len` fields.  The problem is, `idVendor` and `idProduct` are defined as `const`. My initial struct construct will probably set them to something different from what I want. They might get overwritten by syzkaller's patching, so I can try leaving them, but I need a way to ensure these values are what I need.

And then I read the comment. `idVendor` and `idProduct` are actually patched by the Go code in `sys/linux/init_vusb.go`. Alright, so syzkaller *does* patch them, which means trying to set them directly via the struct definition isn't the best way. I should be able to force it by using `ANY`. I remember that if I use `ANY`, I can pass raw bytes to the program. Let me try it.



117/2 2026/07/30 12:30 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0x2b, &(0x7f0000000000)=ANY=[0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x40, 0x20, 0x00, 0x72, 0x00, 0x00, 0x01, 0x02, 0x03, 0x01, 0x09, 0x02, 0x19, 0x00, 0x01, 0x01, 0x00, 0x80, 0xfa, 0x09, 0x04, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 0x00, 0x02, 0x00], 0)
r1 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r2 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r3 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r4 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r5 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r6 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
r7 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r8 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r9 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r10 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r11 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r12 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
r13 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r14 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r15 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r16 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r17 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r18 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r3, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r4, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r9, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r10, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r11, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r12, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r15, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r16, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r17, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r18, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

118/2 2026/07/30 12:30 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 93934
							output: 20
							thoughts: 1628
						

Thoughts:
**Navigating the USB and I2C Labyrinth**

Okay, so I'm trying to figure out how to trigger this bug, and it's sending me down a rabbit hole. I initially thought this had something to do with the `ANY` type, trying to feed it a union or struct. But after looking at the "wrong string arg" error, I think the `ANY` type expects a struct. I tried to use a struct literal, but I am not certain if it is the correct one.

I then started to focus on the `au0828` USB device and `syz_usb_connect`.  I quickly realized that while I could use `&AUTO=""` for auto-populating the struct, there are `const` fields that syzkaller will reject unless they are zero or `AUTO`.  The Go code *does* patch these fields, but I need to figure out how syzkaller knows which vendor/product IDs to use, because if they are not the same, I am not emulating the correct USB device. I see that syzkaller randomly patches them to known USB IDs. And if `au0828` isn't in that list, I'm out of luck. This also means I cannot easily use `syz_usb_connect` to trigger the bug. I also see that there are different variants of this system call, but none that look like they specifically target `au0828`.

So, if I can't directly emulate the device with `syz_usb_connect`, how was the bug triggered? The crash report points to `nsim_dev_trap_skb_build` which belongs to `netdevsim` and then a UAF in `i2c_adapter_lock_bus`. I remember that the error message shows the buggy object is `kmalloc-4k`. That makes me think a `struct usb_device` *could* be the problem because it's roughly 2251 bytes, which would fit in `kmalloc-4k`.

But wait, this could be something else entirely! If the crash is in `i2c_adapter_lock_bus`, which is called from `i2c_smbus_xfer`, and the UAF is on `adapter->dev.parent`, I have to figure out what driver registers an I2C adapter with `dev.parent` pointing to a `kmalloc-4k` object. `netdevsim` *allocates* a `kmalloc-4k` object, but it does *not* register I2C adapters. So, this looks like a reallocation scenario. The original object was freed, then `netdevsim` allocated an `skb` in the same `kmalloc-4k` slot and freed it. That means the original object was freed *before* `netdevsim` came into play.

If the original object was a `kmalloc-4k` object, it *could* be a `struct usb_device`, but it could be something else. What other drivers use I2C and could have a `kmalloc-4k` object as `parent`?  Could it be a `struct net_device`? `net_device` is allocated via `alloc_netdev`, which uses `kvmalloc`, which often ends up in `kmalloc-4k`. Aha! Are there any network drivers that register I2C adapters? It makes me think SFP modules or PHYs.

I have to wonder if a network device registers an I2C adapter, and then the netdev is unregistered and freed, but the I2C adapter is *not* unregistered.  I'll have to investigate if any network drivers register I2C adapters. I'll need to check the code, maybe in `drivers/net/ethernet/mellanox/mlx5/core/en_main.c` or in `drivers/net/usb/`. Is it a `struct usb_interface`, `struct v4l2_device`, `struct i2c_client`, or `struct platform_device`? I'll search for `i2c_add_adapter` or `i2c_add_numbered_adapter` where `dev.parent` is set to figure this out.



119/2 2026/07/30 12:30 tool grepper
0m Args:
map[Expression:adapter\.dev\.parent =]

Results:
map[Output:drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c=160=struct amdgpu_i2c_chan *amdgpu_i2c_create(struct drm_device *dev,
--
drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c-176-	i2c->adapter.owner = THIS_MODULE;
drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c:177:	i2c->adapter.dev.parent = dev->dev;
drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c-178-	i2c->dev = dev;
--
drivers/gpu/drm/gma500/cdv_intel_dp.c=845=cdv_intel_dp_i2c_init(struct gma_connector *connector,
--
drivers/gpu/drm/gma500/cdv_intel_dp.c-860-	intel_dp->adapter.algo_data = &intel_dp->algo;
drivers/gpu/drm/gma500/cdv_intel_dp.c:861:	intel_dp->adapter.dev.parent = connector->base.kdev;
drivers/gpu/drm/gma500/cdv_intel_dp.c-862-
--
drivers/gpu/drm/gma500/intel_gmbus.c=173=intel_gpio_create(struct drm_psb_private *dev_priv, u32 pin)
--
drivers/gpu/drm/gma500/intel_gmbus.c-200-	gpio->adapter.algo_data	= &gpio->algo;
drivers/gpu/drm/gma500/intel_gmbus.c:201:	gpio->adapter.dev.parent = dev_priv->dev.dev;
drivers/gpu/drm/gma500/intel_gmbus.c-202-	gpio->algo.setsda = set_data;
--
drivers/gpu/drm/gma500/intel_gmbus.c=387=int gma_intel_setup_gmbus(struct drm_device *dev)
--
drivers/gpu/drm/gma500/intel_gmbus.c-419-
drivers/gpu/drm/gma500/intel_gmbus.c:420:		bus->adapter.dev.parent = dev->dev;
drivers/gpu/drm/gma500/intel_gmbus.c-421-		bus->adapter.algo_data	= dev_priv;
--
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c=80=int hibmc_ddc_create(struct drm_device *drm_dev, struct hibmc_vdac *vdac)
--
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c-83-	snprintf(vdac->adapter.name, I2C_NAME_SIZE, "HIS i2c bit bus");
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c:84:	vdac->adapter.dev.parent = drm_dev->dev;
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c-85-	i2c_set_adapdata(&vdac->adapter, vdac);
--
drivers/gpu/drm/i915/display/intel_gmbus.c=903=int intel_gmbus_setup(struct intel_display *display)
--
drivers/gpu/drm/i915/display/intel_gmbus.c-939-
drivers/gpu/drm/i915/display/intel_gmbus.c:940:		bus->adapter.dev.parent = &pdev->dev;
drivers/gpu/drm/i915/display/intel_gmbus.c-941-		bus->display = display;
--
drivers/gpu/drm/radeon/radeon_i2c.c=903=struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
--
drivers/gpu/drm/radeon/radeon_i2c.c-920-	i2c->adapter.owner = THIS_MODULE;
drivers/gpu/drm/radeon/radeon_i2c.c:921:	i2c->adapter.dev.parent = dev->dev;
drivers/gpu/drm/radeon/radeon_i2c.c-922-	i2c->dev = dev;
--
drivers/hid/hid-mcp2221.c=1237=static int mcp2221_probe(struct hid_device *hdev,
--
drivers/hid/hid-mcp2221.c-1299-	mcp->adapter.retries = 1;
drivers/hid/hid-mcp2221.c:1300:	mcp->adapter.dev.parent = &hdev->dev;
drivers/hid/hid-mcp2221.c-1301-	ACPI_COMPANION_SET(&mcp->adapter.dev, ACPI_COMPANION(hdev->dev.parent));
--
drivers/i2c/busses/i2c-ali1535.c=486=static int ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id)
--
drivers/i2c/busses/i2c-ali1535.c-496-	/* set up the sysfs linkage to our parent device */
drivers/i2c/busses/i2c-ali1535.c:497:	ali1535_adapter.dev.parent = &dev->dev;
drivers/i2c/busses/i2c-ali1535.c-498-
--
drivers/i2c/busses/i2c-ali1563.c=396=static int ali1563_probe(struct pci_dev *dev,
--
drivers/i2c/busses/i2c-ali1563.c-403-		goto exit;
drivers/i2c/busses/i2c-ali1563.c:404:	ali1563_adapter.dev.parent = &dev->dev;
drivers/i2c/busses/i2c-ali1563.c-405-	snprintf(ali1563_adapter.name, sizeof(ali1563_adapter.name),
--
drivers/i2c/busses/i2c-ali15x3.c=473=static int ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
--
drivers/i2c/busses/i2c-ali15x3.c-483-	/* set up the sysfs linkage to our parent device */
drivers/i2c/busses/i2c-ali15x3.c:484:	ali15x3_adapter.dev.parent = &dev->dev;
drivers/i2c/busses/i2c-ali15x3.c-485-
--
drivers/i2c/busses/i2c-altera.c=383=static int altr_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-altera.c-452-	idev->adapter.algo = &altr_i2c_algo;
drivers/i2c/busses/i2c-altera.c:453:	idev->adapter.dev.parent = &pdev->dev;
drivers/i2c/busses/i2c-altera.c-454-	idev->adapter.dev.of_node = pdev->dev.of_node;
--
drivers/i2c/busses/i2c-amd8111.c=422=static int amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id)
--
drivers/i2c/busses/i2c-amd8111.c-452-	/* set up the sysfs linkage to our parent device */
drivers/i2c/busses/i2c-amd8111.c:453:	smbus->adapter.dev.parent = &dev->dev;
drivers/i2c/busses/i2c-amd8111.c-454-
--
drivers/i2c/busses/i2c-at91-core.c=196=static int at91_twi_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-at91-core.c-232-	dev->adapter.class = I2C_CLASS_DEPRECATED;
drivers/i2c/busses/i2c-at91-core.c:233:	dev->adapter.dev.parent = dev->dev;
drivers/i2c/busses/i2c-at91-core.c-234-	dev->adapter.nr = pdev->id;
--
drivers/i2c/busses/i2c-axxia.c=720=static int axxia_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-axxia.c-777-	idev->adapter.quirks = &axxia_i2c_quirks;
drivers/i2c/busses/i2c-axxia.c:778:	idev->adapter.dev.parent = &pdev->dev;
drivers/i2c/busses/i2c-axxia.c-779-	idev->adapter.dev.of_node = pdev->dev.of_node;
--
drivers/i2c/busses/i2c-cht-wc.c=426=static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-cht-wc.c-451-		sizeof(adap->adapter.name));
drivers/i2c/busses/i2c-cht-wc.c:452:	adap->adapter.dev.parent = &pdev->dev;
drivers/i2c/busses/i2c-cht-wc.c-453-
--
drivers/i2c/busses/i2c-diolan-u2c.c=430=static int diolan_u2c_probe(struct usb_interface *interface,
--
drivers/i2c/busses/i2c-diolan-u2c.c-464-
drivers/i2c/busses/i2c-diolan-u2c.c:465:	dev->adapter.dev.parent = &dev->interface->dev;
drivers/i2c/busses/i2c-diolan-u2c.c-466-
--
drivers/i2c/busses/i2c-dln2.c=187=static int dln2_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-dln2.c-209-	dln2->adapter.quirks = &dln2_i2c_quirks;
drivers/i2c/busses/i2c-dln2.c:210:	dln2->adapter.dev.parent = dev;
drivers/i2c/busses/i2c-dln2.c-211-	ACPI_COMPANION_SET(&dln2->adapter.dev, ACPI_COMPANION(&pdev->dev));
--
drivers/i2c/busses/i2c-fsi.c=677=static int fsi_i2c_probe(struct fsi_device *fsi_dev)
--
drivers/i2c/busses/i2c-fsi.c-720-		port->adapter.dev.of_node = np;
drivers/i2c/busses/i2c-fsi.c:721:		port->adapter.dev.parent = dev;
drivers/i2c/busses/i2c-fsi.c-722-		port->adapter.algo = &fsi_i2c_algorithm;
--
drivers/i2c/busses/i2c-i801.c=1537=static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
--
drivers/i2c/busses/i2c-i801.c-1549-	priv->adapter.algo = &smbus_algorithm;
drivers/i2c/busses/i2c-i801.c:1550:	priv->adapter.dev.parent = &dev->dev;
drivers/i2c/busses/i2c-i801.c-1551-	acpi_use_parent_companion(&priv->adapter.dev);
--
drivers/i2c/busses/i2c-icy.c=121=static int icy_probe(struct zorro_dev *z,
--
drivers/i2c/busses/i2c-icy.c-139-	dev_set_drvdata(&z->dev, i2c);
drivers/i2c/busses/i2c-icy.c:140:	i2c->adapter.dev.parent = &z->dev;
drivers/i2c/busses/i2c-icy.c-141-	i2c->adapter.owner = THIS_MODULE;
--
drivers/i2c/busses/i2c-isch.c=274=static int smbus_sch_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-isch.c-292-	/* Set up the sysfs linkage to our parent device */
drivers/i2c/busses/i2c-isch.c:293:	priv->adapter.dev.parent = dev;
drivers/i2c/busses/i2c-isch.c-294-	priv->adapter.owner = THIS_MODULE;
--
drivers/i2c/busses/i2c-ismt.c=883=ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id)
--
drivers/i2c/busses/i2c-ismt.c-898-	priv->adapter.algo = &smbus_algorithm;
drivers/i2c/busses/i2c-ismt.c:899:	priv->adapter.dev.parent = &pdev->dev;
drivers/i2c/busses/i2c-ismt.c-900-	ACPI_COMPANION_SET(&priv->adapter.dev, ACPI_COMPANION(&pdev->dev));
--
drivers/i2c/busses/i2c-microchip-corei2c.c=538=static int mchp_corei2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-microchip-corei2c.c-602-	idev->adapter.algo = &mchp_corei2c_algo;
drivers/i2c/busses/i2c-microchip-corei2c.c:603:	idev->adapter.dev.parent = &pdev->dev;
drivers/i2c/busses/i2c-microchip-corei2c.c-604-	idev->adapter.dev.of_node = pdev->dev.of_node;
--
drivers/i2c/busses/i2c-mv64xxx.c=977=mv64xxx_i2c_probe(struct platform_device *pd)
--
drivers/i2c/busses/i2c-mv64xxx.c-1035-
drivers/i2c/busses/i2c-mv64xxx.c:1036:	drv_data->adapter.dev.parent = &pd->dev;
drivers/i2c/busses/i2c-mv64xxx.c-1037-	drv_data->adapter.algo = &mv64xxx_i2c_algo;
--
drivers/i2c/busses/i2c-nct6694.c=145=static int nct6694_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-nct6694.c-175-	data->adapter.quirks = &nct6694_i2c_quirks;
drivers/i2c/busses/i2c-nct6694.c:176:	data->adapter.dev.parent = dev;
drivers/i2c/busses/i2c-nct6694.c-177-	data->adapter.algo_data = data;
--
drivers/i2c/busses/i2c-nforce2.c=304=static int nforce2_probe_smb(struct pci_dev *dev, int bar, int alt_reg,
--
drivers/i2c/busses/i2c-nforce2.c-340-	smbus->adapter.algo_data = smbus;
drivers/i2c/busses/i2c-nforce2.c:341:	smbus->adapter.dev.parent = &dev->dev;
drivers/i2c/busses/i2c-nforce2.c-342-	snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
--
drivers/i2c/busses/i2c-nvidia-gpu.c=272=static int gpu_i2c_probe(struct pci_dev *pdev, const struct pci_device_id *id)
--
drivers/i2c/busses/i2c-nvidia-gpu.c-306-	i2cd->adapter.quirks = &gpu_i2c_quirks;
drivers/i2c/busses/i2c-nvidia-gpu.c:307:	i2cd->adapter.dev.parent = dev;
drivers/i2c/busses/i2c-nvidia-gpu.c-308-	status = i2c_add_adapter(&i2cd->adapter);
--
drivers/i2c/busses/i2c-parport.c=264=static void i2c_parport_attach(struct parport *port)
--
drivers/i2c/busses/i2c-parport.c-320-	adapter->adapter.algo_data = &adapter->algo_data;
drivers/i2c/busses/i2c-parport.c:321:	adapter->adapter.dev.parent = port->physport->dev;
drivers/i2c/busses/i2c-parport.c-322-
--
drivers/i2c/busses/i2c-pasemi-core.c=423=int pasemi_i2c_common_probe(struct pasemi_smbus *smbus)
--
drivers/i2c/busses/i2c-pasemi-core.c-433-	/* set up the sysfs linkage to our parent device */
drivers/i2c/busses/i2c-pasemi-core.c:434:	smbus->adapter.dev.parent = smbus->dev;
drivers/i2c/busses/i2c-pasemi-core.c-435-	smbus->use_irq = 0;
--
drivers/i2c/busses/i2c-pnx.c=607=static int i2c_pnx_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-pnx.c-621-
drivers/i2c/busses/i2c-pnx.c:622:	alg_data->adapter.dev.parent = &pdev->dev;
drivers/i2c/busses/i2c-pnx.c-623-	alg_data->adapter.algo = &pnx_algorithm;
--
drivers/i2c/busses/i2c-scmi.c=356=static int smbus_cmi_probe(struct platform_device *device)
--
drivers/i2c/busses/i2c-scmi.c-388-	smbus_cmi->adapter.class = I2C_CLASS_HWMON;
drivers/i2c/busses/i2c-scmi.c:389:	smbus_cmi->adapter.dev.parent = &device->dev;
drivers/i2c/busses/i2c-scmi.c-390-
--
drivers/i2c/busses/i2c-sis5595.c=367=static int sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id)
--
drivers/i2c/busses/i2c-sis5595.c-376-	/* set up the sysfs linkage to our parent device */
drivers/i2c/busses/i2c-sis5595.c:377:	sis5595_adapter.dev.parent = &dev->dev;
drivers/i2c/busses/i2c-sis5595.c-378-
--
drivers/i2c/busses/i2c-sis630.c=508=static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
--
drivers/i2c/busses/i2c-sis630.c-516-	/* set up the sysfs linkage to our parent device */
drivers/i2c/busses/i2c-sis630.c:517:	sis630_adapter.dev.parent = &dev->dev;
drivers/i2c/busses/i2c-sis630.c-518-
--
drivers/i2c/busses/i2c-sis96x.c=242=static int sis96x_probe(struct pci_dev *dev,
--
drivers/i2c/busses/i2c-sis96x.c-279-	/* set up the sysfs linkage to our parent device */
drivers/i2c/busses/i2c-sis96x.c:280:	sis96x_adapter.dev.parent = &dev->dev;
drivers/i2c/busses/i2c-sis96x.c-281-
--
drivers/i2c/busses/i2c-sun6i-p2wi.c=183=static int p2wi_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-sun6i-p2wi.c-255-	init_completion(&p2wi->complete);
drivers/i2c/busses/i2c-sun6i-p2wi.c:256:	p2wi->adapter.dev.parent = dev;
drivers/i2c/busses/i2c-sun6i-p2wi.c-257-	p2wi->adapter.algo = &p2wi_algo;
--
drivers/i2c/busses/i2c-synquacer.c=535=static int synquacer_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-synquacer.c-584-	i2c_set_adapdata(&i2c->adapter, i2c);
drivers/i2c/busses/i2c-synquacer.c:585:	i2c->adapter.dev.parent = &pdev->dev;
drivers/i2c/busses/i2c-synquacer.c-586-	i2c->adapter.dev.of_node = pdev->dev.of_node;
--
drivers/i2c/busses/i2c-tegra-bpmp.c=283=static int tegra_bpmp_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-tegra-bpmp.c-310-	i2c->adapter.algo = &tegra_bpmp_i2c_algo;
drivers/i2c/busses/i2c-tegra-bpmp.c:311:	i2c->adapter.dev.parent = &pdev->dev;
drivers/i2c/busses/i2c-tegra-bpmp.c-312-	i2c->adapter.dev.of_node = pdev->dev.of_node;
--
drivers/i2c/busses/i2c-tegra.c=2268=static int tegra_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-tegra.c-2341-	i2c_dev->adapter.dev.of_node = i2c_dev->dev->of_node;
drivers/i2c/busses/i2c-tegra.c:2342:	i2c_dev->adapter.dev.parent = i2c_dev->dev;
drivers/i2c/busses/i2c-tegra.c-2343-	i2c_dev->adapter.retries = 1;
--
drivers/i2c/busses/i2c-tiny-usb.c=216=static int i2c_tiny_usb_probe(struct usb_interface *interface,
--
drivers/i2c/busses/i2c-tiny-usb.c-261-
drivers/i2c/busses/i2c-tiny-usb.c:262:	dev->adapter.dev.parent = &dev->interface->dev;
drivers/i2c/busses/i2c-tiny-usb.c-263-
--
drivers/i2c/busses/i2c-via.c=86=static int vt586b_probe(struct pci_dev *dev, const struct pci_device_id *id)
--
drivers/i2c/busses/i2c-via.c-123-	/* set up the sysfs linkage to our parent device */
drivers/i2c/busses/i2c-via.c:124:	vt586b_adapter.dev.parent = &dev->dev;
drivers/i2c/busses/i2c-via.c-125-
--
drivers/i2c/busses/i2c-viapro.c=311=static int vt596_probe(struct pci_dev *pdev,
--
drivers/i2c/busses/i2c-viapro.c-406-
drivers/i2c/busses/i2c-viapro.c:407:	vt596_adapter.dev.parent = &pdev->dev;
drivers/i2c/busses/i2c-viapro.c-408-	snprintf(vt596_adapter.name, sizeof(vt596_adapter.name),
--
drivers/i2c/busses/i2c-xlp9xx.c=506=static int xlp9xx_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-xlp9xx.c-535-	init_completion(&priv->msg_complete);
drivers/i2c/busses/i2c-xlp9xx.c:536:	priv->adapter.dev.parent = &pdev->dev;
drivers/i2c/busses/i2c-xlp9xx.c-537-	priv->adapter.algo = &xlp9xx_i2c_algo;
--
drivers/infiniband/hw/hfi1/qsfp.c=104=static struct hfi1_i2c_bus *init_i2c_bus(struct hfi1_devdata *dd,
--
drivers/infiniband/hw/hfi1/qsfp.c-126-	bus->adapter.algo_data = &bus->algo;
drivers/infiniband/hw/hfi1/qsfp.c:127:	bus->adapter.dev.parent = &dd->pcidev->dev;
drivers/infiniband/hw/hfi1/qsfp.c-128-	snprintf(bus->adapter.name, sizeof(bus->adapter.name),
--
drivers/input/keyboard/pinephone-keyboard.c=320=static int ppkb_probe(struct i2c_client *client)
--
drivers/input/keyboard/pinephone-keyboard.c-378-		ppkb->adapter.algo_data = client;
drivers/input/keyboard/pinephone-keyboard.c:379:		ppkb->adapter.dev.parent = dev;
drivers/input/keyboard/pinephone-keyboard.c-380-		ppkb->adapter.dev.of_node = i2c_bus;
--
drivers/media/dvb-frontends/cx24123.c=1041=struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
--
drivers/media/dvb-frontends/cx24123.c-1084-	state->tuner_i2c_adapter.algo_data = NULL;
drivers/media/dvb-frontends/cx24123.c:1085:	state->tuner_i2c_adapter.dev.parent = i2c->dev.parent;
drivers/media/dvb-frontends/cx24123.c-1086-	i2c_set_adapdata(&state->tuner_i2c_adapter, state);
--
drivers/media/dvb-frontends/zd1301_demod.c=454=static int zd1301_demod_probe(struct platform_device *pdev)
--
drivers/media/dvb-frontends/zd1301_demod.c-495-	dev->adapter.algo_data = NULL;
drivers/media/dvb-frontends/zd1301_demod.c:496:	dev->adapter.dev.parent = pdev->dev.parent;
drivers/media/dvb-frontends/zd1301_demod.c-497-	i2c_set_adapdata(&dev->adapter, dev);
--
drivers/media/pci/zoran/zoran_card.c=698=static int zoran_register_i2c(struct zoran *zr)
--
drivers/media/pci/zoran/zoran_card.c-705-	zr->i2c_adapter.algo_data = &zr->i2c_algo;
drivers/media/pci/zoran/zoran_card.c:706:	zr->i2c_adapter.dev.parent = &zr->pci_dev->dev;
drivers/media/pci/zoran/zoran_card.c-707-	return i2c_bit_add_bus(&zr->i2c_adapter);
--
drivers/media/radio/si4713/radio-usb-si4713.c=400=static int si4713_register_i2c_adapter(struct si4713_usb_device *radio)
--
drivers/media/radio/si4713/radio-usb-si4713.c-403-	/* set up sysfs linkage to our parent device */
drivers/media/radio/si4713/radio-usb-si4713.c:404:	radio->i2c_adapter.dev.parent = &radio->usbdev->dev;
drivers/media/radio/si4713/radio-usb-si4713.c-405-	i2c_set_adapdata(&radio->i2c_adapter, radio);
--
drivers/media/usb/go7007/go7007-i2c.c=204=int go7007_i2c_init(struct go7007 *go)
--
drivers/media/usb/go7007/go7007-i2c.c-207-			sizeof(go7007_adap_templ));
drivers/media/usb/go7007/go7007-i2c.c:208:	go->i2c_adapter.dev.parent = go->dev;
drivers/media/usb/go7007/go7007-i2c.c-209-	i2c_set_adapdata(&go->i2c_adapter, go);
--
drivers/media/usb/go7007/go7007-usb.c=1040=static int go7007_usb_probe(struct usb_interface *intf,
--
drivers/media/usb/go7007/go7007-usb.c-1169-		mutex_init(&usb->i2c_lock);
drivers/media/usb/go7007/go7007-usb.c:1170:		go->i2c_adapter.dev.parent = go->dev;
drivers/media/usb/go7007/go7007-usb.c-1171-		i2c_set_adapdata(&go->i2c_adapter, go);
--
drivers/media/usb/hdpvr/hdpvr-i2c.c=180=int hdpvr_register_i2c_adapter(struct hdpvr_device *dev)
--
drivers/media/usb/hdpvr/hdpvr-i2c.c-184-	dev->i2c_adapter = hdpvr_i2c_adapter_template;
drivers/media/usb/hdpvr/hdpvr-i2c.c:185:	dev->i2c_adapter.dev.parent = &dev->udev->dev;
drivers/media/usb/hdpvr/hdpvr-i2c.c-186-
--
drivers/video/fbdev/cyber2000fb.c=1263=static int cyber2000fb_i2c_register(struct cfb_info *cfb)
--
drivers/video/fbdev/cyber2000fb.c-1268-	cfb->i2c_adapter.algo_data = &cfb->i2c_algo;
drivers/video/fbdev/cyber2000fb.c:1269:	cfb->i2c_adapter.dev.parent = cfb->fb.device;
drivers/video/fbdev/cyber2000fb.c-1270-	cfb->i2c_algo.setsda = cyber2000fb_i2c_setsda;
--
drivers/video/fbdev/matrox/i2c-matroxfb.c=102=static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, 
--
drivers/video/fbdev/matrox/i2c-matroxfb.c-114-	b->adapter.algo_data = &b->bac;
drivers/video/fbdev/matrox/i2c-matroxfb.c:115:	b->adapter.dev.parent = &minfo->pcidev->dev;
drivers/video/fbdev/matrox/i2c-matroxfb.c-116-	b->bac = matrox_i2c_algo_template;
--
drivers/video/fbdev/nvidia/nv_i2c.c=84=static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name,
--
drivers/video/fbdev/nvidia/nv_i2c.c-92-	chan->adapter.algo_data = &chan->algo;
drivers/video/fbdev/nvidia/nv_i2c.c:93:	chan->adapter.dev.parent = &chan->par->pci_dev->dev;
drivers/video/fbdev/nvidia/nv_i2c.c-94-	chan->algo.setsda = nvidia_gpio_setsda;
--
drivers/w1/slaves/w1_ds28e17.c=681=static int w1_f19_add_slave(struct w1_slave *sl)
--
drivers/w1/slaves/w1_ds28e17.c-723-		  sl->name);
drivers/w1/slaves/w1_ds28e17.c:724:	data->adapter.dev.parent = &sl->dev;
drivers/w1/slaves/w1_ds28e17.c-725-	data->adapter.quirks     = &w1_f19_i2c_adapter_quirks;
]

120/2 2026/07/30 12:30 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 105934
							output: 19
							thoughts: 248
						

Thoughts:
**Analyzing I2C Device Parent Assignment in USB Media Drivers**

Okay, my initial observation is that I've spotted a pattern across several USB media drivers. Specifically, I see examples in `drivers/media/radio/si4713/radio-usb-si4713.c`, `drivers/media/usb/hdpvr/hdpvr-i2c.c`, and `drivers/media/usb/go7007/go7007-usb.c` where the I2C adapter's device parent is being set. It looks like each one uses a slightly different approach but shares the same underlying goal.

My immediate question is how `go->dev` resolves to a `struct device *`. I know it's pointing to either `&intf->dev` or `&usbdev->dev`, but I need to quickly refresh my understanding here. Let's dig into the `hdpvr` driver for a concrete example, as it appears to directly use `&dev->udev->dev`. I need to confirm that `hdpvr` handles unregistration correctly, especially given this parent assignment strategy. I suspect it might defer unregistration, or have some specific logic related to this. To confirm this I need to check the `hdpvr_disconnect` function.



121/2 2026/07/30 12:30 tool grepper
0m Args:
map[Expression:hdpvr_disconnect]

Results:
map[Output:drivers/media/usb/hdpvr/hdpvr-core.c=264=static int hdpvr_probe(struct usb_interface *interface,
--
drivers/media/usb/hdpvr/hdpvr-core.c-400-
drivers/media/usb/hdpvr/hdpvr-core.c:401:static void hdpvr_disconnect(struct usb_interface *interface)
drivers/media/usb/hdpvr/hdpvr-core.c-402-{
--
drivers/media/usb/hdpvr/hdpvr-core.c=427=static struct usb_driver hdpvr_usb_driver = {
--
drivers/media/usb/hdpvr/hdpvr-core.c-429-	.probe =	hdpvr_probe,
drivers/media/usb/hdpvr/hdpvr-core.c:430:	.disconnect =	hdpvr_disconnect,
drivers/media/usb/hdpvr/hdpvr-core.c-431-	.id_table =	hdpvr_table,
]

122/2 2026/07/30 12:31 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 106762
							output: 45
							thoughts: 11
						

Thoughts:
Okay, here's my interpretation of that thought process, tailored for an expert audience, and written in the first person:

**Analyzing the Command: `hdpvr_disconnect`**

Alright, let's dive into this. "hdpvr_disconnect"... immediately my mind goes to the likely implications. Given the name, I'm expecting this command to be involved in severing a connection, presumably related to an HDPVR – a High Definition Personal Video Recorder. The immediate questions that spring to mind are: *What* is being disconnected? Is this a hardware connection (e.g., physical cable removal) or a software-level disconnect (e.g., stopping a stream, unmounting a network share)? Is this command part of a larger management framework or a standalone utility? What are the potential side effects - data corruption, orphaned processes, system instability if not handled carefully? I'll need to consider this in light of the likely context, and I'll need to look at whether it might be part of a pipeline. What are the dependencies? I'm already anticipating the need to cross-reference with related tools and configurations. I'm also assessing potential error conditions and graceful handling. If it's a software disconnect, I need to know about the shutdown routines. If it's a hardware disconnect, I'm thinking about how the system handles hot-swapping and if there are any specific shutdown sequences required to ensure the system doesn't crash. My next step will be to examine the implementation of `hdpvr_disconnect` itself. I need the specifics of its interaction with the kernel, device drivers, and any relevant user-space applications. And from the name, it's pretty clear it's going to be something very specific. I can't wait to see the details.



123/2 2026/07/30 12:31 tool read-file
0m Args:
map[File:drivers/media/usb/hdpvr/hdpvr-core.c FirstLine:401 LineCount:30]

Results:
map[Contents: 401:	static void hdpvr_disconnect(struct usb_interface *interface)
 402:	{
 403:		struct hdpvr_device *dev = to_hdpvr_dev(usb_get_intfdata(interface));
 404:	
 405:		v4l2_info(&dev->v4l2_dev, "device %s disconnected\n",
 406:			  video_device_node_name(&dev->video_dev));
 407:		/* prevent more I/O from starting and stop any ongoing */
 408:		mutex_lock(&dev->io_mutex);
 409:		dev->status = STATUS_DISCONNECTED;
 410:		wake_up_interruptible(&dev->wait_data);
 411:		wake_up_interruptible(&dev->wait_buffer);
 412:		mutex_unlock(&dev->io_mutex);
 413:		v4l2_device_disconnect(&dev->v4l2_dev);
 414:		msleep(100);
 415:		flush_work(&dev->worker);
 416:		mutex_lock(&dev->io_mutex);
 417:		hdpvr_cancel_queue(dev);
 418:		mutex_unlock(&dev->io_mutex);
 419:	#if IS_ENABLED(CONFIG_I2C)
 420:		i2c_del_adapter(&dev->i2c_adapter);
 421:	#endif
 422:		video_unregister_device(&dev->video_dev);
 423:		atomic_dec(&dev_nr);
 424:	}
 425:	
 426:	
 427:	static struct usb_driver hdpvr_usb_driver = {
 428:		.name =		"hdpvr",
 429:		.probe =	hdpvr_probe,
 430:		.disconnect =	hdpvr_disconnect,
]

124/2 2026/07/30 12:31 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 107724
							output: 25
							thoughts: 46
						

Thoughts:
Okay, here's my interpretation of those thoughts, presented as a personal thought process, as requested:

**Debugging I2C Adapter Disconnection**

Right, so that `hdpvr_disconnect` function... I need to be careful here. I just remembered that it calls `i2c_del_adapter` synchronously! That's a crucial piece of information. Since it's synchronous, that pretty much rules out the `hdpvr` module as the source of my problem, or at least, this isn't the primary area of focus. I need to look elsewhere for the root cause of the adapter disconnection. Okay, time to look for the next likely suspect.

Now, let's see... what else is on the radar? Ah, yes. `radio-usb-si4713.c`. I have a feeling that might be a better lead. Let me dig into that module next and see what its handling of the I2C adapter looks like. I'll check its disconnect routines specifically. I'm hoping I can find a flaw in the I2C handling there that helps explain the behavior I'm seeing.



125/2 2026/07/30 12:31 tool grepper
0m Error:
log-in to see details

Args:
map[Expression:si4713_usb_device_disconnect]

Results:
map[Output:]

126/2 2026/07/30 12:31 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 108051
							output: 46
							thoughts: 23
						

Thoughts:
Okay, here's my take on those thoughts, tailored for an expert audience:

**Diving into the Si4713 USB Driver**

Alright, time to get my hands dirty. I need to refresh my memory on the specifics of how the Si4713 radio chip interacts with the system via USB. Specifically, I should start by taking a close look at the `usb_driver` within the `radio-usb-si4713.c` source file. This is where the core logic will reside – the device probe, disconnect handling, data transfer mechanisms, USB descriptor parsing, and all the nitty-gritty details of the USB communication protocol for this particular device family. Knowing that driver code will give me the best insight into its design decisions. This is where I'll probably find the critical data structures and how they are populated, any potential hardware idiosyncrasies the driver has accounted for, and most importantly, how the driver handles potential USB errors or device states. This is my starting point for understanding its operational behavior.



127/2 2026/07/30 12:31 tool grepper
0m Args:
map[Expression:usb_driver PathPrefix:drivers/media/radio/si4713/radio-usb-si4713.c]

Results:
map[Output:drivers/media/radio/si4713/radio-usb-si4713.c=500=static void usb_si4713_disconnect(struct usb_interface *intf)
--
drivers/media/radio/si4713/radio-usb-si4713.c-514-/* USB subsystem interface */
drivers/media/radio/si4713/radio-usb-si4713.c:515:static struct usb_driver usb_si4713_driver = {
drivers/media/radio/si4713/radio-usb-si4713.c-516-	.name			= "radio-usb-si4713",
--
drivers/media/radio/si4713/radio-usb-si4713.c-521-
drivers/media/radio/si4713/radio-usb-si4713.c:522:module_usb_driver(usb_si4713_driver);
]

128/2 2026/07/30 12:31 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 108601
							output: 51
							thoughts: 15
						

Thoughts:
Okay, let's dive into this. Here's my take on `usb_si4713_disconnect`, breaking down my thought process as I, an expert, would:

**Dissecting `usb_si4713_disconnect`**

Alright, I see the task: to analyze this `usb_si4713_disconnect` function. My initial assumption, given the name, is that it's related to cleanly removing or detaching a device – specifically, a Si4713-based USB device. The naming convention is pretty standard, making that assumption quite solid. Now, my mind immediately jumps to a checklist: What resources are being managed? USB devices, especially those interfacing with audio or radio, often have multiple layers: the USB connection itself, perhaps a specific driver instance, potentially even audio playback streams or radio frequency controls. The disconnect function *should* handle the graceful shutdown of all of these, not just the raw USB connection. I need to look for calls to functions that release USB descriptors, stop any data transfer endpoints, unregister the device from the system, release any mutexes or semaphores protecting shared resources, and free any allocated memory associated with the device's state.

I'm also curious about error handling. Is there any attempt to gracefully handle the case where the device is unexpectedly disconnected? A robust disconnect routine would likely check for and handle errors reported by lower-level USB APIs, logging the errors appropriately or even attempting some sort of fallback or retry mechanism if feasible. Furthermore, what about race conditions? This function, or at least its underlying device data structures, is likely being accessed concurrently by multiple threads – the USB interrupt handler, application threads, perhaps even system management threads. Therefore, I must expect and look for synchronization primitives like mutexes or spinlocks to ensure data integrity and avoid crashes during the disconnection process. In addition, I will want to think through the scenarios where a disconnect can happen. What are the various scenarios that may arise, such as a user pressing "eject", a USB cable being pulled, or a system shutdown. Does the code adequately handle all of them? Finally, I need to verify that this function aligns with the overall driver architecture. Does it follow established best practices for USB device handling? Does it adhere to the relevant specifications and standards? That is my framework for evaluation.



129/2 2026/07/30 12:31 tool read-file
0m Args:
map[File:drivers/media/radio/si4713/radio-usb-si4713.c FirstLine:500 LineCount:20]

Results:
map[Contents: 500:	static void usb_si4713_disconnect(struct usb_interface *intf)
 501:	{
 502:		struct si4713_usb_device *radio = to_si4713_dev(usb_get_intfdata(intf));
 503:	
 504:		dev_info(&intf->dev, "Si4713 development board now disconnected\n");
 505:	
 506:		mutex_lock(&radio->lock);
 507:		usb_set_intfdata(intf, NULL);
 508:		video_unregister_device(&radio->vdev);
 509:		v4l2_device_disconnect(&radio->v4l2_dev);
 510:		mutex_unlock(&radio->lock);
 511:		v4l2_device_put(&radio->v4l2_dev);
 512:	}
 513:	
 514:	/* USB subsystem interface */
 515:	static struct usb_driver usb_si4713_driver = {
 516:		.name			= "radio-usb-si4713",
 517:		.probe			= usb_si4713_probe,
 518:		.disconnect		= usb_si4713_disconnect,
 519:		.id_table		= usb_si4713_usb_device_table,
]

130/2 2026/07/30 12:31 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 109544
							output: 50
							thoughts: 62
						

Thoughts:
**Debugging the SI4713 USB Disconnect**

Okay, here's what's running through my head. I've been tracing the disconnect sequence for this SI4713 USB device, and it's become clear: `usb_si4713_disconnect` doesn't actually handle the unregistering of the I2C adapter. That's a key piece I was missing! Now, I need to figure out *where* that crucial `i2c_del_adapter` call is actually happening, or *should* be happening. Hmm, let me think... where does the lifecycle of this I2C adapter get managed? Let's quickly review the standard places for device cleanup. I need to check `v4l2_device_put` and the driver's release callback function - those seem like the most likely candidates for handling the de-registration of the I2C adapter when the device is removed. Time to go dig in those functions!



131/2 2026/07/30 12:31 tool grepper
0m Args:
map[Expression:i2c_del_adapter PathPrefix:drivers/media/radio/si4713/radio-usb-si4713.c]

Results:
map[Output:drivers/media/radio/si4713/radio-usb-si4713.c=128=static void usb_si4713_video_device_release(struct v4l2_device *v4l2_dev)
--
drivers/media/radio/si4713/radio-usb-si4713.c-132-
drivers/media/radio/si4713/radio-usb-si4713.c:133:	i2c_del_adapter(adapter);
drivers/media/radio/si4713/radio-usb-si4713.c-134-	v4l2_device_unregister(&radio->v4l2_dev);
--
drivers/media/radio/si4713/radio-usb-si4713.c=411=static int usb_si4713_probe(struct usb_interface *intf,
--
drivers/media/radio/si4713/radio-usb-si4713.c-490-del_adapter:
drivers/media/radio/si4713/radio-usb-si4713.c:491:	i2c_del_adapter(adapter);
drivers/media/radio/si4713/radio-usb-si4713.c-492-err_i2cdev:
]

132/2 2026/07/30 12:31 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 110218
							output: 51
							thoughts: 298
						

Thoughts:
**My Analysis of the Si4713 USB Radio Driver's Device Release**

Okay, so I've been tracing the driver's lifecycle and release path for the Si4713 USB radio. The key is understanding when `usb_si4713_video_device_release` gets called. Right, it's triggered when the *last* reference to the `v4l2_dev` is dropped. And that happens when the user closes the corresponding `/dev/radioX` file descriptor. Makes sense.

So, user opens the radio device, then unplugs the USB device. Now `usb_si4713_disconnect` gets called. This disconnect function unregisters the video device and disconnects `v4l2_dev`. But hold on, the `v4l2_dev`'s reference count is *still* greater than zero because the file descriptor is still open. This is crucial: that means `i2c_del_adapter` is *not* called at this point. That's good.

But, the `usb_device` itself... that's managed by the USB core. It gets freed when the USB device is physically disconnected. Ah, that's right, the USB core handles that. But hang on... let's see. The I2C adapter... the parent of `radio->i2c_adapter.dev` is set to `&radio->usbdev->dev;`. The parent! So, it points to the device structure itself. When the USB device disappears, so does the reference to the usbdev.

Wait, `usbdev` is a `struct usb_device`. Does it get freed then? Yes, yes it does. When the device is physically disconnected, the USB core drops the reference to it, and it's free game. Aha.

But does `usb_si4713_probe` actually take a reference to `usbdev`? I need to double-check that. Let me quickly review `usb_si4713_probe`. I need to ensure that the probe function doesn't inadvertently hold a reference longer than necessary. I'll check the probe routine to make sure it doesn't leak references, in other words.



133/2 2026/07/30 12:31 tool read-file
0m Args:
map[File:drivers/media/radio/si4713/radio-usb-si4713.c FirstLine:411 LineCount:30]

Results:
map[Contents: 411:	static int usb_si4713_probe(struct usb_interface *intf,
 412:					const struct usb_device_id *id)
 413:	{
 414:		struct si4713_usb_device *radio;
 415:		struct i2c_adapter *adapter;
 416:		struct v4l2_subdev *sd;
 417:		int retval;
 418:	
 419:		dev_info(&intf->dev, "Si4713 development board discovered: (%04X:%04X)\n",
 420:				id->idVendor, id->idProduct);
 421:	
 422:		/* Initialize local device structure */
 423:		radio = kzalloc_obj(struct si4713_usb_device);
 424:		if (radio)
 425:			radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
 426:	
 427:		if (!radio || !radio->buffer) {
 428:			dev_err(&intf->dev, "kmalloc for si4713_usb_device failed\n");
 429:			kfree(radio);
 430:			return -ENOMEM;
 431:		}
 432:	
 433:		mutex_init(&radio->lock);
 434:	
 435:		radio->usbdev = interface_to_usbdev(intf);
 436:		radio->intf = intf;
 437:		usb_set_intfdata(intf, &radio->v4l2_dev);
 438:	
 439:		retval = si4713_start_seq(radio);
 440:		if (retval < 0)
]

134/2 2026/07/30 12:31 llm crash-repro-finder
1m Model:
gemini-3.1-pro-preview

Tokens:
							input: 111540
							output: 48
							thoughts: 125
						

Thoughts:
**The Root of the Issue**

Okay, so I'm looking at this `radio-usb-si4713` driver and it's making a fundamental mistake. It just assigns `interface_to_usbdev(intf)` to `radio->usbdev` directly, without a `usb_get_dev()` call. That's a huge oversight. Essentially, it's not taking a reference to the `usb_device`. This means when the USB device is disconnected – and the USB core handles the cleanup – that `usb_device` is going to be freed. But the I2C adapter, and by extension, this driver, are still registered and their `dev.parent` is now pointing at a *freed* `usb_device`! That, in a nutshell, is the bug. This is exactly where the problem lies. It's a simple driver, but this oversight has some nasty implications. Now, let me just quickly confirm the USB IDs to ensure I'm barking up the right tree...



135/2 2026/07/30 12:32 tool grepper
0m Args:
map[Expression:usb_device_id PathPrefix:drivers/media/radio/si4713/radio-usb-si4713.c]

Results:
map[Output:drivers/media/radio/si4713/radio-usb-si4713.c=29=MODULE_LICENSE("GPL v2");
--
drivers/media/radio/si4713/radio-usb-si4713.c-39-/* USB Device ID List */
drivers/media/radio/si4713/radio-usb-si4713.c:40:static const struct usb_device_id usb_si4713_usb_device_table[] = {
drivers/media/radio/si4713/radio-usb-si4713.c-41-	{USB_DEVICE_AND_INTERFACE_INFO(USB_SI4713_VENDOR, USB_SI4713_PRODUCT,
--
drivers/media/radio/si4713/radio-usb-si4713.c=411=static int usb_si4713_probe(struct usb_interface *intf,
drivers/media/radio/si4713/radio-usb-si4713.c:412:				const struct usb_device_id *id)
drivers/media/radio/si4713/radio-usb-si4713.c-413-{
]

136/2 2026/07/30 12:32 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 112248
							output: 52
							thoughts: 27
						

Thoughts:
Okay, here's my attempt at summarizing those thoughts from an expert's perspective, using a first-person narrative:

**Investigating USB Vendor and Product IDs for SI4713**

Alright, let's get down to brass tacks. First thing's first, I need to verify something fundamental: the specific USB identifiers for the SI4713. I'm going to have to check `USB_SI4713_VENDOR` and `USB_SI4713_PRODUCT`. It's crucial, obviously. Knowing those specific Vendor and Product IDs is the foundational step for proper device recognition and interaction. Without them, even the most elegant driver or application will be dead in the water. I have to make sure these are correctly defined and understood across the whole stack. I'll need these constants to be correct when I'm debugging, and will need to reference them as I build or modify the driver code. It's a quick check, but vital.



137/2 2026/07/30 12:32 tool grepper
0m Args:
map[Expression:USB_SI4713_VENDOR PathPrefix:drivers/media/radio/si4713/radio-usb-si4713.c]

Results:
map[Output:drivers/media/radio/si4713/radio-usb-si4713.c=29=MODULE_LICENSE("GPL v2");
--
drivers/media/radio/si4713/radio-usb-si4713.c-31-/* The Device announces itself as Cygnal Integrated Products, Inc. */
drivers/media/radio/si4713/radio-usb-si4713.c:32:#define USB_SI4713_VENDOR		0x10c4
drivers/media/radio/si4713/radio-usb-si4713.c-33-#define USB_SI4713_PRODUCT		0x8244
--
drivers/media/radio/si4713/radio-usb-si4713.c=40=static const struct usb_device_id usb_si4713_usb_device_table[] = {
drivers/media/radio/si4713/radio-usb-si4713.c:41:	{USB_DEVICE_AND_INTERFACE_INFO(USB_SI4713_VENDOR, USB_SI4713_PRODUCT,
drivers/media/radio/si4713/radio-usb-si4713.c-42-							USB_CLASS_HID, 0, 0) },
]

138/2 2026/07/30 12:32 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 112875
							output: 35
							thoughts: 201
						

Thoughts:
**USB Device Configuration: A Breakdown**

Okay, so I'm looking at vendor `0x10c4`, product `0x8244`.  Right, and this needs the `USB_CLASS_HID` interface – that's 0x03. Now, I vaguely remember something about this... Ah, yes!  Looking back at `vusb.txt`, I see `usb_device_descriptor_hid` mentions that the `idVendor` and `idProduct` are modified by some Go code.

So, the plan is to bypass that and use `syz_usb_connect` with a custom structure. I've done this before, I *think* I recall that being how this works.

Hang on a second. Didn't I run into a problem earlier?  I remember getting a "wrong int arg *prog.UnionType" error when I tried using `ANY`. Right, that's because `ANY` is expecting a union of `ANY` types, and `syzkaller` doesn't directly support `ANY` being used on structs in that way, darn it. Okay, I'll need to go another route...

But wait!  `syz_usb_connect` has a `dev ptr[in, string]` argument in the generic definition!  *That* should allow me to specify the device details. Okay, let me go back to `vusb.txt` and double-check how that argument is constructed. Hopefully, I've got enough information to craft the right structure and get this test running.



139/2 2026/07/30 12:32 tool grepper
0m Error:
log-in to see details

Args:
map[Expression:syz_usb_connect\( PathPrefix:sys/linux/vusb.txt]

Results:
map[Output:]

140/2 2026/07/30 12:32 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 113460
							output: 23
							thoughts: 2166
						

Thoughts:
**USB Device Descriptor Conundrum**

Okay, let's break this down. I've been staring at this `vusb.txt` file and I need to reliably emulate a specific USB device, namely the si4713. The immediate issue is the expected data type for the `dev` argument in `syz_usb_connect`. It's clearly not a string, like I initially tried with that `&AUTO` construct. It's expecting a `usb_device_descriptor` struct.

My first thought was, "Great, I can construct the struct!".  I started trying to define the `usb_device_descriptor` with the correct values from the si4713. But then the `idVendor` field threw a wrench in the works. It's defined as `const[0, int16]`.  I realized I *can't* directly set the vendor ID to `0x10c4` because of that `const` constraint. It appears Syzkaller will override what I provide if it's set to a value other than `0`.

Then I pondered if the `AUTO` keyword would help, but it still expects a USB ID, not a specific value.

I considered `syz_usb_connect$hid` to see if that would automatically patch the device ID. Maybe the syzkaller Go code knows about this specific device (`0x10c4:0x8244`) or can force the HID patching. I can't check `init_vusb.go` directly.

I considered manually crafting a struct that would be compatible with a descriptor using the `&ANY` operator. I got the error `"wrong int arg *prog.UnionType"` meaning I needed to specify which union option. My next idea was using `ANY=@ANYBLOB="1201..."`

I thought, "Can I force the vendor by using `syz_usb_connect` and then `syz_usb_control_io` to manually handle the `GET_DESCRIPTOR` request?"  But no, `syz_usb_connect` handles the descriptor internally.

The `usb_device_descriptor` definition is a bit tricky. The struct itself takes the `VENDOR` and `PRODUCT` constants, but that still won't help me control the vendor and product ID. I am still unable to modify the device descriptor and inject raw data.

A potential solution popped in my head. Since I can't directly control the value of `idVendor` and `idProduct`, the *best* option may be to write bytes to a memory location, then pass the address of that memory as the `dev` argument. I planned to do this by using a pipe to write the correct byte values to a specific memory location. However, since I can't manipulate the file descriptors returned by `pipe2` as individual variables, this won't be possible.

Now the question is, can I control which `VENDOR` and `PRODUCT` IDs are generated by `AUTO`?

But *wait*! The device is a HID device. If I use `syz_usb_connect$hid`, syzkaller might patch `idVendor` and `idProduct` for a known HID device. I remembered that si4713 declares: `{USB_DEVICE_AND_INTERFACE_INFO(USB_SI4713_VENDOR, USB_SI4713_PRODUCT, USB_CLASS_HID, 0, 0) }`.

I have to check if `0x10c4:0x8244` is a known HID device in syzkaller. If it is, then `syz_usb_connect$hid` will automatically use it. I need to make sure this happens reliably, though. I am going to search in the driver.

There is a last desperate thought: Are there any other drivers? Could `hdpvr` or `go7007` work? No, not really.



141/2 2026/07/30 12:33 tool grepper
0m Args:
map[Expression:go7007_usb_disconnect]

Results:
map[Output:drivers/media/usb/go7007/go7007-usb.c=1040=static int go7007_usb_probe(struct usb_interface *intf,
--
drivers/media/usb/go7007/go7007-usb.c-1327-
drivers/media/usb/go7007/go7007-usb.c:1328:static void go7007_usb_disconnect(struct usb_interface *intf)
drivers/media/usb/go7007/go7007-usb.c-1329-{
--
drivers/media/usb/go7007/go7007-usb.c=1347=static struct usb_driver go7007_usb_driver = {
--
drivers/media/usb/go7007/go7007-usb.c-1349-	.probe		= go7007_usb_probe,
drivers/media/usb/go7007/go7007-usb.c:1350:	.disconnect	= go7007_usb_disconnect,
drivers/media/usb/go7007/go7007-usb.c-1351-	.id_table	= go7007_usb_id_table,
]

142/2 2026/07/30 12:33 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 116848
							output: 50
							thoughts: 15
						

Thoughts:
Okay, here's my interpretation of that.

**Analyzing the USB Disconnect Scenario**

Alright, let's dive into this `go7007_usb_disconnect` situation. It's a key piece of the puzzle, likely a function responsible for handling the detachment of a USB device associated with the go7007 system. As an expert in embedded systems/drivers, I need to understand what this function does, and how it handles the device being unplugged. My immediate mental checklist starts:

*   **Resource Management:** I'm expecting this function to free any allocated resources (buffers, memory, etc.) associated with the disconnected device. Failing to do so can lead to memory leaks, system instability, and ultimately a crash.
*   **Interrupt Handling:** How is the interrupt flow managed? Does the function disable interrupts related to the device, acknowledge the disconnection event, and ensure that the system no longer attempts to communicate with the now-absent hardware? Timing is critical here to avoid race conditions.
*   **State Transitions:** Disconnection is a state change. The function likely needs to transition the driver and the go7007 system from an active state to an inactive or disconnected state. This requires updating internal flags, potentially signaling to other modules that the device is gone.
*   **Error Conditions:** What if the disconnection is unexpected (e.g., a power failure)? Are error checks and handling implemented? Does it gracefully report any errors?
*   **Cleanup Procedures:** There's likely some device specific cleanup, like stopping ongoing data transfers, or putting the USB interface back into a known state.
*   **Driver Unloading:** Is it responsible for unloading the USB driver, if the device is no longer present?
*   **Concurrency:** Any potential threading or multi-process issues? Does this function use mutexes or other synchronization primitives to protect shared data structures?
*   **Log Entries:** I want to check for logging. A disconnect event should always be logged, providing invaluable debugging information.

I'll be looking for these aspects, so I can analyze if this function is robust.



143/2 2026/07/30 12:33 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:1328 LineCount:20]

Results:
map[Contents:1328:	static void go7007_usb_disconnect(struct usb_interface *intf)
1329:	{
1330:		struct go7007 *go = to_go7007(usb_get_intfdata(intf));
1331:	
1332:		mutex_lock(&go->queue_lock);
1333:		mutex_lock(&go->serialize_lock);
1334:	
1335:		if (go->audio_enabled)
1336:			go7007_snd_remove(go);
1337:	
1338:		go->status = STATUS_SHUTDOWN;
1339:		v4l2_device_disconnect(&go->v4l2_dev);
1340:		video_unregister_device(&go->vdev);
1341:		mutex_unlock(&go->serialize_lock);
1342:		mutex_unlock(&go->queue_lock);
1343:	
1344:		v4l2_device_put(&go->v4l2_dev);
1345:	}
1346:	
1347:	static struct usb_driver go7007_usb_driver = {
]

144/2 2026/07/30 12:33 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 117691
							output: 39
							thoughts: 38
						

Thoughts:
Okay, here's my take on those thoughts, framed from my expert perspective:

**Debugging I2C Adapter Removal in the go7007_usb Driver**

Right, let me see... I'm looking at this `go7007_usb_disconnect` function, and the code definitely *doesn't* appear to have a call to `i2c_del_adapter`. That's a bit perplexing. This is critical because `i2c_del_adapter` is responsible for properly releasing the I2C adapter resources when a USB device is disconnected. Without it, we're likely going to run into issues; potential resource leaks, perhaps even system instability, are immediate concerns.

So, the immediate question is: *where* is `i2c_del_adapter` actually being called within this module, or perhaps in some other related module? My initial thought is to trace the disconnect flow more thoroughly. Let me check the driver's exit path, see if there's any other cleanup involved, or if any auxiliary module handling the I2C adapter is responsible for this critical cleanup. I'll need to go beyond `go7007_usb_disconnect` itself to track down the responsible call. I need to understand this whole cleanup sequence and ensure no resources are being orphaned. I'll need to get to the bottom of this.



145/2 2026/07/30 12:33 tool grepper
0m Args:
map[Expression:i2c_del_adapter PathPrefix:drivers/media/usb/go7007/]

Results:
map[Output:drivers/media/usb/go7007/go7007-driver.c=227=static void go7007_remove(struct v4l2_device *v4l2_dev)
--
drivers/media/usb/go7007/go7007-driver.c-234-	if (go->i2c_adapter_online) {
drivers/media/usb/go7007/go7007-driver.c:235:		i2c_del_adapter(&go->i2c_adapter);
drivers/media/usb/go7007/go7007-driver.c-236-		go->i2c_adapter_online = 0;
]

146/2 2026/07/30 12:33 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 118251
							output: 46
							thoughts: 70
						

Thoughts:
**Eureka! The Problem Domain is Narrowed**

Yes! I've confirmed it. The `go7007_remove` function, just like with the other driver I was investigating, is being called from within `v4l2_device_put`! That's the key: it's triggered when the *last* reference to the device is released. It's the same bug, manifesting in a different driver. Excellent! This is a pattern.

And hang on... `go7007` is a *USB video device*! So, it’s a specific category of devices. Now that I know the code point, I can quickly check the USB IDs and understand the device that is having this issue, and the drivers they are associated with. With that information, I can see how it's interacting with the underlying USB stack, as a starting point for figuring out what's going wrong. This is perfect!



147/2 2026/07/30 12:33 tool grepper
0m Args:
map[Expression:usb_device_id PathPrefix:drivers/media/usb/go7007/go7007-usb.c]

Results:
map[Output:drivers/media/usb/go7007/go7007-usb.c=469=static const struct go7007_usb_board board_ads_usbav_709 = {
--
drivers/media/usb/go7007/go7007-usb.c-505-
drivers/media/usb/go7007/go7007-usb.c:506:static const struct usb_device_id go7007_usb_id_table[] = {
drivers/media/usb/go7007/go7007-usb.c-507-	{
--
drivers/media/usb/go7007/go7007-usb.c=1040=static int go7007_usb_probe(struct usb_interface *intf,
drivers/media/usb/go7007/go7007-usb.c:1041:		const struct usb_device_id *id)
drivers/media/usb/go7007/go7007-usb.c-1042-{
]

148/2 2026/07/30 12:33 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 118853
							output: 49
							thoughts: 17
						

Thoughts:
Okay, let's dive into this. Here's my take on those thoughts, as if they're my own:

**Analyzing the USB ID Table: `go7007_usb_id_table`**

Alright, let's see what we've got here. I need to get a handle on the `go7007_usb_id_table`. I'm immediately thinking, this is probably a critical piece of the puzzle for identifying and configuring USB devices related to the go7007 chipset – likely a driver or module setup. Knowing this table's structure is essential, because, like any expert in this area understands, the USB ID table provides the foundation for associating specific hardware vendor and product IDs with the appropriate driver or module. That's a crucial first step for proper device recognition and operation within the system. Is this just a simple lookup table or is it more complex, perhaps including more parameters? I need to look closer to assess the architecture. I'm hoping it's well-documented... but probably not. Time to get digging!



149/2 2026/07/30 12:33 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:506 LineCount:30]

Results:
map[Contents: 506:	static const struct usb_device_id go7007_usb_id_table[] = {
 507:		{
 508:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
 509:						USB_DEVICE_ID_MATCH_INT_INFO,
 510:			.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
 511:			.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
 512:			.bcdDevice_lo	= 0x200,   /* Revision number of XMen */
 513:			.bcdDevice_hi	= 0x200,
 514:			.bInterfaceClass	= 255,
 515:			.bInterfaceSubClass	= 0,
 516:			.bInterfaceProtocol	= 255,
 517:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_XMEN,
 518:		},
 519:		{
 520:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
 521:			.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
 522:			.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
 523:			.bcdDevice_lo	= 0x202,   /* Revision number of Matrix II */
 524:			.bcdDevice_hi	= 0x202,
 525:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_MATRIX_II,
 526:		},
 527:		{
 528:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
 529:			.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
 530:			.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
 531:			.bcdDevice_lo	= 0x204,   /* Revision number of Matrix */
 532:			.bcdDevice_hi	= 0x204,   /*     Reloaded */
 533:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_MATRIX_RELOAD,
 534:		},
 535:		{
]

150/2 2026/07/30 12:33 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 119832
							output: 21
							thoughts: 3277
						

Thoughts:
**Okay, let's break this down. My initial focus was on figuring out how to trigger a specific USB device configuration (0x0eb1:0x7007) using syzkaller.** I quickly realized that syzkaller's `syz_usb_connect` function and its limited pre-defined device descriptors weren't going to cut it. I pondered whether I could directly manipulate `idVendor` and `idProduct` within the descriptor, but the constants prevented that. The existence of various pre-defined descriptors in syzkaller gave me a hint, but none matched the device I was targeting. The fact that the bug report references kasan reports and not usb errors piqued my interest.

**Then, my thinking shifted. The crash wasn't directly in a USB driver itself, but potentially in something called by it.** I examined the stack trace from the KASAN report, specifically focusing on `usb_register_bus` and its call chain: `blocking_notifier_call_chain`, `mon_notify`, `mon_bus_add`, `mon_bus_init`, `mon_bin_add`, and finally, `device_create`. The `device_create` function allocates a `struct device` and is key. Then I investigated the allocator size of `struct device` which led me to the conclusion that `kobject_uevent_env` could be in the same allocation slot. This is because both were allocated by `kmalloc-4k`. I then investigated the sizes of both these objects.

**The allocation size was clearly the crucial clue.** I honed in on the fact that `kobject_uevent_env` has a sizable buffer (2048 bytes) that would be allocated in a `kmalloc-4k` region, matching the KASAN report's "4096-byte region". Then, I realized that `kobject_uevent_env` is short-lived, meaning the memory it allocated was freed quickly. This strongly suggests a Use-After-Free (UAF) issue, where a previous object allocated in that same 4k slot was freed, then accessed later. The KASAN report pointing to 264 bytes into the freed region gave me a solid indication of what the memory slot had previously held.

**This led me to hypothesize that the original allocation was likely a `struct usb_device`, which is significantly larger than just `struct device` itself.** I checked the size of `struct usb_device`, calculating that it *could* fit within a `kmalloc-4k` region. The key was confirming that a member of that struct would be at or around the KASAN report offset. From the code, I could see that offset 264 in a freed `struct usb_device` pointed to `dev.type` from within `struct device`, perfectly explaining the UAF! To fully confirm this hypothesis I did some manual calculation of offset to verify. Finally, I used external tools to confirm my suspicion about the offset of `dev.type` within `struct usb_device`. I think I have it!



151/2 2026/07/30 12:34 tool codesearch-struct-layout
0m Args:
map[Name:usb_device]

Results:
map[Fields:[map[Name:devnum OffsetBits:0 SizeBits:32] map[Name:devpath OffsetBits:32 SizeBits:128] map[Name:route OffsetBits:160 SizeBits:32] map[Name:state OffsetBits:192 SizeBits:32] map[Name:speed OffsetBits:224 SizeBits:32] map[Name:rx_lanes OffsetBits:256 SizeBits:32] map[Name:tx_lanes OffsetBits:288 SizeBits:32] map[Name:ssp_rate OffsetBits:320 SizeBits:32] map[Name:tt OffsetBits:384 SizeBits:64] map[Name:ttport OffsetBits:448 SizeBits:32] map[Name:toggle OffsetBits:480 SizeBits:64] map[Name:parent OffsetBits:576 SizeBits:64] map[Name:bus OffsetBits:640 SizeBits:64] map[Name:ep0 OffsetBits:704 SizeBits:704] map[Name:dev OffsetBits:1408 SizeBits:11776] map[Name:descriptor OffsetBits:13184 SizeBits:144] map[Name:bos OffsetBits:13376 SizeBits:64] map[Name:config OffsetBits:13440 SizeBits:64] map[Name:actconfig OffsetBits:13504 SizeBits:64] map[Name:ep_in OffsetBits:13568 SizeBits:1024] map[Name:ep_out OffsetBits:14592 SizeBits:1024] map[Name:rawdescriptors OffsetBits:15616 SizeBits:64] map[Name:bus_mA OffsetBits:15680 SizeBits:16] map[Name:portnum OffsetBits:15696 SizeBits:8] map[Name:level OffsetBits:15704 SizeBits:8] map[Name:devaddr OffsetBits:15712 SizeBits:8] map[Name:can_submit OffsetBits:15720 SizeBits:1] map[Name:persist_enabled OffsetBits:15721 SizeBits:1] map[Name:reset_in_progress OffsetBits:15722 SizeBits:1] map[Name:have_langid OffsetBits:15723 SizeBits:1] map[Name:authorized OffsetBits:15724 SizeBits:1] map[Name:authenticated OffsetBits:15725 SizeBits:1] map[Name:lpm_capable OffsetBits:15726 SizeBits:1] map[Name:lpm_devinit_allow OffsetBits:15727 SizeBits:1] map[Name:usb2_hw_lpm_capable OffsetBits:15728 SizeBits:1] map[Name:usb2_hw_lpm_besl_capable OffsetBits:15729 SizeBits:1] map[Name:usb2_hw_lpm_enabled OffsetBits:15730 SizeBits:1] map[Name:usb2_hw_lpm_allowed OffsetBits:15731 SizeBits:1] map[Name:usb3_lpm_u1_enabled OffsetBits:15732 SizeBits:1] map[Name:usb3_lpm_u2_enabled OffsetBits:15733 SizeBits:1] map[Name:string_langid OffsetBits:15744 SizeBits:32] map[Name:product OffsetBits:15808 SizeBits:64] map[Name:manufacturer OffsetBits:15872 SizeBits:64] map[Name:serial OffsetBits:15936 SizeBits:64] map[Name:filelist OffsetBits:16000 SizeBits:128] map[Name:maxchild OffsetBits:16128 SizeBits:32] map[Name:quirks OffsetBits:16160 SizeBits:32] map[Name:urbnum OffsetBits:16192 SizeBits:32] map[Name:active_duration OffsetBits:16256 SizeBits:64] map[Name:connect_time OffsetBits:16320 SizeBits:64] map[Name:do_remote_wakeup OffsetBits:16384 SizeBits:1] map[Name:reset_resume OffsetBits:16385 SizeBits:1] map[Name:port_is_suspended OffsetBits:16386 SizeBits:1] map[Name:offload_pm_locked OffsetBits:16387 SizeBits:1] map[Name:offload_usage OffsetBits:16416 SizeBits:32] map[Name:offload_lock OffsetBits:16448 SizeBits:1024] map[Name:tunnel_mode OffsetBits:17472 SizeBits:32] map[Name:usb4_link OffsetBits:17536 SizeBits:64] map[Name:slot_id OffsetBits:17600 SizeBits:32] map[Name:l1_params OffsetBits:17632 SizeBits:64] map[Name:u1_params OffsetBits:17696 SizeBits:128] map[Name:u2_params OffsetBits:17824 SizeBits:128] map[Name:lpm_disable_count OffsetBits:17952 SizeBits:32] map[Name:hub_delay OffsetBits:17984 SizeBits:16] map[Name:use_generic_driver OffsetBits:18000 SizeBits:1]]]

152/2 2026/07/30 12:34 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 125282
							output: 39
							thoughts: 251
						

Thoughts:
**Debugging a USB Driver UAF**

Okay, so `dev` is at offset 1408 bits, which is 176 bytes. Alright, 176 bytes for `dev`. And looking at the structure, `type` is at offset 88 bytes within `struct device`. Now we can calculate: `176 + 88 = 264` bytes. Perfect, exactly 264 bytes. That confirms it, the object is a `struct usb_device`. The UAF is definitely accessing `adapter->dev.parent->type`. This points to a USB driver issue. It's registering an I2C adapter and setting `adapter->dev.parent = &usb_device->dev`, but crucially, it's failing to unregister the I2C adapter during the USB device disconnection!

Now, I need to see which drivers are responsible. I've got `go7007`, `si4713`, and `hdpvr` in mind. Let's see how they handle it. Okay, `hdpvr` correctly unregisters in the `disconnect` function. Good! `si4713` unregisters in `release`. And `go7007` unregisters in `remove`, which is called from `release`. Hmm, that's interesting. Are there any other drivers that might have this vulnerability? Let's take a look at `au0828`.



153/2 2026/07/30 12:34 tool grepper
0m Args:
map[Expression:i2c_del_adapter PathPrefix:drivers/media/usb/au0828/]

Results:
map[Output:drivers/media/usb/au0828/au0828-i2c.c=388=int au0828_i2c_unregister(struct au0828_dev *dev)
drivers/media/usb/au0828/au0828-i2c.c-389-{
drivers/media/usb/au0828/au0828-i2c.c:390:	i2c_del_adapter(&dev->i2c_adap);
drivers/media/usb/au0828/au0828-i2c.c-391-	return 0;
]

154/2 2026/07/30 12:34 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 126058
							output: 43
							thoughts: 17
						

Thoughts:
Here's my thought process, summarized as you requested:

**Unregistering the I2C Adapter: Tracing the Call**

Okay, so I need to figure out where the `au0828_i2c_unregister` function is actually being invoked. I'm dealing with the `au0828` driver, so this is likely a critical step in the I2C adapter's lifecycle, potentially during module unloading or device removal. I need to understand the control flow.

My initial approach will be a code search. I'll need to use my tools – likely grep, or perhaps cscope or ctags if the codebase supports it, to locate all instances where `au0828_i2c_unregister` is directly called. I'm expecting to find it within the `au0828` driver source files, or possibly in related cleanup or shutdown functions.

Once I have a list of call sites, I'll need to analyze the surrounding code. I'll need to understand the conditions under which this unregistration occurs. Is it a graceful shutdown triggered by a specific event, or an error-handling path? Is it called when a device is detached, or when the entire module is unloaded? I'll be looking for clues in the context of the call, specifically at things like device state, error codes, and resource management. I'll probably cross-reference the calls with the device model to check what happens in regards to device power management and registration/deregistration.

Ultimately, my goal is to pinpoint the exact circumstances that trigger the I2C adapter unregistration. This is a crucial piece of the puzzle for understanding the driver's overall behavior and ensuring proper resource cleanup.



155/2 2026/07/30 12:34 tool grepper
0m Args:
map[Expression:au0828_i2c_unregister PathPrefix:drivers/media/usb/au0828/]

Results:
map[Output:drivers/media/usb/au0828/au0828-core.c=153=void au0828_usb_release(struct au0828_dev *dev)
--
drivers/media/usb/au0828/au0828-core.c-157-	/* I2C */
drivers/media/usb/au0828/au0828-core.c:158:	au0828_i2c_unregister(dev);
drivers/media/usb/au0828/au0828-core.c-159-
--
drivers/media/usb/au0828/au0828-i2c.c=354=int au0828_i2c_register(struct au0828_dev *dev)
--
drivers/media/usb/au0828/au0828-i2c.c-387-
drivers/media/usb/au0828/au0828-i2c.c:388:int au0828_i2c_unregister(struct au0828_dev *dev)
drivers/media/usb/au0828/au0828-i2c.c-389-{
--
drivers/media/usb/au0828/au0828.h=315=extern int au0828_i2c_register(struct au0828_dev *dev);
drivers/media/usb/au0828/au0828.h:316:extern int au0828_i2c_unregister(struct au0828_dev *dev);
drivers/media/usb/au0828/au0828.h-317-
]

156/2 2026/07/30 12:34 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 126942
							output: 41
							thoughts: 30
						

Thoughts:
Here's my analysis of the provided snippet, framed as my own thought process:

**Diving into the `au0828_usb_release` Function**

Okay, I'm zeroing in on this `au0828_usb_release` function. My initial question is: what's its purpose within the broader context? It's pretty clear that it has been called somewhere. The critical next step is to trace the call graph. I need to understand the dependencies and where this function is invoked. Finding the calling sites will give me crucial context. I need to figure out the scenarios where resources are being released, which will inform my whole understanding of this module's function.



157/2 2026/07/30 12:34 tool grepper
0m Args:
map[Expression:au0828_usb_release PathPrefix:drivers/media/usb/au0828/]

Results:
map[Output:drivers/media/usb/au0828/au0828-core.c=125=static void au0828_unregister_media_device(struct au0828_dev *dev)
--
drivers/media/usb/au0828/au0828-core.c-152-
drivers/media/usb/au0828/au0828-core.c:153:void au0828_usb_release(struct au0828_dev *dev)
drivers/media/usb/au0828/au0828-core.c-154-{
--
drivers/media/usb/au0828/au0828-core.c=163=static void au0828_usb_disconnect(struct usb_interface *interface)
--
drivers/media/usb/au0828/au0828-core.c-186-		/*
drivers/media/usb/au0828/au0828-core.c:187:		 * No need to call au0828_usb_release() if V4L2 is enabled,
drivers/media/usb/au0828/au0828-core.c-188-		 * as this is already called via au0828_usb_v4l2_release()
--
drivers/media/usb/au0828/au0828-core.c-191-	}
drivers/media/usb/au0828/au0828-core.c:192:	au0828_usb_release(dev);
drivers/media/usb/au0828/au0828-core.c-193-}
--
drivers/media/usb/au0828/au0828-video.c=635=static void au0828_usb_v4l2_release(struct v4l2_device *v4l2_dev)
--
drivers/media/usb/au0828/au0828-video.c-642-	au0828_usb_v4l2_media_release(dev);
drivers/media/usb/au0828/au0828-video.c:643:	au0828_usb_release(dev);
drivers/media/usb/au0828/au0828-video.c-644-}
--
drivers/media/usb/au0828/au0828.h=300=extern u32 au0828_write(struct au0828_dev *dev, u16 reg, u32 val);
drivers/media/usb/au0828/au0828.h:301:extern void au0828_usb_release(struct au0828_dev *dev);
drivers/media/usb/au0828/au0828.h-302-extern int au0828_debug;
]

158/2 2026/07/30 12:34 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 127928
							output: 38
							thoughts: 147
						

Thoughts:
**Vulnerability Confirmation and Extension**

Yes! I've confirmed that `au0828` exhibits the exact same vulnerability I suspected! The issue arises because if Video4Linux2 (V4L2) is enabled, which implies that a `/dev/videoX` device is open, the `au0828_usb_disconnect` function preemptively returns and defers the call to `au0828_usb_release` to `au0828_usb_v4l2_release`. This `au0828_usb_v4l2_release` function is then called when the last reference to the `v4l2_dev` structure is dropped, specifically when the file descriptor associated with the `/dev/videoX` device is closed. The timing of those disconnect calls certainly leaves the driver open to abuse in the same way. So, I am confident that `au0828` is, in fact, vulnerable.

Now, a new thought occurs to me... I need to consider `pvrusb2` as well. Does it have the same design?



159/2 2026/07/30 12:34 tool grepper
0m Args:
map[Expression:i2c_del_adapter PathPrefix:drivers/media/usb/pvrusb2/]

Results:
map[Output:drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c=649=void pvr2_i2c_core_done(struct pvr2_hdw *hdw)
--
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c-651-	if (hdw->i2c_linked) {
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c:652:		i2c_del_adapter(&hdw->i2c_adap);
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c-653-		hdw->i2c_linked = 0;
]

160/2 2026/07/30 12:34 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 128549
							output: 42
							thoughts: 17
						

Thoughts:
Okay, here's my attempt at summarizing that thought process, keeping in mind I'm speaking to a fellow expert:

**Tracing the Origins of `pvr2_i2c_core_done`**

Right, so, I need to figure out where the `pvr2_i2c_core_done` function is actually being *called* within the system. That's the key to understanding its execution flow and dependencies. I'm going to have to dive into the codebase and start tracing it back. Where is this function's call being initiated? Is it from a driver, a kernel module, or some other part of the I2C subsystem? I need to track down the call sites to get a handle on the triggering conditions, the context in which it operates, and what data is being passed in. It's a fundamental step in analyzing the function's purpose and how it fits into the broader I2C communication scheme used in that particular system. I expect that tracking this down will allow me to reason about any potential race conditions and other edge cases that might be present.



161/2 2026/07/30 12:34 tool grepper
0m Args:
map[Expression:pvr2_i2c_core_done PathPrefix:drivers/media/usb/pvrusb2/]

Results:
map[Output:drivers/media/usb/pvrusb2/pvrusb2-hdw.c=2705=void pvr2_hdw_disconnect(struct pvr2_hdw *hdw)
--
drivers/media/usb/pvrusb2/pvrusb2-hdw.c-2708-	LOCK_TAKE(hdw->big_lock);
drivers/media/usb/pvrusb2/pvrusb2-hdw.c:2709:	pvr2_i2c_core_done(hdw);
drivers/media/usb/pvrusb2/pvrusb2-hdw.c-2710-	LOCK_TAKE(hdw->ctl_lock);
--
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c=591=void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
--
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c-648-
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c:649:void pvr2_i2c_core_done(struct pvr2_hdw *hdw)
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c-650-{
--
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.h=11=void pvr2_i2c_core_init(struct pvr2_hdw *);
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.h:12:void pvr2_i2c_core_done(struct pvr2_hdw *);
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.h-13-
]

162/2 2026/07/30 12:34 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 129320
							output: 594
							thoughts: 2519
						

Thoughts:
**Analyzing USB Driver Vulnerability and Reproducer Strategies**

Okay, so the initial assessment is that `pvr2_hdw_disconnect` doesn't seem vulnerable, since it calls `pvr2_i2c_core_done` synchronously. This means we should focus on drivers like `au0828`, `go7007`, and `si4713`. However, the `si4713` is a HID device, and `go7007` and `au0828` are vendor-specific.

The primary target here is `au0828`, specifically with the USB IDs `0x2040:0x7200`. The question becomes, can we emulate the `au0828` device using `syz_usb_connect`? It seems we can't directly target `au0828` with a dedicated `syz_usb_connect` call. However, since `syz_usb_connect` takes `dev ptr[in, usb_device_descriptor]`, the strategy is to construct the `usb_device_descriptor` in memory and pass it.

Initially, I considered using `mmap` and `memcpy`, but `memcpy` is not a syzkaller primitive. The workaround is to use `write` and `read` to pipe data into the mmapped memory. However, `pipe2` returns file descriptors as an array, making it difficult to access the array's contents.

A better approach is to leverage the ability to pass pointers to structs within syzkaller. The `usb_device_descriptor` is defined in `vusb.txt`. Trying to create the struct directly within the program is difficult. However, the existing structure definitions in `vusb.txt` provide a literal. So, can we just use that structure literal and populate its values?

There's a catch: `idVendor` is defined as `const[0, int16]`. Passing `0x2040` directly would likely be rejected. But, what if we use `syz_usb_connect$hid`? The documentation says that `syz_usb_connect$hid` utilizes a `usb_device_descriptor_hid` structure, in which `idVendor` is still `const[0, int16]`. However, the syzkaller Go code patches this value. If syzkaller patches it, does it pick from a list of known HID devices?

The next step is to examine whether `si4713` is in the kernel tree. Yes, `drivers/media/radio/si4713/radio-usb-si4713.c` confirms its presence. Given that syzkaller extracts USB IDs from the kernel, it *should* include `0x10c4:0x8244` in the list of known HID devices because syzkaller extracts all `usb_device_id` tables. Thus, using `syz_usb_connect$hid` will randomly select this device. However, this is not a reliable reproducer.

The next potential workaround is to see if `syz_usb_connect` accepts a string for the `dev` argument. Checking the prompt documentation yields a definition for `syz_usb_connect` which takes `dev ptr[in, string]`. However, testing with `&AUTO='\x12\x01...'` fails due to a "wrong string arg" error.

It looks like the initial documentation might be outdated. Looking into the definition of `syz_usb_connect` in `vusb.txt`, it states that `dev` is, in fact, `ptr[in, usb_device_descriptor]`, implying that a struct, rather than a string, is required. It's also noted that trying to use `&AUTO` won't work because `AUTO` is for pointers to structs, and the `dev` is expecting a struct.

The upshot is that a `usb_device_descriptor` must be provided, and `idVendor` is `const[0, int16]`. However, using `syz_usb_connect` allows the Go code to patch the `idVendor`. Since the goal is to trigger the bug related to `au0828`, can we rely on syzkaller patching the `idVendor` to `0x2040` by letting the `idVendor` and `idProduct` fields use `AUTO` to have syzkaller pick values for them? The reasoning is that syzkaller extracts all USB IDs from the kernel. This also means the correct `usb_device_descriptor` must be provided to trigger the vulnerability. So, a generic struct with `AUTO` for the patchable `


163/2 2026/07/30 12:35 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{0x12, 0x1, 0x200, 0, 0, 0, 0x40, 0, 0, 0, 1, 2, 3, 1, [{{0x9, 0x2, 0x19, 1, 1, 0, 0x80, 0xfa, [{{0x9, 0x4, 0, 0, 1, 0xff, 0, 0, 0, [], [{{0x7, 0x5, 0x81, 2, 0x200, 0, 0, 0, []}}]}}]}}]}}, 0)
r1 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r2 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r3 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r4 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r5 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r6 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r3, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r4, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

164/2 2026/07/30 12:35 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 133680
							output: 433
							thoughts: 1837
						

Thoughts:
**Debugging USB Descriptor Structures in Syzkaller**

Okay, so I'm wrestling with how syzkaller is interpreting these USB descriptor structures. It started with a puzzling error, a "wrong array arg *prog.BufferType" message. I need to understand why my struct literals aren't being parsed correctly.

First, I looked at the `usb_config_descriptor`. I saw that it *should* have an `extra` field, which is `void`.  In syzkaller, I initially thought `void` fields *weren't* omitted in struct literals, but then I realized that, since it's `void`, it *should* be omitted.  The key part is the `interfaces` field, an `array[usb_interface_descriptor, 1:4]`. That's where I thought the problem was, expecting a literal like `[{{0x9, 0x4, ...}}]`.

The `usb_interface_descriptor` itself also threw me for a loop. It's defined as a struct with a single field, `inner`. So, I was initially thinking it should be just `{{0x9, 0x4, ...}}`, but then I remembered that `interfaces` is an *array* of `usb_interface_descriptor`, so it needed the extra set of curly braces: `[{{0x9, 0x4, ...}}]`. The structure definition of `usb_interface_descriptor` eventually unraveled to a type named `usb_interface_descriptor_verbose_t`.  Within it, the `extra` field is an `array[usb_interface_extra_descriptor, 0:2]`, and those are unions.

I started to think the problem was with passing an empty array `[]` for `extra`. But then the dreaded `wrong array arg *prog.BufferType` error again. That made me realize that syzkaller expected a buffer, not an array.

Then I realized that `usb_config_descriptor` has an `inner` field. So `[{{...}}]` is an array of `usb_config_descriptor`. And the `usb_device_descriptor` has a `configs` field, which is `array[usb_config_descriptor, 1]`, and so `configs` should be `[{{...}}]`. Inside `usb_config_descriptor`, there is an array of `interfaces` as `array[usb_interface_descriptor, 1:4]`. The problem must be the same as before.

I went back to carefully examine the `usb_config_descriptor_verbose_t` definition, making sure to track the data types and sizes.  The fields, in order, are: `bLength`, `bDescriptorType`, `wTotalLength`, `bNumInterfaces`, `bConfigurationValue`, `iConfiguration`, `bmAttributes`, `bMaxPower`, and finally, the array of `interfaces`. Everything lines up! The `EXTRA` is `void`, so it's omitted.

I checked my literal: `{0x9, 0x2, 0x19, 1, 1, 0, 0x80, 0xfa, [{{0x9, 0x4, ...}}]}`. This matches the structure's fields. I still can't explain the `*prog.BufferType` error, despite this. I confirmed that the inner structure is indeed a struct, not a buffer. I'm stumped as to why it’s not working!

Perhaps this has something to do with the specific syzcall I'm calling. Rather than crafting these structs by hand, let me see if I can leverage the existing syzkaller infrastructure. I'll try using `&AUTO=AUTO` with `syz_usb_connect$hid`. It looks like that takes `dev ptr[in, usb_device_descriptor_hid]`, and hopefully, syzkaller will automatically generate a valid struct for me!



165/2 2026/07/30 12:35 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect$hid(3, 0, &AUTO=AUTO, 0)
r1 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r2 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r3 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r4 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r5 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r6 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r3, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r4, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

166/2 2026/07/30 12:35 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 136822
							output: 536
							thoughts: 304
						

Thoughts:
**Syzkaller Syntax Quandary**

Okay, so I'm wrestling with how to handle this struct within the syzkaller context. I initially thought I could simply use `AUTO` for the whole thing, but then I remembered that won't work if it contains any flags or unions. Right, and `&AUTO=AUTO` is clearly invalid syntax. Hmm, but I *can* use just `&AUTO` by itself, which seems promising. Hang on… if I'm referencing the pointer `ptr[in, usb_device_descriptor_hid]`, then `&AUTO` should be perfectly acceptable!

Let me double-check the syzkaller syntax just to be sure. Alright, it's defined as `pointer-arg = "&" pointer-arg-addr ["=ANY"] "=" arg`. Wait a minute, the `arg` part is required! That means I have to provide the struct itself... Ugh. But wait, can I get away with `&AUTO={}`? No, that just creates an empty struct.

Okay, let's back up a step. If I try `&AUTO=ANY="..."`, it fails because `ANY` expects a union option, of course. So, what about `&AUTO=ANY=@ANYBLOB="1201..."`? That could be the key!

I need to confirm if `ANYBLOB` is a valid union option within the `ANY` union. Time to go back to the syzkaller documentation. Ah, yes, here it is: `ANY` is indeed a union, containing `ANYRES16`, `ANYRES32`, `ANYRES64`, and the crucial `ANYBLOB`, which is an array of `int8`. So, it looks like `&AUTO=ANY=@ANYBLOB="1201..."` just might be the correct syntax! Now that's the one to try next!



167/2 2026/07/30 12:35 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0x2b, &(0x7f0000000000)=ANY=@ANYBLOB="1201000200000040402000720000010203010902190001010080fa0904000001ff00000007058102000200", 0)
r1 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r2 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r3 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r4 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r5 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r6 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r3, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r4, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

168/2 2026/07/30 12:35 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 138231
							output: 705
							thoughts: 294
						

Thoughts:
**Debugging the Blob Conversion**

Okay, so I'm dealing with `ANYBLOB` here, and immediately I remember that it's defined as `array[int8]`.  Therefore, it's expecting an array literal representation – something like `[...]` – and not a raw string. That's the root of the problem.

Let's adjust the argument to reflect this. I need to make sure I format the data as an array of hex values. I think this will work: `&AUTO=ANY=@ANYBLOB=[0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x40, 0x20, 0x00, 0x72, 0x00, 0x00, 0x01, 0x02, 0x03, 0x01, 0x09, 0x02, 0x19, 0x00, 0x01, 0x01, 0x00, 0x80, 0xfa, 0x09, 0x04, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 0x00, 0x02, 0x00]`. That should be the right format.



169/2 2026/07/30 12:35 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0x2b, &(0x7f0000000000)=ANY=@ANYBLOB=[0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x40, 0x20, 0x00, 0x72, 0x00, 0x00, 0x01, 0x02, 0x03, 0x01, 0x09, 0x02, 0x19, 0x00, 0x01, 0x01, 0x00, 0x80, 0xfa, 0x09, 0x04, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 0x00, 0x02, 0x00], 0)
r1 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r2 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r3 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r4 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r5 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r6 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r3, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r4, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

170/2 2026/07/30 12:35 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 139940
							output: 626
							thoughts: 1046
						

Thoughts:
**Debugging USB Device Descriptor Construction**

Okay, so I'm trying to figure out how to properly define a USB device descriptor for fuzzing. I just realized `ANYBLOB` isn't a valid option for `ANY` in this context. Let's go back and check the definition of `ANY` in syzkaller to be sure. I was hoping I could just use `syz_usb_connect$hid` with `&AUTO=AUTO`, but I remember hitting an issue with `AUTO` and flags before; I got that "wrong type" error. Right, because `AUTO` can't be used directly for flags. I can't just use `&AUTO={}` either, since that would provide an empty struct.

My next idea is that if I focus on `syz_usb_connect$hid`, I can manually construct a valid descriptor, using `AUTO` for the non-flag fields. Looking at the struct definition for `usb_device_descriptor_hid`, I see that `bcdUSB` is a `usb_versions, int16`, so I can provide `0x200` for it. The `bMaxPacketSize0` is `flags[usb_device_max_packet_sizes, int8]`, so I'll provide `64`.

Okay, I'm constructing `usb_device_descriptor_hid`, bit by bit. I need to now construct the nested structs and data. The inner `usb_config_descriptor_hid` has an `interfaces` field, which is an array of `usb_interface_descriptor_hid`. Inside that, there's `extra`, which is a `usb_hid_descriptor_hid`. The `usb_hid_descriptor_hid` has `report_desc`, so I need to construct that. Then there's `endpoints`, which is `usb_endpoint_descriptors_hid`, containing the in and out endpoints.

Now, I'm carefully constructing the full structure, filling in the values I've figured out. I need to make sure I'm matching the correct sizes and data types. I'll construct it, and then I'll use it. Let's try this now and see if I'm on the right track!



171/2 2026/07/30 12:36 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect$hid(3, 0, &AUTO={{0x12, 0x1, 0x200, 0, 0, 0, 64, 0, 0, 0, 1, 2, 3, 1, [{{0x9, 0x2, 0x22, 1, 1, 0, 0x80, 0xfa, [{{0x9, 0x4, 0, 0, 1, 3, 0, 0, 0, {0x9, 0x21, 0x111, 0, 1, {0x22, 0x3f}}, {{{0x7, 0x5, 0x81, 3, 8, 10, 0, 0, []}}, []}}}]}}]}}, 0)
r1 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r2 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r3 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r4 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r5 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r6 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r3, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r4, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

172/2 2026/07/30 12:36 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 142345
							output: 431
							thoughts: 1460
						

Thoughts:
**Debugging a USB Configuration Descriptor**

Okay, here we go again with this "wrong array arg" error for `*prog.BufferType`. Why is it treating the `interfaces` field like a buffer when it should be a struct array? Let's trace this. `usb_config_descriptor_hid`... that's where we start. It seems to wrap an `usb_config_descriptor_ifaces_array_t`. Alright, that type definition uses `usb_config_descriptor_t`, which in turn leads to `usb_config_descriptor_verbose_t`.  Nested types, got it.

Now, `usb_config_descriptor_verbose_t` defines `interfaces` as `IFS`, and looking at the types, the extra field is `void`, so that is not presented in the resulting struct. This `interfaces` field is the ninth one. But the `usb_config_descriptor_hid` struct is really just a wrapper for `usb_config_descriptor_ifaces_array_t`, which is the nested struct. So, it should be a struct with just one member. The resulting hex looks correct: `{{0x9, 0x2, ...}}`. And `configs` is an array of these. So `configs` would be: `[{{0x9, 0x2, ...}}]`. I have: `[{{0x9, 0x2, 0x22, 1, 1, 0, 0x80, 0xfa, [{{...}}]}}]`.

Wait, maybe `interfaces` isn't an array of structs like I think it is. But, it is defined in the type as `array[usb_interface_descriptor_hid, 1]`. And `usb_interface_descriptor_hid` is another struct. So, this should be: `{{0x9, 0x4, ...}}`. and `interfaces` is `[{{0x9, 0x4, ...}}]`. Exactly what I have! This should work.

Why the "wrong array arg" error? Could it be related to the `len[interfaces, int8]` within `usb_config_descriptor_ifaces_array_t`? It is actually used for `bNumInterfaces`. I am using `1` in the literal, the correct value for the example. And, `len` fields can be `AUTO`. So I could use `AUTO` for all of the fixed-size fields, making this simpler.

Wait, if the parser is expecting a buffer, maybe it's because of `len[interfaces, int8]`.

Let's check `usb_config_descriptor_verbose_t` again. `interfaces` is, indeed, defined as `array[usb_interface_descriptor_hid, 1]`. That *should* be an array of structs.

Why would the parser expect a buffer then? Is `usb_interface_descriptor_hid` somehow resolving to a buffer? No, it's a struct.

Wait... maybe `usb_config_descriptor_hid` isn't what I think it is! Let's check a similar type definition. Hmm, `usb_device_descriptor_hid` uses a similar structure, and looks like the last argument in the nested struct is `array[usb_config_descriptor_hid, 1]`. I don't think I am missing anything here... it is an array of structs.

Wait, I can just cheat and let syzkaller generate the descriptor!  Use `syz_usb_connect$hid` with `&AUTO`. But wait, I had that "wrong type" error when I tried `=AUTO`.

Ah, because I used `=AUTO`, that's the problem.  What if I just do `syz_usb_connect$hid(3, 0, &AUTO, 0)`?  `&AUTO` without an initialization is not valid for a struct pointer. Hmm, but if I don't provide the value, syzkaller will just give me a random valid one! Let's try that... `syz_usb_connect$hid(3, 0, &AUTO, 0)`!



173/2 2026/07/30 12:36 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect$hid(3, 0, &AUTO, 0)
r1 = openat$video0(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r2 = openat$video1(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r3 = openat$i2c0(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r4 = openat$i2c1(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r5 = openat$i2c2(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r6 = openat$i2c3(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r3, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r4, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

174/2 2026/07/30 12:36 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 145158
							output: 405
							thoughts: 63
						

Thoughts:
Here's my take on the situation:

**Debugging a Kernel Interaction in Syzkaller**

Alright, so I was looking at this trace and hit a snag. The system call, `openat$video0`, is throwing a wrench in the works – it's not a recognized syscall. My first thought was, "Darn it! What's going on?"

Then, I had a moment of clarity, remembering that in the Syzkaller context, I don't need those descriptive suffixes. The tool already distinguishes based on other factors. I added that suffix just to differentiate in my mental model, but that's not how it's defined. Duh! I should just be using the standard `openat` syscall.

Time to correct that and see if this solves the problem!



175/2 2026/07/30 12:36 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect$hid(3, 0, &AUTO, 0)
r1 = openat(0xffffffffffffff9c, &AUTO='/dev/video0\x00', 0, 0)
r2 = openat(0xffffffffffffff9c, &AUTO='/dev/video1\x00', 0, 0)
r3 = openat(0xffffffffffffff9c, &AUTO='/dev/i2c-0\x00', 0, 0)
r4 = openat(0xffffffffffffff9c, &AUTO='/dev/i2c-1\x00', 0, 0)
r5 = openat(0xffffffffffffff9c, &AUTO='/dev/i2c-2\x00', 0, 0)
r6 = openat(0xffffffffffffff9c, &AUTO='/dev/i2c-3\x00', 0, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r3, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r4, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

176/2 2026/07/30 12:36 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 146740
							output: 22
							thoughts: 229
						

Thoughts:
**Debugging I2C Device Interaction**

Okay, so I'm hitting some snags with this I2C interface. First, it looks like when dealing with filenames, specifically when I'm escaping them, I need to make sure I'm not using the null byte (`\x00`). That's a classic pitfall. Now, that "out-of-tree result" message - I think that means I can't just pass `r3` into the `ioctl` call if `r3` isn't pointing to a valid resource or if it's not handled by the kernel. Let me think...

Ah, right, `openat` gives me a file descriptor (`fd`), but the `ioctl` function I'm calling, specifically the `I2C_SMBUS` variant, is expecting a dedicated `fd_i2c` type. So, I need to figure out how to reconcile those. I'm going to need to do some casting, or maybe there's a specific `openat$i2c` wrapper call. I'll check if there's such a thing. That would be ideal – a streamlined approach.

Let's look around for that. I'm going to start with the obvious places, namely `sys/linux/dev_i2c.txt` and `sys/linux/fs.txt`. I need to figure out the right way to initialize it so I can pass it to `ioctl`.

Okay, I think I've got it. Can I simply use `openat$i2c(0xffffffffffffff9c, &AUTO='/dev/i2c-0', 0, 0)`? I'll double-check `dev_i2c.txt` and confirm my assumptions about the arguments for this function.



177/2 2026/07/30 12:36 tool read-description
0m Args:
map[File:dev_i2c.txt]

Results:
map[Output:# Copyright 2018 syzkaller project authors. All rights reserved.
# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

include <uapi/linux/i2c-dev.h>
include <uapi/linux/i2c.h>

define I2C_MAX_BLOCK_1	(I2C_SMBUS_BLOCK_MAX + 1)
define I2C_MAX_BLOCK_2	(I2C_SMBUS_BLOCK_MAX + 2)

resource fd_i2c[fd]

syz_open_dev$I2C(dev ptr[in, string["/dev/i2c-#"]], id intptr, flags flags[open_flags]) fd_i2c

ioctl$I2C_RETRIES(fd fd_i2c, cmd const[I2C_RETRIES], arg intptr)
ioctl$I2C_TIMEOUT(fd fd_i2c, cmd const[I2C_TIMEOUT], arg intptr)
ioctl$I2C_SLAVE(fd fd_i2c, cmd const[I2C_SLAVE], arg intptr[0:0x3ff])
ioctl$I2C_SLAVE_FORCE(fd fd_i2c, cmd const[I2C_SLAVE_FORCE], arg intptr[0:0x3ff])
ioctl$I2C_TENBIT(fd fd_i2c, cmd const[I2C_TENBIT], arg boolptr)
ioctl$I2C_PEC(fd fd_i2c, cmd const[I2C_PEC], arg intptr)

ioctl$I2C_FUNCS(fd fd_i2c, cmd const[I2C_FUNCS], arg ptr[in, intptr])
ioctl$I2C_RDWR(fd fd_i2c, cmd const[I2C_RDWR], arg ptr[in, i2c_rdwr_ioctl_data])
ioctl$I2C_SMBUS(fd fd_i2c, cmd const[I2C_SMBUS], arg ptr[in, i2c_smbus_ioctl_data])

i2c_smbus_ioctl_data {
	read_write	bool8
	command		int8
	size		int32[I2C_SMBUS_QUICK:I2C_SMBUS_I2C_BLOCK_DATA]
	data		ptr[in, i2c_smbus_data]
}

i2c_smbus_data {
	size	int8[0:I2C_MAX_BLOCK_2]
	block	array[int8, I2C_MAX_BLOCK_1]
}

i2c_rdwr_ioctl_data {
	msgs	ptr[in, array[i2c_msg]]
	nmsgs	len[msgs, int32]
}

i2c_msg {
	addr	int16
	flags	flags[i2c_msg_flags, int16]
	len	len[buf, int16]
	buf	ptr[in, array[int8]]
}

i2c_msg_flags = I2C_M_RD, I2C_M_TEN, I2C_M_DMA_SAFE, I2C_M_RECV_LEN, I2C_M_NO_RD_ACK, I2C_M_IGNORE_NAK, I2C_M_REV_DIR_ADDR, I2C_M_NOSTART, I2C_M_STOP
]

178/2 2026/07/30 12:36 llm crash-repro-finder
1m Model:
gemini-3.1-pro-preview

Tokens:
							input: 148218
							output: 22
							thoughts: 98
						

Thoughts:
**Initial Assessment & Hypothesis**

Okay, so I've got this system call, `syz_open_dev$I2C`, that takes a device path, an identifier, and some flags, and returns a file descriptor for I2C devices. Got it. Based on that function, I'm thinking I should use `syz_open_dev$I2C` for anything I2C-related. That seems straightforward. Now, the next question is about video devices. My initial hunch is that I'll need something like `syz_open_dev$video`. It makes logical sense, but I need to confirm that. Time to consult `dev_video4linux.txt`. That documentation should have all the details I need to nail down the correct syz call to use.



179/2 2026/07/30 12:37 tool read-description
0m Args:
map[File:dev_video4linux.txt]

Results:
map[Output:# Copyright 2018 syzkaller project authors. All rights reserved.
# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

include <linux/time.h>
include <linux/types.h>
include <uapi/asm/ioctl.h>
include <uapi/linux/fcntl.h>
include <uapi/linux/videodev2.h>
include <uapi/linux/v4l2-common.h>
include <uapi/linux/v4l2-subdev.h>
include <uapi/linux/v4l2-mediabus.h>
include <uapi/linux/media-bus-format.h>
include <uapi/linux/v4l2-controls.h>
include <uapi/linux/media.h>

resource fd_video[fd]
resource fd_v4l2_buffer[fd]

syz_open_dev$video(dev ptr[in, string["/dev/video#"]], id intptr, flags flags[open_flags]) fd_video
syz_open_dev$video4linux(dev ptr[in, string["/dev/v4l-subdev#"]], id intptr, flags flags[open_flags]) fd_video

# TODO: we now get wrong values for ioctl commands that involve v4l2_buffer and v4l2_event.
# Our definition uses 32-bit timespec, while kernel uses 64-bit timespec when __KERNEL__ is defined.

# Special support for CONFIG_VIDEO_VIMC/VIM2M/VIVID/VICODEC.
# Here we assume that all of them are enabled and the following arguments are passed on command line:
# vivid.n_devs=16 vivid.multiplanar=1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2
openat$vimc0(fd const[AT_FDCWD], file ptr[in, string["/dev/video0"]], flags const[O_RDWR], mode const[0]) fd_video
openat$vimc1(fd const[AT_FDCWD], file ptr[in, string["/dev/video1"]], flags const[O_RDWR], mode const[0]) fd_video
openat$vimc2(fd const[AT_FDCWD], file ptr[in, string["/dev/video2"]], flags const[O_RDWR], mode const[0]) fd_video
syz_open_dev$vivid(dev ptr[in, string["/dev/video#"]], id proc[3, 4], flags const[O_RDWR]) fd_video
openat$vicodec0(fd const[AT_FDCWD], file ptr[in, string["/dev/video36"]], flags const[O_RDWR], mode const[0]) fd_video
openat$vicodec1(fd const[AT_FDCWD], file ptr[in, string["/dev/video37"]], flags const[O_RDWR], mode const[0]) fd_video
# TODO: there are some complex rules as to what ioctl's are applicable to what devices
# (see determine_valid_ioctls in v4l2-dev.c). We don't have these rules described.
# Currently we just apply all ioctl's to all v4l devices.
syz_open_dev$swradio(dev ptr[in, string["/dev/swradio#"]], id proc[0, 2], flags const[O_RDWR]) fd_video
syz_open_dev$radio(dev ptr[in, string["/dev/radio#"]], id proc[0, 4], flags const[O_RDWR]) fd_video
syz_open_dev$vbi(dev ptr[in, string["/dev/vbi#"]], id proc[0, 4], flags const[O_RDWR]) fd_video

ioctl$VIDIOC_QUERYCAP(fd fd_video, cmd const[VIDIOC_QUERYCAP], arg ptr[out, v4l2_capability])
ioctl$VIDIOC_ENUM_FMT(fd fd_video, cmd const[VIDIOC_ENUM_FMT], arg ptr[inout, v4l2_fmtdesc[v4l2_buf_type]])
ioctl$VIDIOC_G_FMT(fd fd_video, cmd const[VIDIOC_G_FMT], arg ptr[inout, v4l2_format[v4l2_buf_type]])
ioctl$VIDIOC_S_FMT(fd fd_video, cmd const[VIDIOC_S_FMT], arg ptr[inout, v4l2_format[v4l2_buf_type]])
ioctl$VIDIOC_REQBUFS(fd fd_video, cmd const[VIDIOC_REQBUFS], arg ptr[inout, v4l2_requestbuffers[v4l2_buf_type]])
# This variant serves as fd_v4l2_buffer constructor.
# Potentially more ioctl can create fd_v4l2_buffer, but the kernel code is hard to understand.
ioctl$VIDIOC_QUERYBUF_DMABUF(fd fd_video, cmd const[VIDIOC_QUERYBUF], arg ptr[inout, v4l2_buffer[v4l2_buf_type, V4L2_MEMORY_DMABUF, fd_v4l2_buffer]])
ioctl$VIDIOC_QUERYBUF(fd fd_video, cmd const[VIDIOC_QUERYBUF], arg ptr[inout, v4l2_buffer_t[v4l2_buf_type]])
ioctl$VIDIOC_G_FBUF(fd fd_video, cmd const[VIDIOC_G_FBUF], arg ptr[inout, v4l2_framebuffer])
ioctl$VIDIOC_S_FBUF(fd fd_video, cmd const[VIDIOC_S_FBUF], arg ptr[in, v4l2_framebuffer])
ioctl$VIDIOC_OVERLAY(fd fd_video, cmd const[VIDIOC_OVERLAY], arg ptr[in, int32])
ioctl$VIDIOC_QBUF(fd fd_video, cmd const[VIDIOC_QBUF], arg ptr[inout, v4l2_buffer_t[v4l2_buf_type]])
ioctl$VIDIOC_EXPBUF(fd fd_video, cmd const[VIDIOC_EXPBUF], arg ptr[inout, v4l2_exportbuffer[v4l2_buf_type]])
ioctl$VIDIOC_DQBUF(fd fd_video, cmd const[VIDIOC_DQBUF], arg ptr[inout, v4l2_buffer_t[v4l2_buf_type]])
ioctl$VIDIOC_STREAMON(fd fd_video, cmd const[VIDIOC_STREAMON], arg ptr[in, int32])
ioctl$VIDIOC_STREAMOFF(fd fd_video, cmd const[VIDIOC_STREAMOFF], arg ptr[in, int32])
ioctl$VIDIOC_G_PARM(fd fd_video, cmd const[VIDIOC_G_PARM], arg ptr[inout, v4l2_streamparm])
ioctl$VIDIOC_S_PARM(fd fd_video, cmd const[VIDIOC_S_PARM], arg ptr[inout, v4l2_streamparm])
ioctl$VIDIOC_G_STD(fd fd_video, cmd const[VIDIOC_G_STD], arg ptr[out, v4l2_std_id])
ioctl$VIDIOC_S_STD(fd fd_video, cmd const[VIDIOC_S_STD], arg ptr[in, v4l2_std_id])
ioctl$VIDIOC_ENUMSTD(fd fd_video, cmd const[VIDIOC_ENUMSTD], arg ptr[inout, v4l2_standard])
ioctl$VIDIOC_ENUMINPUT(fd fd_video, cmd const[VIDIOC_ENUMINPUT], arg ptr[inout, v4l2_input])
ioctl$VIDIOC_G_CTRL(fd fd_video, cmd const[VIDIOC_G_CTRL], arg ptr[inout, v4l2_control])
ioctl$VIDIOC_S_CTRL(fd fd_video, cmd const[VIDIOC_S_CTRL], arg ptr[inout, v4l2_control])
ioctl$VIDIOC_G_TUNER(fd fd_video, cmd const[VIDIOC_G_TUNER], arg ptr[inout, v4l2_tuner])
ioctl$VIDIOC_S_TUNER(fd fd_video, cmd const[VIDIOC_S_TUNER], arg ptr[in, v4l2_tuner])
ioctl$VIDIOC_G_AUDIO(fd fd_video, cmd const[VIDIOC_G_AUDIO], arg ptr[out, v4l2_audio])
ioctl$VIDIOC_S_AUDIO(fd fd_video, cmd const[VIDIOC_S_AUDIO], arg ptr[in, v4l2_audio])
ioctl$VIDIOC_QUERYCTRL(fd fd_video, cmd const[VIDIOC_QUERYCTRL], arg ptr[inout, v4l2_queryctrl])
ioctl$VIDIOC_QUERYMENU(fd fd_video, cmd const[VIDIOC_QUERYMENU], arg ptr[inout, v4l2_querymenu])
ioctl$VIDIOC_G_INPUT(fd fd_video, cmd const[VIDIOC_G_INPUT], arg ptr[out, int32])
ioctl$VIDIOC_S_INPUT(fd fd_video, cmd const[VIDIOC_S_INPUT], arg ptr[inout, int32])
ioctl$VIDIOC_G_EDID(fd fd_video, cmd const[VIDIOC_G_EDID], arg ptr[inout, v4l2_edid])
ioctl$VIDIOC_S_EDID(fd fd_video, cmd const[VIDIOC_S_EDID], arg ptr[inout, v4l2_edid])
ioctl$VIDIOC_G_OUTPUT(fd fd_video, cmd const[VIDIOC_G_OUTPUT], arg ptr[out, int32])
ioctl$VIDIOC_S_OUTPUT(fd fd_video, cmd const[VIDIOC_S_OUTPUT], arg ptr[inout, int32])
ioctl$VIDIOC_ENUMOUTPUT(fd fd_video, cmd const[VIDIOC_ENUMOUTPUT], arg ptr[inout, v4l2_output])
ioctl$VIDIOC_G_AUDOUT(fd fd_video, cmd const[VIDIOC_G_AUDOUT], arg ptr[out, v4l2_audioout])
ioctl$VIDIOC_S_AUDOUT(fd fd_video, cmd const[VIDIOC_S_AUDOUT], arg ptr[in, v4l2_audioout])
ioctl$VIDIOC_G_MODULATOR(fd fd_video, cmd const[VIDIOC_G_MODULATOR], arg ptr[inout, v4l2_modulator])
ioctl$VIDIOC_S_MODULATOR(fd fd_video, cmd const[VIDIOC_S_MODULATOR], arg ptr[in, v4l2_modulator])
ioctl$VIDIOC_G_FREQUENCY(fd fd_video, cmd const[VIDIOC_G_FREQUENCY], arg ptr[inout, v4l2_frequency])
ioctl$VIDIOC_S_FREQUENCY(fd fd_video, cmd const[VIDIOC_S_FREQUENCY], arg ptr[in, v4l2_frequency])
ioctl$VIDIOC_CROPCAP(fd fd_video, cmd const[VIDIOC_CROPCAP], arg ptr[inout, v4l2_cropcap])
ioctl$VIDIOC_G_CROP(fd fd_video, cmd const[VIDIOC_G_CROP], arg ptr[inout, v4l2_crop])
ioctl$VIDIOC_S_CROP(fd fd_video, cmd const[VIDIOC_S_CROP], arg ptr[in, v4l2_crop])
ioctl$VIDIOC_G_JPEGCOMP(fd fd_video, cmd const[VIDIOC_G_JPEGCOMP], arg ptr[out, v4l2_jpegcompression])
ioctl$VIDIOC_S_JPEGCOMP(fd fd_video, cmd const[VIDIOC_S_JPEGCOMP], arg ptr[in, v4l2_jpegcompression])
ioctl$VIDIOC_QUERYSTD(fd fd_video, cmd const[VIDIOC_QUERYSTD], arg ptr[out, v4l2_std_id])
ioctl$VIDIOC_TRY_FMT(fd fd_video, cmd const[VIDIOC_TRY_FMT], arg ptr[inout, v4l2_format[v4l2_buf_type]])
ioctl$VIDIOC_ENUMAUDIO(fd fd_video, cmd const[VIDIOC_ENUMAUDIO], arg ptr[inout, v4l2_audio])
ioctl$VIDIOC_ENUMAUDOUT(fd fd_video, cmd const[VIDIOC_ENUMAUDOUT], arg ptr[inout, v4l2_audioout])
ioctl$VIDIOC_G_PRIORITY(fd fd_video, cmd const[VIDIOC_G_PRIORITY], arg flags[v4l2_priority])
ioctl$VIDIOC_S_PRIORITY(fd fd_video, cmd const[VIDIOC_S_PRIORITY], arg flags[v4l2_priority])
ioctl$VIDIOC_G_SLICED_VBI_CAP(fd fd_video, cmd const[VIDIOC_G_SLICED_VBI_CAP], arg ptr[inout, v4l2_sliced_vbi_cap])
ioctl$VIDIOC_LOG_STATUS(fd fd_video, cmd const[VIDIOC_LOG_STATUS], arg const[0])
ioctl$VIDIOC_G_EXT_CTRLS(fd fd_video, cmd const[VIDIOC_G_EXT_CTRLS], arg ptr[inout, v4l2_ext_controls])
ioctl$VIDIOC_S_EXT_CTRLS(fd fd_video, cmd const[VIDIOC_S_EXT_CTRLS], arg ptr[inout, v4l2_ext_controls])
ioctl$VIDIOC_TRY_EXT_CTRLS(fd fd_video, cmd const[VIDIOC_TRY_EXT_CTRLS], arg ptr[inout, v4l2_ext_controls])
ioctl$VIDIOC_ENUM_FRAMESIZES(fd fd_video, cmd const[VIDIOC_ENUM_FRAMESIZES], arg ptr[inout, v4l2_frmsizeenum])
ioctl$VIDIOC_ENUM_FRAMEINTERVALS(fd fd_video, cmd const[VIDIOC_ENUM_FRAMEINTERVALS], arg ptr[inout, v4l2_frmivalenum])
ioctl$VIDIOC_G_ENC_INDEX(fd fd_video, cmd const[VIDIOC_G_ENC_INDEX], arg ptr[out, v4l2_enc_idx])
ioctl$VIDIOC_ENCODER_CMD(fd fd_video, cmd const[VIDIOC_ENCODER_CMD], arg ptr[inout, v4l2_encoder_cmd])
ioctl$VIDIOC_TRY_ENCODER_CMD(fd fd_video, cmd const[VIDIOC_TRY_ENCODER_CMD], arg ptr[inout, v4l2_encoder_cmd])
ioctl$VIDIOC_DBG_S_REGISTER(fd fd_video, cmd const[VIDIOC_DBG_S_REGISTER], arg ptr[in, v4l2_dbg_register])
ioctl$VIDIOC_DBG_G_REGISTER(fd fd_video, cmd const[VIDIOC_DBG_G_REGISTER], arg ptr[inout, v4l2_dbg_register])
ioctl$VIDIOC_S_HW_FREQ_SEEK(fd fd_video, cmd const[VIDIOC_S_HW_FREQ_SEEK], arg ptr[in, v4l2_hw_freq_seek])
ioctl$VIDIOC_S_DV_TIMINGS(fd fd_video, cmd const[VIDIOC_S_DV_TIMINGS], arg ptr[inout, v4l2_dv_timings])
ioctl$VIDIOC_G_DV_TIMINGS(fd fd_video, cmd const[VIDIOC_G_DV_TIMINGS], arg ptr[inout, v4l2_dv_timings])
ioctl$VIDIOC_DQEVENT(fd fd_video, cmd const[VIDIOC_DQEVENT], arg ptr[out, v4l2_event])
ioctl$VIDIOC_SUBSCRIBE_EVENT(fd fd_video, cmd const[VIDIOC_SUBSCRIBE_EVENT], arg ptr[in, v4l2_event_subscription])
ioctl$VIDIOC_UNSUBSCRIBE_EVENT(fd fd_video, cmd const[VIDIOC_UNSUBSCRIBE_EVENT], arg ptr[in, v4l2_event_subscription])
ioctl$VIDIOC_CREATE_BUFS(fd fd_video, cmd const[VIDIOC_CREATE_BUFS], arg ptr[inout, v4l2_create_buffers[v4l2_buf_type]])
ioctl$VIDIOC_PREPARE_BUF(fd fd_video, cmd const[VIDIOC_PREPARE_BUF], arg ptr[inout, v4l2_buffer_t[v4l2_buf_type]])
ioctl$VIDIOC_G_SELECTION(fd fd_video, cmd const[VIDIOC_G_SELECTION], arg ptr[inout, v4l2_selection])
ioctl$VIDIOC_S_SELECTION(fd fd_video, cmd const[VIDIOC_S_SELECTION], arg ptr[inout, v4l2_selection])
ioctl$VIDIOC_DECODER_CMD(fd fd_video, cmd const[VIDIOC_DECODER_CMD], arg ptr[inout, v4l2_decoder_cmd])
ioctl$VIDIOC_TRY_DECODER_CMD(fd fd_video, cmd const[VIDIOC_TRY_DECODER_CMD], arg ptr[inout, v4l2_decoder_cmd])
ioctl$VIDIOC_ENUM_DV_TIMINGS(fd fd_video, cmd const[VIDIOC_ENUM_DV_TIMINGS], arg ptr[inout, v4l2_enum_dv_timings])
ioctl$VIDIOC_QUERY_DV_TIMINGS(fd fd_video, cmd const[VIDIOC_QUERY_DV_TIMINGS], arg ptr[out, v4l2_dv_timings])
ioctl$VIDIOC_DV_TIMINGS_CAP(fd fd_video, cmd const[VIDIOC_DV_TIMINGS_CAP], arg ptr[inout, v4l2_dv_timings_cap])
ioctl$VIDIOC_ENUM_FREQ_BANDS(fd fd_video, cmd const[VIDIOC_ENUM_FREQ_BANDS], arg ptr[inout, v4l2_frequency_band])
ioctl$VIDIOC_DBG_G_CHIP_INFO(fd fd_video, cmd const[VIDIOC_DBG_G_CHIP_INFO], arg ptr[inout, v4l2_dbg_chip_info])
ioctl$VIDIOC_QUERY_EXT_CTRL(fd fd_video, cmd const[VIDIOC_QUERY_EXT_CTRL], arg ptr[inout, v4l2_query_ext_ctrl])
ioctl$VIDIOC_SUBDEV_G_FMT(fd fd_video, cmd const[VIDIOC_SUBDEV_G_FMT], arg ptr[inout, v4l2_subdev_format])
ioctl$VIDIOC_SUBDEV_S_FMT(fd fd_video, cmd const[VIDIOC_SUBDEV_S_FMT], arg ptr[inout, v4l2_subdev_format])
ioctl$VIDIOC_SUBDEV_G_FRAME_INTERVAL(fd fd_video, cmd const[VIDIOC_SUBDEV_G_FRAME_INTERVAL], arg ptr[inout, v4l2_subdev_frame_interval])
ioctl$VIDIOC_SUBDEV_S_FRAME_INTERVAL(fd fd_video, cmd const[VIDIOC_SUBDEV_S_FRAME_INTERVAL], arg ptr[inout, v4l2_subdev_frame_interval])
ioctl$VIDIOC_SUBDEV_ENUM_MBUS_CODE(fd fd_video, cmd const[VIDIOC_SUBDEV_ENUM_MBUS_CODE], arg ptr[inout, v4l2_subdev_mbus_code_enum])
ioctl$VIDIOC_SUBDEV_ENUM_FRAME_SIZE(fd fd_video, cmd const[VIDIOC_SUBDEV_ENUM_FRAME_SIZE], arg ptr[inout, v4l2_subdev_frame_size_enum])
ioctl$VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL(fd fd_video, cmd const[VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL], arg ptr[inout, v4l2_subdev_frame_interval_enum])
ioctl$VIDIOC_SUBDEV_G_CROP(fd fd_video, cmd const[VIDIOC_SUBDEV_G_CROP], arg ptr[inout, v4l2_subdev_crop])
ioctl$VIDIOC_SUBDEV_S_CROP(fd fd_video, cmd const[VIDIOC_SUBDEV_S_CROP], arg ptr[inout, v4l2_subdev_crop])
ioctl$VIDIOC_SUBDEV_G_SELECTION(fd fd_video, cmd const[VIDIOC_SUBDEV_G_SELECTION], arg ptr[inout, v4l2_subdev_selection])
ioctl$VIDIOC_SUBDEV_S_SELECTION(fd fd_video, cmd const[VIDIOC_SUBDEV_S_SELECTION], arg ptr[inout, v4l2_subdev_selection])
ioctl$VIDIOC_SUBDEV_G_EDID(fd fd_video, cmd const[VIDIOC_SUBDEV_G_EDID], arg ptr[inout, v4l2_edid])
ioctl$VIDIOC_SUBDEV_S_EDID(fd fd_video, cmd const[VIDIOC_SUBDEV_S_EDID], arg ptr[inout, v4l2_edid])
ioctl$VIDIOC_SUBDEV_S_DV_TIMINGS(fd fd_video, cmd const[VIDIOC_SUBDEV_S_DV_TIMINGS], arg ptr[inout, v4l2_dv_timings])
ioctl$VIDIOC_SUBDEV_G_DV_TIMINGS(fd fd_video, cmd const[VIDIOC_SUBDEV_G_DV_TIMINGS], arg ptr[inout, v4l2_dv_timings])
ioctl$VIDIOC_SUBDEV_ENUM_DV_TIMINGS(fd fd_video, cmd const[VIDIOC_SUBDEV_ENUM_DV_TIMINGS], arg ptr[inout, v4l2_enum_dv_timings])
ioctl$VIDIOC_SUBDEV_QUERY_DV_TIMINGS(fd fd_video, cmd const[VIDIOC_SUBDEV_QUERY_DV_TIMINGS], arg ptr[out, v4l2_dv_timings])
ioctl$VIDIOC_SUBDEV_DV_TIMINGS_CAP(fd fd_video, cmd const[VIDIOC_SUBDEV_DV_TIMINGS_CAP], arg ptr[inout, v4l2_dv_timings_cap])

# Generally we don't specify close on resources,
# but fd_v4l2_buffer is not used as input anywhere else (why is it needed?).
# So this is added to prevent compilation errors.
close$fd_v4l2_buffer(fd fd_v4l2_buffer)

v4l2_capability {
	driver		array[int8, 16]
	card		array[int8, 32]
	bus_info	array[int8, 32]
	version		int32
	capabilities	flags[v4l2_capability_capabilities, int32]
	device_caps	int32
	reserved	array[const[0, int32], 3]
}

type v4l2_fmtdesc[BUF_TYPE] {
	index		int32
	type		flags[BUF_TYPE, int32]
	flags		flags[v4l2_fmtdesc_flags, int32]
	description	array[int8, 32]
	pixelformat	flags[v4l2_pix_format_pixelformat, int32]
	reserved	array[const[0, int32], 4]
}

type v4l2_format[BUF_TYPE] {
	type	flags[BUF_TYPE, int32]
	fmt	v4l2_format_fmt
}

v4l2_format_fmt [
	pix		v4l2_pix_format
	pix_mp		v4l2_pix_format_mplane
	win		v4l2_window
	vbi		v4l2_vbi_format
	sliced		v4l2_sliced_vbi_format
	sdr		v4l2_sdr_format
	meta		v4l2_meta_format
	raw_data	array[int8, 200]
]

v4l2_pix_format {
	width		int32
	height		int32
	pixelformat	flags[v4l2_pix_format_pixelformat, int32]
	field		flags[v4l2_field, int32]
	bytesperline	int32
	sizeimage	int32
	colorspace	flags[v4l2_colorspace, int32]
	priv		int32
	flags		flags[v4l2_pix_format_flags, int32]
	ycbcr_enc	flags[v4l2_ycbcr_encoding, int32]
	quantization	flags[v4l2_quantization, int32]
	xfer_func	flags[v4l2_xfer_func, int32]
}

v4l2_pix_format_mplane {
	width		int32
	height		int32
	pixelformat	flags[v4l2_pix_format_pixelformat, int32]
	field		flags[v4l2_field, int32]
	colorspace	flags[v4l2_colorspace, int32]
	plane_fmt	array[v4l2_plane_pix_format, 8]
	num_planes	int8
	flags		int8
	ycbcr_enc	flags[v4l2_ycbcr_encoding, int8]
	quantization	flags[v4l2_quantization, int8]
	xfer_func	flags[v4l2_xfer_func, int8]
	reserved	array[const[0, int8], 7]
} [packed]

v4l2_plane_pix_format {
	sizeimage	int32
	bytesperline	int32
	reserved	array[const[0, int16], 6]
} [packed]

v4l2_window {
	w		v4l2_rect
	field		flags[v4l2_field, int32]
	chromakey	int32
	clips		ptr[inout, v4l2_clip]
	clipcount	int32
	bitmap		buffer[inout]
	global_alpha	int8
}

v4l2_rect {
	left	int32
	top	int32
	width	int32
	height	int32
}

v4l2_clip {
	c	v4l2_rect
	next	ptr[inout, v4l2_clip, opt]
}

v4l2_vbi_format {
	sampling_rate		int32
	offset			int32
	samples_per_line	int32
	sample_format		flags[v4l2_pix_format_pixelformat, int32]
	start			array[int32, 2]
	count			array[int32, 2]
	flags			flags[v4l2_vbi_format_flags, int32]
	reserved		array[const[0, int32], 2]
}

v4l2_sliced_vbi_format {
	service_set	int16
	service_lines	array[int16, 48]
	io_size		int32
	reserved	array[const[0, int32], 2]
}

v4l2_sdr_format {
	pixelformat	flags[v4l2_pix_format_pixelformat, int32]
	buffersize	int32
	reserved	array[const[0, int8], 24]
} [packed]

v4l2_meta_format {
	dataformat	flags[v4l2_meta_data_formats, int32]
	buffersize	int32[0:0x7fffffff]
	width		int32[0:65535]
	height		int32[0:65535]
	bytesperline	int32[0:0x7fffffff]
} [packed]

type v4l2_requestbuffers[BUF_TYPE] {
	count		int32
	type		flags[BUF_TYPE, int32]
	memory		flags[v4l2_memory, int32]
	capabilities	const[0, int32]
	flags		int8
	reserved	array[const[0, int8], 3]
}

type v4l2_buffer_t[BUF_TYPE] [
	mmap			v4l2_buffer[BUF_TYPE, V4L2_MEMORY_MMAP, intptr]
	userptr			v4l2_buffer[BUF_TYPE, V4L2_MEMORY_USERPTR, ptr[out, int8]]
	overlay			v4l2_buffer[BUF_TYPE, V4L2_MEMORY_OVERLAY, int32]
	fd			v4l2_buffer[BUF_TYPE, V4L2_MEMORY_DMABUF, fd_v4l2_buffer[opt]]
	multiplanar_mmap	v4l2_buffer[BUF_TYPE, V4L2_MEMORY_MMAP, ptr[inout, array[v4l2_plane[intptr], 2]]]
	multiplanar_userptr	v4l2_buffer[BUF_TYPE, V4L2_MEMORY_USERPTR, ptr[inout, array[v4l2_plane[ptr[out, int8]], 2]]]
	multiplanar_overlay	v4l2_buffer[BUF_TYPE, V4L2_MEMORY_OVERLAY, ptr[inout, array[v4l2_plane[int32], 2]]]
	multiplanar_fd		v4l2_buffer[BUF_TYPE, V4L2_MEMORY_DMABUF, ptr[inout, array[v4l2_plane[fd_v4l2_buffer[opt]], 2]]]
]

# TODO: The field directions needs to be defined. Recursively v4l2_plane, v4l2_plane_union needs checking.
type v4l2_buffer[BUF_TYPE, MEM_TYPE, ARG_TYPE] {
	index		int32
	type		flags[BUF_TYPE, int32]
	bytesused	len[type, int32]
	flags		flags[v4l2_buffer_flags, int32]
	field		int32
	timestamp	timeval
	timecode	v4l2_timecode
	sequence	int32
	memory		const[MEM_TYPE, int32]
	m		alignptr[ARG_TYPE]	(out)
	length		int32
	reserved2	const[0, int32]
	request_fd	fd_request[opt]
}

v4l2_timecode {
	type		flags[v4l2_timecode_type, int32]
	flags		flags[v4l2_timecode_flags, int32]
	frames		int8
	seconds		int8
	minutes		int8
	hours		int8
	userbits	array[int8, 4]
}

type v4l2_plane[ARG_TYPE] {
	bytesused	int32
	length		int32
	m		alignptr[ARG_TYPE]
	data_offset	int32
	reserved	array[const[0, int32], 11]
}

v4l2_framebuffer {
	capability	flags[v4l2_framebuffer_capability, int32]
	flags		flags[v4l2_framebuffer_flags, int32]
	base		buffer[inout]
	fmt		v4l2_framebuffer_union
}

v4l2_framebuffer_union {
	width		int32
	height		int32
	pixelformat	flags[v4l2_pix_format_pixelformat, int32]
	field		flags[v4l2_field, int32]
	bytesperline	int32
	sizeimage	int32
	colorspace	flags[v4l2_colorspace, int32]
	priv		int32
}

type v4l2_exportbuffer[BUF_TYPE] {
	type		flags[BUF_TYPE, int32]
	index		int32
	plane		int32
	flags		flags[pipe_flags, int32]
	fd		fd_dma_buf	(out)
	reserved	array[const[0, int32], 11]
}

v4l2_streamparm {
	type	flags[v4l2_buf_type, int32]
	parm	v4l2_streamparm_union
}

v4l2_streamparm_union [
	capture		v4l2_captureparm
	output		v4l2_outputparm
	raw_data	array[int8, 200]
]

v4l2_captureparm {
	capability	flags[v4l2_captureparm_cap, int32]
	capturemode	flags[v4l2_captureparm_mode, int32]
	timeperframe	v4l2_fract
	extendedmode	int32
	readbuffers	int32
	reserved	array[const[0, int32], 4]
}

v4l2_fract {
	numerator	int32
	denominator	int32
}

v4l2_outputparm {
	capability	flags[v4l2_captureparm_cap, int32]
	outputmode	flags[v4l2_captureparm_mode, int32]
	timeperframe	v4l2_fract
	extendedmode	int32
	writebuffers	int32
	reserved	array[const[0, int32], 4]
}

v4l2_control {
	id	int32
	value	int32
}

v4l2_tuner {
	index		int32
	name		array[int8, 32]
	type		flags[v4l2_tuner_type, int32]
	capability	flags[v4l2_tuner_capability, int32]
	rangelow	int32
	rangehigh	int32
	rxsubchans	flags[v4l2_tuner_rxsubchans, int32]
	audmode		flags[v4l2_tuner_audmode, int32]
	signal		int32
	afc		int32
	reserved	array[const[0, int32], 4]
}

v4l2_audio {
	index		int32
	name		array[int8, 32]
	capability	flags[v4l2_audio_capability, int32]
	mode		flags[v4l2_audio_mode, int32]
	reserved	array[const[0, int32], 2]
}

v4l2_queryctrl {
	id		int32
	type		flags[v4l2_ctrl_type, int32]
	name		array[int8, 32]
	minimum		int32
	maximum		int32
	step		int32
	default_value	int32
	flags		flags[v4l2_control_flags, int32]
	reserved	array[const[0, int32], 2]
}

v4l2_querymenu {
	id		int32
	index		int32
	union		v4l2_querymenu_union
	reserved	const[0, int32]
} [packed]

v4l2_querymenu_union [
	name	array[int8, 32]
	value	int64
]

v4l2_edid {
	pad		const[0, int32]
	start_block	int32
	blocks		int32
	reserved	array[const[0, int32], 5]
	edid		ptr[inout, int8]
}

v4l2_audioout {
	index		int32
	name		array[int8, 32]
	capability	flags[v4l2_audio_capability, int32]
	mode		flags[v4l2_audio_mode, int32]
	reserved	array[const[0, int32], 2]
}

v4l2_modulator {
	index		int32
	name		array[int8, 32]
	capability	flags[v4l2_tuner_capability, int32]
	rangelow	int32
	rangehigh	int32
	txsubchans	flags[v4l2_tuner_rxsubchans, int32]
	type		flags[v4l2_tuner_type, int32]
	reserved	array[const[0, int32], 3]
}

v4l2_frequency {
	tuner		int32
	type		flags[v4l2_tuner_type, int32]
	frequency	int32
	reserved	array[const[0, int32], 8]
}

v4l2_cropcap {
	type		flags[v4l2_buf_type, int32]
	bounds		v4l2_rect
	defrect		v4l2_rect
	pixelaspect	v4l2_fract
}

v4l2_crop {
	type	flags[v4l2_buf_type, int32]
	c	v4l2_rect
}

v4l2_jpegcompression {
	quality		int32
	APPn		int32[0:15]
	APP_len		int32[0:60]
	APP_data	array[int8, 60]
	COM_len		int32[0:60]
	COM_data	array[int8, 60]
	jpeg_markers	flags[v4l2_jpeg_markers, int32]
}

v4l2_sliced_vbi_cap {
	service_set	int16
	service_lines	array[int16, 48]
	type		flags[v4l2_buf_type, int32]
	reserved	array[const[0, int32], 3]
}

v4l2_ext_controls {
	ctrl_class	flags[v4l2_ext_ctrl_class, int32]
	count		int32
	error_idx	int32
	request_fd	fd_request[opt]	(in)
	reserved	const[0, int32]
	controls	ptr[inout, v4l2_ext_control]
}

v4l2_ext_control {
	id		flags[v4l2_ext_controls, int32]
	size		int32
	reserved2	array[const[0, int32], 1]
	union		v4l2_ext_u
} [packed]

v4l2_ext_u [
	value	int32
	value64	int64
	string	ptr[inout, int8]
	p_u8	ptr[inout, int8]
	p_u16	ptr[inout, int16]
	p_u32	ptr[inout, int32]
	ptr	intptr
]

v4l2_frmsizeenum {
	index		int32
	pixel_format	flags[v4l2_pix_format_pixelformat, int32]
	type		flags[v4l2_frmsizetypes, int32]
	union		v4l2_frmsizeenum_union
	reserved	array[const[0, int32], 2]
}

v4l2_frmsizeenum_union [
	discrete	v4l2_frmsize_discrete
	stepwise	v4l2_frmsize_stepwise
]

v4l2_frmsize_discrete {
	width	int32
	height	int32
}

v4l2_frmsize_stepwise {
	min_width	int32
	max_width	int32
	step_width	int32
	min_height	int32
	max_height	int32
	step_height	int32
}

v4l2_frmivalenum {
	index		int32
	pixel_format	flags[v4l2_pix_format_pixelformat, int32]
	width		int32
	height		int32
	type		flags[v4l2_frmivaltypes, int32]
	union		v4l2_frmivalenum_union
	reserved	array[const[0, int32], 2]
}

v4l2_frmivalenum_union [
	discrete	v4l2_fract
	stepwise	v4l2_frmival_stepwise
]

v4l2_frmival_stepwise {
	min	v4l2_fract
	max	v4l2_fract
	step	v4l2_fract
}

v4l2_enc_idx {
	entries		int32
	entries_cap	int32
	reserved	array[const[0, int32], 4]
	entry		array[v4l2_enc_idx_entry, 64]
}

v4l2_enc_idx_entry {
	offset		int64
	pts		int64
	length		int32
	flags		flags[v4l2_enc_idx_flags, int32]
	reserved	array[const[0, int32], 2]
}

v4l2_dbg_register {
	match	v4l2_dbg_match
	size	bytesize[reg, int32]
	reg	int64
	val	int64
} [packed]

v4l2_dbg_match {
	type	flags[v4l2_dbg_match_type, int32]
	union	v4l2_dbg_match_union
} [packed]

v4l2_dbg_match_union [
	addr	int32
	name	array[int8, 32]
]

v4l2_hw_freq_seek {
	tuner		int32
	type		flags[v4l2_tuner_type, int32]
	seek_upward	int32
	wrap_around	int32
	spacing		int32
	rangelow	int32
	rangehigh	int32
	reserved	array[const[0, int32], 5]
}

v4l2_dv_timings {
	type	flags[v4l2_dv_timings_type, int32]
	union	v4l2_dv_timings_union
} [packed]

v4l2_dv_timings_union [
	bt		v4l2_bt_timings
	reserved	array[const[0, int32], 32]
]

v4l2_bt_timings {
	width		int32
	height		int32
	interlaced	flags[v4l2_bt_timings_interlaced, int32]
	polarities	flags[v4l2_bt_timings_polarities, int32]
	pixelclock	int64
	hfrontporch	int32
	hsync		int32
	hbackporch	int32
	vfrontporch	int32
	vsync		int32
	vbackporch	int32
	il_vfrontporch	int32
	il_vsync	int32
	il_vbackporch	int32
	standards	flags[v4l2_bt_timings_standards, int32]
	flags		flags[v4l2_bt_timings_flags, int32]
	picture_aspect	v4l2_fract
	cea861_vic	int8
	hdmi_vic	int8
	reserved	array[const[0, int8], 46]
} [packed]

v4l2_encoder_cmd {
	cmd	flags[v4l2_encoder_cmd_cmd, int32]
	flags	flags[v4l2_encoder_flags, int32]
	data	array[int32, 8]
}

v4l2_event {
	type		flags[v4l2_event_type, int32]
	u		v4l2_event_union
	pending		int32
	sequence	int32
	timestamp	timespec
	id		int32
	reserved	array[const[0, int32], 8]
}

v4l2_event_union [
	vsync		v4l2_event_vsync
	ctrl		v4l2_event_ctrl
	frame_sync	v4l2_event_frame_sync
	src_change	v4l2_event_src_change
	motion_det	v4l2_event_motion_det
	data		array[int8, 64]
]

v4l2_event_vsync {
	field	flags[v4l2_field_1, int8]
} [packed]

v4l2_event_ctrl {
	changes		flags[v4l2_event_ctrl_changes, int32]
	type		flags[v4l2_ctrl_type, int32]
	u		v4l2_event_ctrl_union
	flags		int32
	minimum		int32
	maximum		int32
	step		int32
	default_value	int32
}

v4l2_event_ctrl_union [
	value	int32
	value64	int64
]

v4l2_event_frame_sync {
	frame_sequence	int32
}

v4l2_event_src_change {
	changes	flags[v4l2_event_src_changes, int32]
}

v4l2_event_motion_det {
	flags		flags[v4l2_event_motion_det_flags, int32]
	frame_sequence	int32
	region_mask	int32
}

v4l2_event_subscription {
	type		flags[v4l2_event_type, int32]
	id		int32
	flags		flags[v4l2_event_subscription_flags, int32]
	reserved	array[const[0, int32], 5]
}

type v4l2_create_buffers[BUF_TYPE] {
	index		int32
	count		int32
	memory		flags[v4l2_memory, int32]
	format		v4l2_format[BUF_TYPE]
	capabilities	int32
	reserved	array[const[0, int32], 7]
}

v4l2_selection {
	type		flags[v4l2_buf_type_1, int32]
	target		flags[v4l2_selection_target, int32]
	flags		flags[v4l2_selection_flags, int32]
	r		v4l2_rect
	reserved	array[const[0, int32], 9]
}

v4l2_decoder_cmd {
	cmd	flags[v4l2_decoder_cmd_cmd, int32]
	flags	flags[v4l2_decoder_cmd_flags, int32]
	u	v4l2_decoder_cmd_u
}

v4l2_decoder_cmd_u [
	stop_pts	int64
	start		v4l2_decoder_cmd_start
	raw_data	array[int32, 16]
]

v4l2_decoder_cmd_start {
	speed	int32
	format	flags[v4l2_decoder_cmd_format, int32]
}

v4l2_enum_dv_timings {
	index		int32
	pad		const[0, int32]
	reserved	array[const[0, int32], 2]
	timings		v4l2_dv_timings
}

v4l2_dv_timings_cap {
	type		flags[v4l2_dv_timings_type, int32]
	pad		const[0, int32]
	reserved	array[const[0, int32], 2]
	u		v4l2_dv_timings_cap_u
}

v4l2_dv_timings_cap_u [
	bt		v4l2_bt_timings_cap
	raw_data	array[int32, 32]
]

v4l2_bt_timings_cap {
	min_width	int32
	max_width	int32
	min_height	int32
	max_height	int32
	min_pixelclock	int64
	max_pixelclock	int64
	standards	flags[v4l2_bt_timings_standards, int32]
	capabilities	flags[v4l2_bt_timings_cap_capabilities, int32]
	reserved	array[const[0, int32], 16]
} [packed]

v4l2_frequency_band {
	tuner		int32
	type		flags[v4l2_tuner_type, int32]
	index		int32
	capability	flags[v4l2_tuner_capability, int32]
	rangelow	int32
	rangehigh	int32
	modulation	flags[v4l2_frequency_band_modulation, int32]
	reserved	array[const[0, int32], 9]
}

v4l2_dbg_chip_info {
	match		v4l2_dbg_match
	name		array[int8, 32]
	flags		flags[v4l2_dbg_chip_info_flags, int32]
	reserved	array[const[0, int32], 32]
} [packed]

v4l2_query_ext_ctrl {
	id		flags[v4l2_query_ext_ctrl, int32]
	type		flags[v4l2_ctrl_type, int32]
	name		array[int8, 32]
	minimum		int64
	maximum		int64
	step		int64
	default_value	int64
	flags		int32
	elem_size	int32
	elems		int32
	nr_of_dims	int32
	dims		array[int32, 4]
	reserved	array[const[0, int32], 32]
}

type v4l2_std_id flags[v4l2_std_id, int64]

v4l2_standard {
	index		int32
	id		v4l2_std_id
	name		array[int8, 24]
	frameperiod	v4l2_fract
	framelines	int32
	reserved	array[const[0, int32], 4]
}

v4l2_input {
	index		int32
	name		array[int8, 32]
	type		flags[v4l2_input_type, int32]
	audioset	int32
	tuner		flags[v4l2_tuner_type, int32]
	std		v4l2_std_id
	status		flags[v4l2_input_status, int32]
	capabilities	flags[v4l2_input_capabilities, int32]
	reserved	array[const[0, int32], 3]
}

v4l2_output {
	index		int32
	name		array[int8, 32]
	type		flags[v4l2_output_type, int32]
	audioset	int32
	modulator	int32
	std		v4l2_std_id
	capabilities	flags[v4l2_output_capabilities, int32]
	reserved	array[const[0, int32], 3]
}

v4l2_subdev_format {
	which		flags[v4l2_subdev_format_whence, int32]
	pad		const[0, int32]
	format		v4l2_mbus_framefmt
	reserved	array[const[0, int32], 8]
}

v4l2_mbus_framefmt {
	width		int32
	height		int32
	code		flags[media_bus_fmt, int32]
	field		flags[v4l2_field, int32]
	colorspace	flags[v4l2_colorspace, int32]
	ycbcr_enc	flags[v4l2_ycbcr_encoding, int16]
	quantization	flags[v4l2_quantization, int16]
	xfer_func	flags[v4l2_xfer_func, int16]
	reserved	array[const[0, int16], 11]
}

v4l2_subdev_frame_interval {
	pad		const[0, int32]
	interval	v4l2_fract
	reserved	array[const[0, int32], 9]
}

v4l2_subdev_mbus_code_enum {
	pad		const[0, int32]
	index		int32
	code		flags[media_bus_fmt, int32]
	which		flags[v4l2_subdev_format_whence, int32]
	reserved	array[const[0, int32], 8]
}

v4l2_subdev_frame_size_enum {
	index		int32
	pad		const[0, int32]
	code		flags[media_bus_fmt, int32]
	min_width	int32
	max_width	int32
	min_height	int32
	max_height	int32
	which		flags[v4l2_subdev_format_whence, int32]
	reserved	array[const[0, int32], 8]
}

v4l2_subdev_frame_interval_enum {
	index		int32
	pad		const[0, int32]
	code		flags[media_bus_fmt, int32]
	width		int32
	height		int32
	interval	v4l2_fract
	which		flags[v4l2_subdev_format_whence, int32]
	reserved	array[const[0, int32], 8]
}

v4l2_subdev_crop {
	which		flags[v4l2_subdev_format_whence, int32]
	pad		const[0, int32]
	rect		v4l2_rect
	reserved	array[const[0, int32], 8]
}

v4l2_subdev_selection {
	which		flags[v4l2_subdev_format_whence, int32]
	pad		const[0, int32]
	target		flags[v4l2_selection_target, int32]
	flags		flags[v4l2_selection_flags, int32]
	r		v4l2_rect
	reserved	array[const[0, int32], 8]
}

v4l2_jpeg_markers = V4L2_JPEG_MARKER_DHT, V4L2_JPEG_MARKER_DQT, V4L2_JPEG_MARKER_DRI, V4L2_JPEG_MARKER_COM, V4L2_JPEG_MARKER_APP
v4l2_subdev_format_whence = V4L2_SUBDEV_FORMAT_TRY, V4L2_SUBDEV_FORMAT_ACTIVE
v4l2_buf_type_1 = V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_BUF_TYPE_VIDEO_OUTPUT, V4L2_BUF_TYPE_VIDEO_OVERLAY, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_BUF_TYPE_VBI_OUTPUT, V4L2_BUF_TYPE_SLICED_VBI_CAPTURE, V4L2_BUF_TYPE_SLICED_VBI_OUTPUT, V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY, V4L2_BUF_TYPE_SDR_CAPTURE, V4L2_BUF_TYPE_SDR_OUTPUT, V4L2_BUF_TYPE_META_CAPTURE, V4L2_BUF_TYPE_META_OUTPUT
v4l2_field_1 = V4L2_FIELD_ANY, V4L2_FIELD_NONE, V4L2_FIELD_TOP, V4L2_FIELD_BOTTOM
v4l2_field = V4L2_FIELD_INTERLACED, V4L2_FIELD_SEQ_TB, V4L2_FIELD_SEQ_BT, V4L2_FIELD_ALTERNATE, V4L2_FIELD_INTERLACED_TB, V4L2_FIELD_INTERLACED_BT, v4l2_field_1
v4l2_colorspace = V4L2_COLORSPACE_DEFAULT, V4L2_COLORSPACE_SMPTE170M, V4L2_COLORSPACE_SMPTE240M, V4L2_COLORSPACE_REC709, V4L2_COLORSPACE_BT878, V4L2_COLORSPACE_470_SYSTEM_M, V4L2_COLORSPACE_470_SYSTEM_BG, V4L2_COLORSPACE_JPEG, V4L2_COLORSPACE_SRGB, V4L2_COLORSPACE_OPRGB, V4L2_COLORSPACE_BT2020, V4L2_COLORSPACE_RAW, V4L2_COLORSPACE_DCI_P3
v4l2_ycbcr_encoding = V4L2_YCBCR_ENC_DEFAULT, V4L2_YCBCR_ENC_601, V4L2_YCBCR_ENC_709, V4L2_YCBCR_ENC_XV601, V4L2_YCBCR_ENC_XV709, V4L2_YCBCR_ENC_BT2020, V4L2_YCBCR_ENC_BT2020_CONST_LUM, V4L2_YCBCR_ENC_SMPTE240M
v4l2_quantization = V4L2_QUANTIZATION_DEFAULT, V4L2_QUANTIZATION_FULL_RANGE, V4L2_QUANTIZATION_LIM_RANGE
v4l2_xfer_func = V4L2_XFER_FUNC_DEFAULT, V4L2_XFER_FUNC_709, V4L2_XFER_FUNC_SRGB, V4L2_XFER_FUNC_OPRGB, V4L2_XFER_FUNC_SMPTE240M, V4L2_XFER_FUNC_NONE, V4L2_XFER_FUNC_DCI_P3, V4L2_XFER_FUNC_SMPTE2084
v4l2_buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, v4l2_buf_type_1
v4l2_memory = V4L2_MEMORY_MMAP, V4L2_MEMORY_USERPTR, V4L2_MEMORY_OVERLAY, V4L2_MEMORY_DMABUF
v4l2_tuner_type = V4L2_TUNER_RADIO, V4L2_TUNER_ANALOG_TV, V4L2_TUNER_DIGITAL_TV, V4L2_TUNER_SDR, V4L2_TUNER_RF
v4l2_ctrl_type = V4L2_CTRL_TYPE_INTEGER, V4L2_CTRL_TYPE_BOOLEAN, V4L2_CTRL_TYPE_MENU, V4L2_CTRL_TYPE_BUTTON, V4L2_CTRL_TYPE_INTEGER64, V4L2_CTRL_TYPE_CTRL_CLASS, V4L2_CTRL_TYPE_STRING, V4L2_CTRL_TYPE_BITMASK, V4L2_CTRL_TYPE_INTEGER_MENU, V4L2_CTRL_COMPOUND_TYPES, V4L2_CTRL_TYPE_U8, V4L2_CTRL_TYPE_U16, V4L2_CTRL_TYPE_U32, V4L2_CTRL_TYPE_AREA, V4L2_CTRL_TYPE_RECT, V4L2_CTRL_TYPE_HDR10_CLL_INFO, V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY, V4L2_CTRL_TYPE_H264_SPS, V4L2_CTRL_TYPE_H264_PPS, V4L2_CTRL_TYPE_H264_SCALING_MATRIX, V4L2_CTRL_TYPE_H264_SLICE_PARAMS, V4L2_CTRL_TYPE_H264_DECODE_PARAMS, V4L2_CTRL_TYPE_H264_PRED_WEIGHTS, V4L2_CTRL_TYPE_FWHT_PARAMS, V4L2_CTRL_TYPE_VP8_FRAME, V4L2_CTRL_TYPE_MPEG2_QUANTISATION, V4L2_CTRL_TYPE_MPEG2_SEQUENCE, V4L2_CTRL_TYPE_MPEG2_PICTURE, V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR, V4L2_CTRL_TYPE_VP9_FRAME, V4L2_CTRL_TYPE_HEVC_SPS, V4L2_CTRL_TYPE_HEVC_PPS, V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS, V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX, V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS, V4L2_CTRL_TYPE_AV1_SEQUENCE, V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY, V4L2_CTRL_TYPE_AV1_FRAME, V4L2_CTRL_TYPE_AV1_FILM_GRAIN
v4l2_priority = V4L2_PRIORITY_UNSET, V4L2_PRIORITY_BACKGROUND, V4L2_PRIORITY_INTERACTIVE, V4L2_PRIORITY_RECORD, V4L2_PRIORITY_DEFAULT
media_bus_fmt = MEDIA_BUS_FMT_FIXED, MEDIA_BUS_FMT_RGB444_1X12, MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE, MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE, MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, MEDIA_BUS_FMT_RGB565_1X16, MEDIA_BUS_FMT_BGR565_2X8_BE, MEDIA_BUS_FMT_BGR565_2X8_LE, MEDIA_BUS_FMT_RGB565_2X8_BE, MEDIA_BUS_FMT_RGB565_2X8_LE, MEDIA_BUS_FMT_RGB666_1X18, MEDIA_BUS_FMT_RBG888_1X24, MEDIA_BUS_FMT_RGB666_1X24_CPADHI, MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, MEDIA_BUS_FMT_BGR888_1X24, MEDIA_BUS_FMT_GBR888_1X24, MEDIA_BUS_FMT_RGB888_1X24, MEDIA_BUS_FMT_RGB888_2X12_BE, MEDIA_BUS_FMT_RGB888_2X12_LE, MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, MEDIA_BUS_FMT_ARGB8888_1X32, MEDIA_BUS_FMT_RGB888_1X32_PADHI, MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_UV8_1X8, MEDIA_BUS_FMT_UYVY8_1_5X8, MEDIA_BUS_FMT_VYUY8_1_5X8, MEDIA_BUS_FMT_YUYV8_1_5X8, MEDIA_BUS_FMT_YVYU8_1_5X8, MEDIA_BUS_FMT_UYVY8_2X8, MEDIA_BUS_FMT_VYUY8_2X8, MEDIA_BUS_FMT_YUYV8_2X8, MEDIA_BUS_FMT_YVYU8_2X8, MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_UYVY10_2X10, MEDIA_BUS_FMT_VYUY10_2X10, MEDIA_BUS_FMT_YUYV10_2X10, MEDIA_BUS_FMT_YVYU10_2X10, MEDIA_BUS_FMT_Y12_1X12, MEDIA_BUS_FMT_UYVY12_2X12, MEDIA_BUS_FMT_VYUY12_2X12, MEDIA_BUS_FMT_YUYV12_2X12, MEDIA_BUS_FMT_YVYU12_2X12, MEDIA_BUS_FMT_UYVY8_1X16, MEDIA_BUS_FMT_VYUY8_1X16, MEDIA_BUS_FMT_YUYV8_1X16, MEDIA_BUS_FMT_YVYU8_1X16, MEDIA_BUS_FMT_YDYUYDYV8_1X16, MEDIA_BUS_FMT_UYVY10_1X20, MEDIA_BUS_FMT_VYUY10_1X20, MEDIA_BUS_FMT_YUYV10_1X20, MEDIA_BUS_FMT_YVYU10_1X20, MEDIA_BUS_FMT_VUY8_1X24, MEDIA_BUS_FMT_YUV8_1X24, MEDIA_BUS_FMT_UYVY12_1X24, MEDIA_BUS_FMT_VYUY12_1X24, MEDIA_BUS_FMT_YUYV12_1X24, MEDIA_BUS_FMT_YVYU12_1X24, MEDIA_BUS_FMT_YUV10_1X30, MEDIA_BUS_FMT_AYUV8_1X32, MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8, MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8, MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8, MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8, MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8, MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8, MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8, MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE, MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE, MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE, MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_JPEG_1X8, MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8, MEDIA_BUS_FMT_AHSV8888_1X32
v4l2_pix_format_flags = V4L2_PIX_FMT_FLAG_PREMUL_ALPHA
v4l2_pix_format_pixelformat = V4L2_PIX_FMT_RGB332, V4L2_PIX_FMT_RGB444, V4L2_PIX_FMT_ARGB444, V4L2_PIX_FMT_XRGB444, V4L2_PIX_FMT_RGB555, V4L2_PIX_FMT_ARGB555, V4L2_PIX_FMT_XRGB555, V4L2_PIX_FMT_RGB565, V4L2_PIX_FMT_RGB555X, V4L2_PIX_FMT_ARGB555X, V4L2_PIX_FMT_XRGB555X, V4L2_PIX_FMT_RGB565X, V4L2_PIX_FMT_BGR666, V4L2_PIX_FMT_BGR24, V4L2_PIX_FMT_RGB24, V4L2_PIX_FMT_BGR32, V4L2_PIX_FMT_ABGR32, V4L2_PIX_FMT_XBGR32, V4L2_PIX_FMT_RGB32, V4L2_PIX_FMT_ARGB32, V4L2_PIX_FMT_XRGB32, V4L2_PIX_FMT_GREY, V4L2_PIX_FMT_Y4, V4L2_PIX_FMT_Y6, V4L2_PIX_FMT_Y10, V4L2_PIX_FMT_Y12, V4L2_PIX_FMT_Y16, V4L2_PIX_FMT_Y16_BE, V4L2_PIX_FMT_Y10BPACK, V4L2_PIX_FMT_PAL8, V4L2_PIX_FMT_UV8, V4L2_PIX_FMT_YUYV, V4L2_PIX_FMT_YYUV, V4L2_PIX_FMT_YVYU, V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_VYUY, V4L2_PIX_FMT_Y41P, V4L2_PIX_FMT_YUV444, V4L2_PIX_FMT_YUV555, V4L2_PIX_FMT_YUV565, V4L2_PIX_FMT_YUV32, V4L2_PIX_FMT_HI240, V4L2_PIX_FMT_NV12_16L16, V4L2_PIX_FMT_M420, V4L2_PIX_FMT_NV12, V4L2_PIX_FMT_NV21, V4L2_PIX_FMT_NV16, V4L2_PIX_FMT_NV61, V4L2_PIX_FMT_NV24, V4L2_PIX_FMT_NV42, V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_NV21M, V4L2_PIX_FMT_NV16M, V4L2_PIX_FMT_NV61M, V4L2_PIX_FMT_NV12MT, V4L2_PIX_FMT_NV12MT_16X16, V4L2_PIX_FMT_YUV410, V4L2_PIX_FMT_YVU410, V4L2_PIX_FMT_YUV411P, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_YVU420, V4L2_PIX_FMT_YUV422P, V4L2_PIX_FMT_YUV420M, V4L2_PIX_FMT_YVU420M, V4L2_PIX_FMT_YUV422M, V4L2_PIX_FMT_YVU422M, V4L2_PIX_FMT_YUV444M, V4L2_PIX_FMT_YVU444M, V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SGBRG8, V4L2_PIX_FMT_SGRBG8, V4L2_PIX_FMT_SRGGB8, V4L2_PIX_FMT_SBGGR10, V4L2_PIX_FMT_SGBRG10, V4L2_PIX_FMT_SGRBG10, V4L2_PIX_FMT_SRGGB10, V4L2_PIX_FMT_SBGGR10P, V4L2_PIX_FMT_SGBRG10P, V4L2_PIX_FMT_SGRBG10P, V4L2_PIX_FMT_SRGGB10P, V4L2_PIX_FMT_SBGGR10ALAW8, V4L2_PIX_FMT_SGBRG10ALAW8, V4L2_PIX_FMT_SGRBG10ALAW8, V4L2_PIX_FMT_SRGGB10ALAW8, V4L2_PIX_FMT_SBGGR10DPCM8, V4L2_PIX_FMT_SGBRG10DPCM8, V4L2_PIX_FMT_SGRBG10DPCM8, V4L2_PIX_FMT_SRGGB10DPCM8, V4L2_PIX_FMT_SBGGR12, V4L2_PIX_FMT_SGBRG12, V4L2_PIX_FMT_SGRBG12, V4L2_PIX_FMT_SRGGB12, V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_MJPEG, V4L2_PIX_FMT_JPEG, V4L2_PIX_FMT_DV, V4L2_PIX_FMT_MPEG, V4L2_PIX_FMT_H264, V4L2_PIX_FMT_H264_NO_SC, V4L2_PIX_FMT_H264_MVC, V4L2_PIX_FMT_H263, V4L2_PIX_FMT_MPEG1, V4L2_PIX_FMT_MPEG2, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_XVID, V4L2_PIX_FMT_VC1_ANNEX_G, V4L2_PIX_FMT_VC1_ANNEX_L, V4L2_PIX_FMT_VP8, V4L2_PIX_FMT_VP9, V4L2_PIX_FMT_HEVC, V4L2_PIX_FMT_CPIA1, V4L2_PIX_FMT_WNVA, V4L2_PIX_FMT_SN9C10X, V4L2_PIX_FMT_SN9C20X_I420, V4L2_PIX_FMT_PWC1, V4L2_PIX_FMT_PWC2, V4L2_PIX_FMT_ET61X251, V4L2_PIX_FMT_SPCA501, V4L2_PIX_FMT_SPCA505, V4L2_PIX_FMT_SPCA508, V4L2_PIX_FMT_SPCA561, V4L2_PIX_FMT_PAC207, V4L2_PIX_FMT_MR97310A, V4L2_PIX_FMT_JL2005BCD, V4L2_PIX_FMT_SN9C2028, V4L2_PIX_FMT_SQ905C, V4L2_PIX_FMT_PJPG, V4L2_PIX_FMT_OV511, V4L2_PIX_FMT_OV518, V4L2_PIX_FMT_STV0680, V4L2_PIX_FMT_TM6000, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_PIX_FMT_KONICA420, V4L2_PIX_FMT_JPGL, V4L2_PIX_FMT_SE401, V4L2_PIX_FMT_S5C_UYVY_JPG, V4L2_PIX_FMT_Y8I, V4L2_PIX_FMT_Y12I, V4L2_PIX_FMT_Z16
v4l2_meta_data_formats = V4L2_META_FMT_VSP1_HGO, V4L2_META_FMT_VSP1_HGT, V4L2_META_FMT_UVC, V4L2_META_FMT_D4XX, V4L2_META_FMT_UVC_MSXU_1_5, V4L2_META_FMT_VIVID, V4L2_META_FMT_RK_ISP1_PARAMS, V4L2_META_FMT_RK_ISP1_STAT_3A, V4L2_META_FMT_RK_ISP1_EXT_PARAMS, V4L2_META_FMT_C3ISP_PARAMS, V4L2_META_FMT_C3ISP_STATS, V4L2_META_FMT_RPI_BE_CFG, V4L2_META_FMT_RPI_FE_CFG, V4L2_META_FMT_RPI_FE_STATS, V4L2_META_FMT_MALI_C55_PARAMS, V4L2_META_FMT_MALI_C55_STATS, V4L2_META_FMT_GENERIC_8, V4L2_META_FMT_GENERIC_CSI2_10, V4L2_META_FMT_GENERIC_CSI2_12, V4L2_META_FMT_GENERIC_CSI2_14, V4L2_META_FMT_GENERIC_CSI2_16, V4L2_META_FMT_GENERIC_CSI2_20, V4L2_META_FMT_GENERIC_CSI2_24
v4l2_fmtdesc_flags = V4L2_FMT_FLAG_COMPRESSED, V4L2_FMT_FLAG_EMULATED, V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM, V4L2_FMT_FLAG_DYN_RESOLUTION, V4L2_FMT_FLAG_ENC_CAP_FRAME_INTERVAL, V4L2_FMT_FLAG_CSC_COLORSPACE, V4L2_FMT_FLAG_CSC_XFER_FUNC, V4L2_FMT_FLAG_CSC_YCBCR_ENC, V4L2_FMT_FLAG_CSC_HSV_ENC, V4L2_FMT_FLAG_CSC_QUANTIZATION, V4L2_FMT_FLAG_META_LINE_BASED
v4l2_capability_capabilities = V4L2_CAP_VIDEO_CAPTURE, V4L2_CAP_VIDEO_OUTPUT, V4L2_CAP_VIDEO_OVERLAY, V4L2_CAP_VBI_CAPTURE, V4L2_CAP_VBI_OUTPUT, V4L2_CAP_SLICED_VBI_CAPTURE, V4L2_CAP_SLICED_VBI_OUTPUT, V4L2_CAP_RDS_CAPTURE, V4L2_CAP_VIDEO_OUTPUT_OVERLAY, V4L2_CAP_HW_FREQ_SEEK, V4L2_CAP_RDS_OUTPUT, V4L2_CAP_VIDEO_CAPTURE_MPLANE, V4L2_CAP_VIDEO_OUTPUT_MPLANE, V4L2_CAP_VIDEO_M2M_MPLANE, V4L2_CAP_VIDEO_M2M, V4L2_CAP_TUNER, V4L2_CAP_AUDIO, V4L2_CAP_RADIO, V4L2_CAP_MODULATOR, V4L2_CAP_SDR_CAPTURE, V4L2_CAP_EXT_PIX_FORMAT, V4L2_CAP_SDR_OUTPUT, V4L2_CAP_META_CAPTURE, V4L2_CAP_READWRITE, V4L2_CAP_EDID, V4L2_CAP_STREAMING, V4L2_CAP_META_OUTPUT, V4L2_CAP_TOUCH, V4L2_CAP_IO_MC, V4L2_CAP_DEVICE_CAPS
v4l2_framebuffer_capability = V4L2_FBUF_CAP_EXTERNOVERLAY, V4L2_FBUF_CAP_CHROMAKEY, V4L2_FBUF_CAP_LOCAL_ALPHA, V4L2_FBUF_CAP_GLOBAL_ALPHA, V4L2_FBUF_CAP_LOCAL_INV_ALPHA, V4L2_FBUF_CAP_SRC_CHROMAKEY
v4l2_framebuffer_flags = V4L2_FBUF_FLAG_PRIMARY, V4L2_FBUF_FLAG_OVERLAY, V4L2_FBUF_FLAG_CHROMAKEY, V4L2_FBUF_FLAG_LOCAL_ALPHA, V4L2_FBUF_FLAG_GLOBAL_ALPHA, V4L2_FBUF_FLAG_LOCAL_INV_ALPHA, V4L2_FBUF_FLAG_SRC_CHROMAKEY
v4l2_vbi_format_flags = V4L2_VBI_UNSYNC, V4L2_VBI_INTERLACED, V4L2_VBI_ITU_525_F1_START, V4L2_VBI_ITU_525_F2_START, V4L2_VBI_ITU_625_F1_START, V4L2_VBI_ITU_625_F2_START
v4l2_buffer_flags = V4L2_BUF_FLAG_MAPPED, V4L2_BUF_FLAG_QUEUED, V4L2_BUF_FLAG_DONE, V4L2_BUF_FLAG_KEYFRAME, V4L2_BUF_FLAG_PFRAME, V4L2_BUF_FLAG_BFRAME, V4L2_BUF_FLAG_ERROR, V4L2_BUF_FLAG_IN_REQUEST, V4L2_BUF_FLAG_TIMECODE, V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF, V4L2_BUF_FLAG_PREPARED, V4L2_BUF_FLAG_NO_CACHE_INVALIDATE, V4L2_BUF_FLAG_NO_CACHE_CLEAN, V4L2_BUF_FLAG_TIMESTAMP_MASK, V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN, V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC, V4L2_BUF_FLAG_TIMESTAMP_COPY, V4L2_BUF_FLAG_TSTAMP_SRC_MASK, V4L2_BUF_FLAG_TSTAMP_SRC_EOF, V4L2_BUF_FLAG_TSTAMP_SRC_SOE, V4L2_BUF_FLAG_LAST, V4L2_BUF_FLAG_REQUEST_FD
v4l2_timecode_type = V4L2_TC_TYPE_24FPS, V4L2_TC_TYPE_25FPS, V4L2_TC_TYPE_30FPS, V4L2_TC_TYPE_50FPS, V4L2_TC_TYPE_60FPS
v4l2_timecode_flags = V4L2_TC_FLAG_DROPFRAME, V4L2_TC_FLAG_COLORFRAME, V4L2_TC_USERBITS_field, V4L2_TC_USERBITS_USERDEFINED, V4L2_TC_USERBITS_8BITCHARS
v4l2_captureparm_cap = V4L2_CAP_TIMEPERFRAME
v4l2_captureparm_mode = V4L2_MODE_HIGHQUALITY
v4l2_tuner_capability = V4L2_TUNER_CAP_LOW, V4L2_TUNER_CAP_NORM, V4L2_TUNER_CAP_HWSEEK_BOUNDED, V4L2_TUNER_CAP_HWSEEK_WRAP, V4L2_TUNER_CAP_STEREO, V4L2_TUNER_CAP_LANG2, V4L2_TUNER_CAP_SAP, V4L2_TUNER_CAP_LANG1, V4L2_TUNER_CAP_RDS, V4L2_TUNER_CAP_RDS_BLOCK_IO, V4L2_TUNER_CAP_RDS_CONTROLS, V4L2_TUNER_CAP_FREQ_BANDS, V4L2_TUNER_CAP_HWSEEK_PROG_LIM, V4L2_TUNER_CAP_1HZ
v4l2_tuner_rxsubchans = V4L2_TUNER_SUB_MONO, V4L2_TUNER_SUB_STEREO, V4L2_TUNER_SUB_LANG2, V4L2_TUNER_SUB_SAP, V4L2_TUNER_SUB_LANG1, V4L2_TUNER_SUB_RDS
v4l2_tuner_audmode = V4L2_TUNER_MODE_MONO, V4L2_TUNER_MODE_STEREO, V4L2_TUNER_MODE_LANG2, V4L2_TUNER_MODE_SAP, V4L2_TUNER_MODE_LANG1, V4L2_TUNER_MODE_LANG1_LANG2
v4l2_audio_capability = V4L2_AUDCAP_STEREO, V4L2_AUDCAP_AVL
v4l2_audio_mode = V4L2_AUDMODE_AVL
v4l2_control_flags = V4L2_CTRL_FLAG_DISABLED, V4L2_CTRL_FLAG_GRABBED, V4L2_CTRL_FLAG_READ_ONLY, V4L2_CTRL_FLAG_UPDATE, V4L2_CTRL_FLAG_INACTIVE, V4L2_CTRL_FLAG_SLIDER, V4L2_CTRL_FLAG_WRITE_ONLY, V4L2_CTRL_FLAG_VOLATILE, V4L2_CTRL_FLAG_HAS_PAYLOAD, V4L2_CTRL_FLAG_EXECUTE_ON_WRITE, V4L2_CTRL_FLAG_MODIFY_LAYOUT, V4L2_CTRL_FLAG_DYNAMIC_ARRAY, V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX, V4L2_CTRL_FLAG_NEXT_CTRL, V4L2_CTRL_FLAG_NEXT_COMPOUND
v4l2_ext_ctrl_class = V4L2_CTRL_CLASS_USER, V4L2_CTRL_CLASS_CODEC, V4L2_CTRL_CLASS_CAMERA, V4L2_CTRL_CLASS_FM_TX, V4L2_CTRL_CLASS_FLASH, V4L2_CTRL_CLASS_JPEG, V4L2_CTRL_CLASS_IMAGE_SOURCE, V4L2_CTRL_CLASS_IMAGE_PROC, V4L2_CTRL_CLASS_DV, V4L2_CTRL_CLASS_FM_RX, V4L2_CTRL_CLASS_RF_TUNER, V4L2_CTRL_CLASS_DETECT, V4L2_CTRL_ID_MASK, V4L2_CTRL_MAX_DIMS, V4L2_CTRL_WHICH_CUR_VAL, V4L2_CTRL_WHICH_DEF_VAL
#Comeback and add others from include/uapi/linux/videodev2.h#1617. Once after syz-extract able to detect with special chars
v4l2_ext_controls = V4L2_CID_USER_CLASS, V4L2_CID_BRIGHTNESS, V4L2_CID_CONTRAST, V4L2_CID_SATURATION, V4L2_CID_HUE, V4L2_CID_AUDIO_VOLUME, V4L2_CID_AUDIO_BALANCE, V4L2_CID_AUDIO_BASS, V4L2_CID_AUDIO_TREBLE, V4L2_CID_AUDIO_MUTE, V4L2_CID_AUDIO_LOUDNESS, V4L2_CID_BLACK_LEVEL, V4L2_CID_AUTO_WHITE_BALANCE, V4L2_CID_DO_WHITE_BALANCE, V4L2_CID_RED_BALANCE, V4L2_CID_BLUE_BALANCE, V4L2_CID_GAMMA, V4L2_CID_EXPOSURE, V4L2_CID_AUTOGAIN, V4L2_CID_GAIN, V4L2_CID_HFLIP, V4L2_CID_VFLIP, V4L2_CID_POWER_LINE_FREQUENCY, V4L2_CID_HUE_AUTO, V4L2_CID_WHITE_BALANCE_TEMPERATURE, V4L2_CID_SHARPNESS, V4L2_CID_BACKLIGHT_COMPENSATION, V4L2_CID_CHROMA_AGC, V4L2_CID_COLOR_KILLER, V4L2_CID_COLORFX, V4L2_CID_AUTOBRIGHTNESS, V4L2_CID_BAND_STOP_FILTER, V4L2_CID_ROTATE, V4L2_CID_BG_COLOR, V4L2_CID_CHROMA_GAIN, V4L2_CID_ILLUMINATORS_1, V4L2_CID_ILLUMINATORS_2, V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, V4L2_CID_ALPHA_COMPONENT, V4L2_CID_COLORFX_CBCR, V4L2_CID_CODEC_CLASS, V4L2_CID_MPEG_STREAM_TYPE, V4L2_CID_MPEG_STREAM_PID_PMT, V4L2_CID_MPEG_STREAM_PID_AUDIO, V4L2_CID_MPEG_STREAM_PID_VIDEO, V4L2_CID_MPEG_STREAM_PID_PCR, V4L2_CID_MPEG_STREAM_PES_ID_AUDIO, V4L2_CID_MPEG_STREAM_PES_ID_VIDEO, V4L2_CID_MPEG_STREAM_VBI_FMT, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, V4L2_CID_MPEG_AUDIO_ENCODING, V4L2_CID_MPEG_AUDIO_L1_BITRATE, V4L2_CID_MPEG_AUDIO_L2_BITRATE, V4L2_CID_MPEG_AUDIO_L3_BITRATE, V4L2_CID_MPEG_AUDIO_MODE, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION, V4L2_CID_MPEG_AUDIO_EMPHASIS, V4L2_CID_MPEG_AUDIO_CRC, V4L2_CID_MPEG_AUDIO_MUTE, V4L2_CID_MPEG_AUDIO_AAC_BITRATE, V4L2_CID_MPEG_AUDIO_AC3_BITRATE, V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK, V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK, V4L2_CID_MPEG_VIDEO_ENCODING, V4L2_CID_MPEG_VIDEO_ASPECT, V4L2_CID_MPEG_VIDEO_B_FRAMES, V4L2_CID_MPEG_VIDEO_GOP_SIZE, V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, V4L2_CID_MPEG_VIDEO_PULLDOWN, V4L2_CID_MPEG_VIDEO_BITRATE_MODE, V4L2_CID_MPEG_VIDEO_BITRATE, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION, V4L2_CID_MPEG_VIDEO_MUTE, V4L2_CID_MPEG_VIDEO_MUTE_YUV, V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE, V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER, V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB, V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE, V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE, V4L2_CID_MPEG_VIDEO_HEADER_MODE, V4L2_CID_MPEG_VIDEO_MAX_REF_PIC, V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP, V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP, V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP, V4L2_CID_MPEG_VIDEO_H263_MIN_QP, V4L2_CID_MPEG_VIDEO_H263_MAX_QP, V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP, V4L2_CID_MPEG_VIDEO_H264_MAX_QP, V4L2_CID_MPEG_VIDEO_H264_MIN_QP, V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM, V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE, V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE, V4L2_CID_MPEG_VIDEO_H264_I_PERIOD, V4L2_CID_MPEG_VIDEO_H264_LEVEL, V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA, V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE, V4L2_CID_MPEG_VIDEO_H264_PROFILE, V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT, V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH, V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE, V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC, V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING, V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0, V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE, V4L2_CID_MPEG_VIDEO_H264_FMO, V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE, V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP, V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION, V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE, V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH, V4L2_CID_MPEG_VIDEO_H264_ASO, V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER, V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING, V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE, V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER, V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP, V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP, V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP, V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP, V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP, V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP, V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL, V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE, V4L2_CID_MPEG_VIDEO_MPEG4_QPEL, V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES, V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB, V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE, V4L2_CID_MPEG_VIDEO_VBV_SIZE, V4L2_CID_MPEG_VIDEO_DEC_PTS, V4L2_CID_MPEG_VIDEO_DEC_FRAME, V4L2_CID_MPEG_VIDEO_VBV_DELAY, V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE, V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE, V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER, V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME, V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS, V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4, V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES, V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL, V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS, V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD, V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL, V4L2_CID_MPEG_VIDEO_VPX_MIN_QP, V4L2_CID_MPEG_VIDEO_VPX_MAX_QP, V4L2_CID_MPEG_VIDEO_VPX_I_FRAME_QP, V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP, V4L2_CID_MPEG_VIDEO_VPX_PROFILE, V4L2_CID_CAMERA_CLASS, V4L2_CID_EXPOSURE_AUTO, V4L2_CID_EXPOSURE_ABSOLUTE, V4L2_CID_EXPOSURE_AUTO_PRIORITY, V4L2_CID_PAN_RELATIVE, V4L2_CID_TILT_RELATIVE, V4L2_CID_PAN_RESET, V4L2_CID_TILT_RESET, V4L2_CID_PAN_ABSOLUTE, V4L2_CID_TILT_ABSOLUTE, V4L2_CID_FOCUS_ABSOLUTE, V4L2_CID_FOCUS_RELATIVE, V4L2_CID_FOCUS_AUTO, V4L2_CID_ZOOM_ABSOLUTE, V4L2_CID_ZOOM_RELATIVE, V4L2_CID_ZOOM_CONTINUOUS, V4L2_CID_PRIVACY, V4L2_CID_IRIS_ABSOLUTE, V4L2_CID_IRIS_RELATIVE, V4L2_CID_AUTO_EXPOSURE_BIAS, V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE, V4L2_CID_WIDE_DYNAMIC_RANGE, V4L2_CID_IMAGE_STABILIZATION, V4L2_CID_ISO_SENSITIVITY, V4L2_CID_ISO_SENSITIVITY_AUTO, V4L2_CID_EXPOSURE_METERING, V4L2_CID_SCENE_MODE, V4L2_CID_3A_LOCK, V4L2_CID_AUTO_FOCUS_START, V4L2_CID_AUTO_FOCUS_STOP, V4L2_CID_AUTO_FOCUS_STATUS, V4L2_CID_AUTO_FOCUS_RANGE, V4L2_CID_PAN_SPEED, V4L2_CID_TILT_SPEED, V4L2_CID_FM_TX_CLASS, V4L2_CID_RDS_TX_DEVIATION, V4L2_CID_RDS_TX_PI, V4L2_CID_RDS_TX_PTY, V4L2_CID_RDS_TX_PS_NAME, V4L2_CID_RDS_TX_RADIO_TEXT, V4L2_CID_RDS_TX_MONO_STEREO, V4L2_CID_RDS_TX_ARTIFICIAL_HEAD, V4L2_CID_RDS_TX_COMPRESSED, V4L2_CID_RDS_TX_DYNAMIC_PTY, V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT, V4L2_CID_RDS_TX_TRAFFIC_PROGRAM, V4L2_CID_RDS_TX_MUSIC_SPEECH, V4L2_CID_RDS_TX_ALT_FREQS_ENABLE, V4L2_CID_RDS_TX_ALT_FREQS, V4L2_CID_AUDIO_LIMITER_ENABLED, V4L2_CID_AUDIO_LIMITER_RELEASE_TIME, V4L2_CID_AUDIO_LIMITER_DEVIATION, V4L2_CID_AUDIO_COMPRESSION_ENABLED, V4L2_CID_AUDIO_COMPRESSION_GAIN, V4L2_CID_AUDIO_COMPRESSION_THRESHOLD, V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME, V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME, V4L2_CID_PILOT_TONE_ENABLED, V4L2_CID_PILOT_TONE_DEVIATION, V4L2_CID_PILOT_TONE_FREQUENCY, V4L2_CID_TUNE_PREEMPHASIS, V4L2_CID_TUNE_POWER_LEVEL, V4L2_CID_TUNE_ANTENNA_CAPACITOR, V4L2_CID_FLASH_CLASS, V4L2_CID_FLASH_LED_MODE, V4L2_CID_FLASH_STROBE_SOURCE, V4L2_CID_FLASH_STROBE, V4L2_CID_FLASH_STROBE_STOP, V4L2_CID_FLASH_STROBE_STATUS, V4L2_CID_FLASH_TIMEOUT, V4L2_CID_FLASH_INTENSITY, V4L2_CID_FLASH_TORCH_INTENSITY, V4L2_CID_FLASH_INDICATOR_INTENSITY, V4L2_CID_FLASH_FAULT, V4L2_CID_FLASH_CHARGE, V4L2_CID_FLASH_READY, V4L2_CID_JPEG_CLASS, V4L2_CID_JPEG_CHROMA_SUBSAMPLING, V4L2_CID_JPEG_RESTART_INTERVAL, V4L2_CID_JPEG_COMPRESSION_QUALITY, V4L2_CID_JPEG_ACTIVE_MARKER, V4L2_CID_IMAGE_SOURCE_CLASS, V4L2_CID_VBLANK, V4L2_CID_HBLANK, V4L2_CID_ANALOGUE_GAIN, V4L2_CID_TEST_PATTERN_RED, V4L2_CID_TEST_PATTERN_GREENR, V4L2_CID_TEST_PATTERN_BLUE, V4L2_CID_TEST_PATTERN_GREENB, V4L2_CID_IMAGE_PROC_CLASS, V4L2_CID_LINK_FREQ, V4L2_CID_PIXEL_RATE, V4L2_CID_TEST_PATTERN, V4L2_CID_DV_CLASS, V4L2_CID_DV_TX_HOTPLUG, V4L2_CID_DV_TX_RXSENSE, V4L2_CID_DV_TX_EDID_PRESENT, V4L2_CID_DV_TX_MODE, V4L2_CID_DV_TX_RGB_RANGE, V4L2_CID_DV_TX_IT_CONTENT_TYPE, V4L2_CID_DV_RX_POWER_PRESENT, V4L2_CID_DV_RX_RGB_RANGE, V4L2_CID_DV_RX_IT_CONTENT_TYPE, V4L2_CID_FM_RX_CLASS, V4L2_CID_TUNE_DEEMPHASIS, V4L2_CID_RDS_RECEPTION, V4L2_CID_RF_TUNER_CLASS, V4L2_CID_RF_TUNER_RF_GAIN, V4L2_CID_RF_TUNER_LNA_GAIN_AUTO, V4L2_CID_RF_TUNER_LNA_GAIN, V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO, V4L2_CID_RF_TUNER_MIXER_GAIN, V4L2_CID_RF_TUNER_IF_GAIN_AUTO, V4L2_CID_RF_TUNER_IF_GAIN, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, V4L2_CID_RF_TUNER_BANDWIDTH, V4L2_CID_RF_TUNER_PLL_LOCK, V4L2_CID_RDS_RX_PTY, V4L2_CID_RDS_RX_PS_NAME, V4L2_CID_RDS_RX_RADIO_TEXT, V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT, V4L2_CID_RDS_RX_TRAFFIC_PROGRAM, V4L2_CID_RDS_RX_MUSIC_SPEECH, V4L2_CID_DETECT_CLASS, V4L2_CID_DETECT_MD_MODE, V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD, V4L2_CID_DETECT_MD_THRESHOLD_GRID, V4L2_CID_DETECT_MD_REGION_GRID
v4l2_frmsizetypes = V4L2_FRMSIZE_TYPE_DISCRETE, V4L2_FRMSIZE_TYPE_CONTINUOUS, V4L2_FRMSIZE_TYPE_STEPWISE
v4l2_frmivaltypes = V4L2_FRMIVAL_TYPE_DISCRETE, V4L2_FRMIVAL_TYPE_CONTINUOUS, V4L2_FRMIVAL_TYPE_STEPWISE
v4l2_enc_idx_flags = V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_P, V4L2_ENC_IDX_FRAME_B, V4L2_ENC_IDX_FRAME_MASK
v4l2_dbg_match_type = V4L2_CHIP_MATCH_BRIDGE, V4L2_CHIP_MATCH_SUBDEV, V4L2_CHIP_MATCH_I2C_DRIVER, V4L2_CHIP_MATCH_I2C_ADDR, V4L2_CHIP_MATCH_AC97
v4l2_frequency_band_modulation = V4L2_BAND_MODULATION_VSB, V4L2_BAND_MODULATION_FM, V4L2_BAND_MODULATION_AM
v4l2_dv_timings_type = V4L2_DV_BT_656_1120
v4l2_bt_timings_interlaced = V4L2_DV_PROGRESSIVE, V4L2_DV_INTERLACED
v4l2_bt_timings_polarities = V4L2_DV_VSYNC_POS_POL, V4L2_DV_HSYNC_POS_POL
v4l2_bt_timings_standards = V4L2_DV_BT_STD_CEA861, V4L2_DV_BT_STD_DMT, V4L2_DV_BT_STD_CVT, V4L2_DV_BT_STD_GTF, V4L2_DV_BT_STD_SDI
v4l2_bt_timings_flags = V4L2_DV_FL_REDUCED_BLANKING, V4L2_DV_FL_CAN_REDUCE_FPS, V4L2_DV_FL_REDUCED_FPS, V4L2_DV_FL_HALF_LINE, V4L2_DV_FL_IS_CE_VIDEO, V4L2_DV_FL_FIRST_FIELD_EXTRA_LINE
v4l2_encoder_cmd_cmd = V4L2_ENC_CMD_START, V4L2_ENC_CMD_STOP, V4L2_ENC_CMD_PAUSE, V4L2_ENC_CMD_RESUME
v4l2_encoder_flags = V4L2_ENC_CMD_STOP_AT_GOP_END
v4l2_decoder_cmd_cmd = V4L2_DEC_CMD_START, V4L2_DEC_CMD_STOP, V4L2_DEC_CMD_PAUSE, V4L2_DEC_CMD_RESUME
v4l2_decoder_cmd_flags = V4L2_DEC_CMD_START_MUTE_AUDIO, V4L2_DEC_CMD_PAUSE_TO_BLACK, V4L2_DEC_CMD_STOP_TO_BLACK, V4L2_DEC_CMD_STOP_IMMEDIATELY
v4l2_decoder_cmd_format = V4L2_DEC_START_FMT_NONE, V4L2_DEC_START_FMT_GOP
v4l2_event_src_changes = V4L2_EVENT_SRC_CH_RESOLUTION
v4l2_event_type = V4L2_EVENT_ALL, V4L2_EVENT_VSYNC, V4L2_EVENT_EOS, V4L2_EVENT_CTRL, V4L2_EVENT_FRAME_SYNC, V4L2_EVENT_SOURCE_CHANGE, V4L2_EVENT_MOTION_DET, V4L2_EVENT_PRIVATE_START
v4l2_event_ctrl_changes = V4L2_EVENT_CTRL_CH_VALUE, V4L2_EVENT_CTRL_CH_FLAGS, V4L2_EVENT_CTRL_CH_RANGE
v4l2_event_motion_det_flags = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ
v4l2_event_subscription_flags = V4L2_EVENT_SUB_FL_SEND_INITIAL, V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK
v4l2_selection_target = V4L2_SEL_TGT_CROP, V4L2_SEL_TGT_CROP_DEFAULT, V4L2_SEL_TGT_CROP_BOUNDS, V4L2_SEL_TGT_NATIVE_SIZE, V4L2_SEL_TGT_COMPOSE, V4L2_SEL_TGT_COMPOSE_DEFAULT, V4L2_SEL_TGT_COMPOSE_BOUNDS, V4L2_SEL_TGT_COMPOSE_PADDED
v4l2_selection_flags = V4L2_SEL_FLAG_GE, V4L2_SEL_FLAG_LE, V4L2_SEL_FLAG_KEEP_CONFIG
v4l2_bt_timings_cap_capabilities = V4L2_DV_BT_CAP_INTERLACED, V4L2_DV_BT_CAP_PROGRESSIVE, V4L2_DV_BT_CAP_REDUCED_BLANKING, V4L2_DV_BT_CAP_CUSTOM
v4l2_dbg_chip_info_flags = V4L2_CHIP_FL_READABLE, V4L2_CHIP_FL_WRITABLE
v4l2_std_id = V4L2_STD_PAL_B, V4L2_STD_PAL_B1, V4L2_STD_PAL_G, V4L2_STD_PAL_H, V4L2_STD_PAL_I, V4L2_STD_PAL_D, V4L2_STD_PAL_D1, V4L2_STD_PAL_K, V4L2_STD_PAL_M, V4L2_STD_PAL_N, V4L2_STD_PAL_Nc, V4L2_STD_PAL_60, V4L2_STD_NTSC_M, V4L2_STD_NTSC_M_JP, V4L2_STD_NTSC_443, V4L2_STD_NTSC_M_KR, V4L2_STD_SECAM_B, V4L2_STD_SECAM_D, V4L2_STD_SECAM_G, V4L2_STD_SECAM_H, V4L2_STD_SECAM_K, V4L2_STD_SECAM_K1, V4L2_STD_SECAM_L, V4L2_STD_SECAM_LC, V4L2_STD_ATSC_8_VSB, V4L2_STD_ATSC_16_VSB, V4L2_STD_NTSC, V4L2_STD_SECAM_DK, V4L2_STD_SECAM, V4L2_STD_PAL_BG, V4L2_STD_PAL_DK, V4L2_STD_PAL, V4L2_STD_B, V4L2_STD_G, V4L2_STD_H, V4L2_STD_L, V4L2_STD_GH, V4L2_STD_DK, V4L2_STD_BG, V4L2_STD_MN, V4L2_STD_MTS, V4L2_STD_525_60, V4L2_STD_625_50, V4L2_STD_ATSC, V4L2_STD_UNKNOWN, V4L2_STD_ALL
v4l2_input_status = V4L2_IN_ST_NO_POWER, V4L2_IN_ST_NO_SIGNAL, V4L2_IN_ST_NO_COLOR, V4L2_IN_ST_HFLIP, V4L2_IN_ST_VFLIP, V4L2_IN_ST_NO_H_LOCK, V4L2_IN_ST_COLOR_KILL, V4L2_IN_ST_NO_V_LOCK, V4L2_IN_ST_NO_STD_LOCK, V4L2_IN_ST_NO_SYNC, V4L2_IN_ST_NO_EQU, V4L2_IN_ST_NO_CARRIER, V4L2_IN_ST_MACROVISION, V4L2_IN_ST_NO_ACCESS, V4L2_IN_ST_VTR
v4l2_input_type = V4L2_INPUT_TYPE_TUNER, V4L2_INPUT_TYPE_CAMERA, V4L2_INPUT_TYPE_TOUCH
v4l2_input_capabilities = V4L2_IN_CAP_DV_TIMINGS, V4L2_IN_CAP_CUSTOM_TIMINGS, V4L2_IN_CAP_STD, V4L2_IN_CAP_NATIVE_SIZE
v4l2_output_type = V4L2_OUTPUT_TYPE_MODULATOR, V4L2_OUTPUT_TYPE_ANALOG, V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY
v4l2_output_capabilities = V4L2_OUT_CAP_DV_TIMINGS, V4L2_OUT_CAP_CUSTOM_TIMINGS, V4L2_OUT_CAP_STD, V4L2_OUT_CAP_NATIVE_SIZE
v4l2_query_ext_ctrl = V4L2_CTRL_FLAG_NEXT_CTRL, V4L2_CTRL_FLAG_NEXT_COMPOUND

# These are actually defined in the newer kernel versions.
# But the newer kernel versions don't build with make extract.
# This can be removed once we can regenerate consts on at least v6.19-rc3.
define V4L2_META_FMT_MALI_C55_PARAMS	1345664323
define V4L2_META_FMT_MALI_C55_STATS	1395995971
]

180/2 2026/07/30 12:37 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 177497
							output: 479
							thoughts: 81
						

Thoughts:
Okay, here's my interpretation of that thought process, tailored for an expert audience:

**Refactoring the Reproducer with Device-Specific Opens**

Right, the reproducer is currently using a generic open call. I see we have `syz_open_dev$video` and, presumably, a similar function for I2C devices, `syz_open_dev$I2C`. This looks like the right approach, much more precise than the current method. We need to leverage these device-specific system call wrappers instead of the broader, less targeted opens. This should offer us greater control over the device and, hopefully, lead to a cleaner and more reliable reproducer. Time to rewrite the reproducer to take advantage of these primitives. I expect this refinement will make the code more readable and the exploit more direct.



181/2 2026/07/30 12:38 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect$hid(3, 0, &AUTO, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video0\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video1\x00', 0, 0)
r3 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-0\x00', 0, 0)
r4 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-1\x00', 0, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-2\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-3\x00', 0, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r3, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r4, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

182/2 2026/07/30 12:38 llm crash-repro-finder-compressor
0m Model:
gemini-3.5-flash

Reply:
### 1. Approaches Tried and Results
*   **KASAN Report Analysis**:
    *   Analyzed slab-use-after-free read of size 8 at offset 264 (`0x108`) inside a `kmalloc-4k` object.
    *   Identified that the allocation/free stack traces in the report pointing to `nsim_dev_trap_skb_build` and `kobject_uevent_env` are reallocation noise (red herrings).
    *   Calculated exact struct offsets: `struct usb_device` has `struct device dev` at offset 176 bytes. `struct device` has `const struct device_type *type` at offset 88 bytes. Total offset of `parent->type` is `176 + 88 = 264` bytes (`0x108`), matching the KASAN report exactly.
    *   Confirmed the UAF occurs in `i2c_adapter_depth` when dereferencing `parent->type` where `parent` is `adapter->dev.parent` pointing to a freed `struct usb_device`.
*   **Driver Code Auditing**:
    *   Audited USB drivers setting `adapter->dev.parent = &usb_device->dev` and deferring `i2c_del_adapter` on disconnect.
    *   Ruled out `cx231xx`, `dvb_usb`, `dvb_usb_v2`, and `pvrusb2` (which calls `pvr2_i2c_core_done` synchronously in `pvr2_hdw_disconnect`).
    *   Identified vulnerable drivers:
        *   `au0828`: Defers `au0828_usb_release` (which calls `au0828_i2c_unregister` -> `i2c_del_adapter`) to `au0828_usb_v4l2_release` if V4L2 is open during disconnect.
        *   `si4713` (`radio-usb-si4713`): Defers `i2c_del_adapter` to `usb_si4713_video_device_release` (called when the last reference to `v4l2_dev` is dropped, i.e., when `/dev/radioX` is closed). Does not call `usb_get_dev()` in `probe`, leaving `usb_device` unprotected.
        *   `go7007`: Defers `i2c_del_adapter` to `go7007_remove` (called via `v4l2_device_put` when `/dev/videoX` is closed).
*   **Syzkaller Program Construction & Syntax Debugging**:
    *   Attempted to use `syz_usb_connect` with raw hex strings (`&AUTO="1201..."` or `&AUTO='\x12\x01...'`), which failed with `wrong string arg` because `syz_usb_connect` expects a `usb_device_descriptor` struct, not a string.
    *   Attempted to use `&(0x7f0000000000)=ANY=[...]` and `ANY=@ANYBLOB=[...]`, which failed with `wrong union arg for "array"` because `ANYBLOB` is not a valid union option or array type.
    *   Attempted to construct `usb_device_descriptor` manually, but hit `wrong array arg *prog.BufferType` due to complex nested struct/array definitions in `vusb.txt` (specifically `interfaces` array in `usb_config_descriptor`).
    *   Discovered `syz_usb_connect$hid` with `&AUTO` allows syzkaller to automatically generate a valid HID device descriptor.
    *   Discovered `syz_open_dev$I2C` and `syz_open_dev$radio` / `syz_open_dev$video` are the correct pseudo-syscalls to open `/dev/i2c-X` and `/dev/radioX` / `/dev/videoX` respectively, returning the correct resource types (`fd_i2c` and `fd_video`).

### 2. Current Hypotheses & Active Lines of Investigation
*   **Deferred Cleanup Race via `si4713` or `au0828`**:
    1.  Emulate a USB device matching `si4713` (Vendor `0x10c4`, Product `0x8244`, Interface Class `USB_CLASS_HID`) or `au0828` (Vendor `0x2040`, Product `0x7200`).
    2.  Open the corresponding video/radio device (e.g., `/dev/radio0` or `/dev/video0`) to hold a reference to the driver context.
    3.  Open the corresponding I2C device (e.g., `/dev/i2c-0`).
    4.  Disconnect the USB device. The driver's `disconnect` callback runs but defers the unregistration of the I2C adapter because the video/radio device is still open.
    5.  The USB core frees the `struct usb_device`.
    6.  Perform an I2C transaction (e.g., `ioctl$I2C_SMBUS`) on the open I2C file descriptor. This triggers `i2c_adapter_depth` which dereferences `adapter->dev.parent->type` (offset 264 of the freed `usb_device`), causing the UAF.

### 3. Critical Code and Configuration Values
*   **Vulnerable Code Path**:
    ```c
    // drivers/i2c/i2c-core-base.c
    unsigned int i2c_adapter_depth(struct i2c_adapter *adapter)
    {
        unsigned int depth = 0;
        struct device *parent;

        for (parent = adapter->dev.parent; parent; parent = parent->parent)
            if (parent->type == &i2c_adapter_type) // UAF here: parent points to freed usb_device
                depth++;
        ...
    }
    ```
*   **Struct Layout Offsets**:
    *   `struct usb_device` size: ~2251 bytes (fits in `kmalloc-4k`).
    *   `usb_device->dev` offset: 176 bytes.
    *   `device->type` offset: 88 bytes.
    *   Total offset of `usb_device->dev.type`: 264 bytes (`0x108`).
*   **USB IDs & Classes**:
    *   `si4713`: Vendor `0x10c4`, Product `0x8244`, Interface Class `0x03` (`USB_CLASS_HID`).
    *   `au0828`: Vendor `0x2040`, Product `0x7200`.
    *   `go7007`: Vendor `0x0eb1`, Product `0x7007`.
*   **Syzkaller API Definitions**:
    *   `syz_open_dev$I2C(dev ptr[in, string["/dev/i2c-#"]], id intptr, flags flags[open_flags]) fd_i2c`
    *   `syz_open_dev$radio(dev ptr[in, string["/dev/radio#"]], id proc[0, 4], flags const[O_RDWR]) fd_video`
    *   `syz_open_dev$video(dev ptr[in, string["/dev/video#"]], id intptr, flags flags[open_flags]) fd_video`

### 4. Potential Reasoning Loops / Repetitive Tool Calls
*   Avoid manually constructing the `usb_device_descriptor` struct literal in the syzkaller program, as the parser is extremely strict and prone to `wrong array arg *prog.BufferType` errors due to nested `void` and `len` fields.
*   Instead, use `syz_usb_connect$hid(3, 0, &AUTO, 0)` which lets syzkaller automatically generate a valid HID device descriptor, and rely on syzkaller's automatic USB ID patching to match `si4713` (`0x10c4:0x8244`).

Tokens:
							input: 191091
							output: 1903
							thoughts: 2104
						

183/2 2026/07/30 12:38 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 21561
							output: 22
							thoughts: 39
						

Thoughts:
Okay, here's my take on those thoughts, framed as an expert's internal monologue:

**Investigating a Video Device Path in Syzkaller**

Right, `syz_open_dev$video`. That's pointing towards a video device, and it's expecting a specific path format: `/dev/video#\x00`. Specifically, the null-terminated string. Okay, good. That confirms the general structure I would expect, but I need to make sure I understand the precise implementation and any nuances in the driver.

Time to consult the definitive source for V4L2 device handling, `dev_video4linux.txt`. I need to review this to confirm expected behavior, permissions, and any potential gotchas with the device node names or the way it handles errors or invalid arguments. That's the place to look for any subtle details.



184/2 2026/07/30 12:38 tool read-description
0m Args:
map[File:dev_video4linux.txt]

Results:
map[Output:# Copyright 2018 syzkaller project authors. All rights reserved.
# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

include <linux/time.h>
include <linux/types.h>
include <uapi/asm/ioctl.h>
include <uapi/linux/fcntl.h>
include <uapi/linux/videodev2.h>
include <uapi/linux/v4l2-common.h>
include <uapi/linux/v4l2-subdev.h>
include <uapi/linux/v4l2-mediabus.h>
include <uapi/linux/media-bus-format.h>
include <uapi/linux/v4l2-controls.h>
include <uapi/linux/media.h>

resource fd_video[fd]
resource fd_v4l2_buffer[fd]

syz_open_dev$video(dev ptr[in, string["/dev/video#"]], id intptr, flags flags[open_flags]) fd_video
syz_open_dev$video4linux(dev ptr[in, string["/dev/v4l-subdev#"]], id intptr, flags flags[open_flags]) fd_video

# TODO: we now get wrong values for ioctl commands that involve v4l2_buffer and v4l2_event.
# Our definition uses 32-bit timespec, while kernel uses 64-bit timespec when __KERNEL__ is defined.

# Special support for CONFIG_VIDEO_VIMC/VIM2M/VIVID/VICODEC.
# Here we assume that all of them are enabled and the following arguments are passed on command line:
# vivid.n_devs=16 vivid.multiplanar=1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2
openat$vimc0(fd const[AT_FDCWD], file ptr[in, string["/dev/video0"]], flags const[O_RDWR], mode const[0]) fd_video
openat$vimc1(fd const[AT_FDCWD], file ptr[in, string["/dev/video1"]], flags const[O_RDWR], mode const[0]) fd_video
openat$vimc2(fd const[AT_FDCWD], file ptr[in, string["/dev/video2"]], flags const[O_RDWR], mode const[0]) fd_video
syz_open_dev$vivid(dev ptr[in, string["/dev/video#"]], id proc[3, 4], flags const[O_RDWR]) fd_video
openat$vicodec0(fd const[AT_FDCWD], file ptr[in, string["/dev/video36"]], flags const[O_RDWR], mode const[0]) fd_video
openat$vicodec1(fd const[AT_FDCWD], file ptr[in, string["/dev/video37"]], flags const[O_RDWR], mode const[0]) fd_video
# TODO: there are some complex rules as to what ioctl's are applicable to what devices
# (see determine_valid_ioctls in v4l2-dev.c). We don't have these rules described.
# Currently we just apply all ioctl's to all v4l devices.
syz_open_dev$swradio(dev ptr[in, string["/dev/swradio#"]], id proc[0, 2], flags const[O_RDWR]) fd_video
syz_open_dev$radio(dev ptr[in, string["/dev/radio#"]], id proc[0, 4], flags const[O_RDWR]) fd_video
syz_open_dev$vbi(dev ptr[in, string["/dev/vbi#"]], id proc[0, 4], flags const[O_RDWR]) fd_video

ioctl$VIDIOC_QUERYCAP(fd fd_video, cmd const[VIDIOC_QUERYCAP], arg ptr[out, v4l2_capability])
ioctl$VIDIOC_ENUM_FMT(fd fd_video, cmd const[VIDIOC_ENUM_FMT], arg ptr[inout, v4l2_fmtdesc[v4l2_buf_type]])
ioctl$VIDIOC_G_FMT(fd fd_video, cmd const[VIDIOC_G_FMT], arg ptr[inout, v4l2_format[v4l2_buf_type]])
ioctl$VIDIOC_S_FMT(fd fd_video, cmd const[VIDIOC_S_FMT], arg ptr[inout, v4l2_format[v4l2_buf_type]])
ioctl$VIDIOC_REQBUFS(fd fd_video, cmd const[VIDIOC_REQBUFS], arg ptr[inout, v4l2_requestbuffers[v4l2_buf_type]])
# This variant serves as fd_v4l2_buffer constructor.
# Potentially more ioctl can create fd_v4l2_buffer, but the kernel code is hard to understand.
ioctl$VIDIOC_QUERYBUF_DMABUF(fd fd_video, cmd const[VIDIOC_QUERYBUF], arg ptr[inout, v4l2_buffer[v4l2_buf_type, V4L2_MEMORY_DMABUF, fd_v4l2_buffer]])
ioctl$VIDIOC_QUERYBUF(fd fd_video, cmd const[VIDIOC_QUERYBUF], arg ptr[inout, v4l2_buffer_t[v4l2_buf_type]])
ioctl$VIDIOC_G_FBUF(fd fd_video, cmd const[VIDIOC_G_FBUF], arg ptr[inout, v4l2_framebuffer])
ioctl$VIDIOC_S_FBUF(fd fd_video, cmd const[VIDIOC_S_FBUF], arg ptr[in, v4l2_framebuffer])
ioctl$VIDIOC_OVERLAY(fd fd_video, cmd const[VIDIOC_OVERLAY], arg ptr[in, int32])
ioctl$VIDIOC_QBUF(fd fd_video, cmd const[VIDIOC_QBUF], arg ptr[inout, v4l2_buffer_t[v4l2_buf_type]])
ioctl$VIDIOC_EXPBUF(fd fd_video, cmd const[VIDIOC_EXPBUF], arg ptr[inout, v4l2_exportbuffer[v4l2_buf_type]])
ioctl$VIDIOC_DQBUF(fd fd_video, cmd const[VIDIOC_DQBUF], arg ptr[inout, v4l2_buffer_t[v4l2_buf_type]])
ioctl$VIDIOC_STREAMON(fd fd_video, cmd const[VIDIOC_STREAMON], arg ptr[in, int32])
ioctl$VIDIOC_STREAMOFF(fd fd_video, cmd const[VIDIOC_STREAMOFF], arg ptr[in, int32])
ioctl$VIDIOC_G_PARM(fd fd_video, cmd const[VIDIOC_G_PARM], arg ptr[inout, v4l2_streamparm])
ioctl$VIDIOC_S_PARM(fd fd_video, cmd const[VIDIOC_S_PARM], arg ptr[inout, v4l2_streamparm])
ioctl$VIDIOC_G_STD(fd fd_video, cmd const[VIDIOC_G_STD], arg ptr[out, v4l2_std_id])
ioctl$VIDIOC_S_STD(fd fd_video, cmd const[VIDIOC_S_STD], arg ptr[in, v4l2_std_id])
ioctl$VIDIOC_ENUMSTD(fd fd_video, cmd const[VIDIOC_ENUMSTD], arg ptr[inout, v4l2_standard])
ioctl$VIDIOC_ENUMINPUT(fd fd_video, cmd const[VIDIOC_ENUMINPUT], arg ptr[inout, v4l2_input])
ioctl$VIDIOC_G_CTRL(fd fd_video, cmd const[VIDIOC_G_CTRL], arg ptr[inout, v4l2_control])
ioctl$VIDIOC_S_CTRL(fd fd_video, cmd const[VIDIOC_S_CTRL], arg ptr[inout, v4l2_control])
ioctl$VIDIOC_G_TUNER(fd fd_video, cmd const[VIDIOC_G_TUNER], arg ptr[inout, v4l2_tuner])
ioctl$VIDIOC_S_TUNER(fd fd_video, cmd const[VIDIOC_S_TUNER], arg ptr[in, v4l2_tuner])
ioctl$VIDIOC_G_AUDIO(fd fd_video, cmd const[VIDIOC_G_AUDIO], arg ptr[out, v4l2_audio])
ioctl$VIDIOC_S_AUDIO(fd fd_video, cmd const[VIDIOC_S_AUDIO], arg ptr[in, v4l2_audio])
ioctl$VIDIOC_QUERYCTRL(fd fd_video, cmd const[VIDIOC_QUERYCTRL], arg ptr[inout, v4l2_queryctrl])
ioctl$VIDIOC_QUERYMENU(fd fd_video, cmd const[VIDIOC_QUERYMENU], arg ptr[inout, v4l2_querymenu])
ioctl$VIDIOC_G_INPUT(fd fd_video, cmd const[VIDIOC_G_INPUT], arg ptr[out, int32])
ioctl$VIDIOC_S_INPUT(fd fd_video, cmd const[VIDIOC_S_INPUT], arg ptr[inout, int32])
ioctl$VIDIOC_G_EDID(fd fd_video, cmd const[VIDIOC_G_EDID], arg ptr[inout, v4l2_edid])
ioctl$VIDIOC_S_EDID(fd fd_video, cmd const[VIDIOC_S_EDID], arg ptr[inout, v4l2_edid])
ioctl$VIDIOC_G_OUTPUT(fd fd_video, cmd const[VIDIOC_G_OUTPUT], arg ptr[out, int32])
ioctl$VIDIOC_S_OUTPUT(fd fd_video, cmd const[VIDIOC_S_OUTPUT], arg ptr[inout, int32])
ioctl$VIDIOC_ENUMOUTPUT(fd fd_video, cmd const[VIDIOC_ENUMOUTPUT], arg ptr[inout, v4l2_output])
ioctl$VIDIOC_G_AUDOUT(fd fd_video, cmd const[VIDIOC_G_AUDOUT], arg ptr[out, v4l2_audioout])
ioctl$VIDIOC_S_AUDOUT(fd fd_video, cmd const[VIDIOC_S_AUDOUT], arg ptr[in, v4l2_audioout])
ioctl$VIDIOC_G_MODULATOR(fd fd_video, cmd const[VIDIOC_G_MODULATOR], arg ptr[inout, v4l2_modulator])
ioctl$VIDIOC_S_MODULATOR(fd fd_video, cmd const[VIDIOC_S_MODULATOR], arg ptr[in, v4l2_modulator])
ioctl$VIDIOC_G_FREQUENCY(fd fd_video, cmd const[VIDIOC_G_FREQUENCY], arg ptr[inout, v4l2_frequency])
ioctl$VIDIOC_S_FREQUENCY(fd fd_video, cmd const[VIDIOC_S_FREQUENCY], arg ptr[in, v4l2_frequency])
ioctl$VIDIOC_CROPCAP(fd fd_video, cmd const[VIDIOC_CROPCAP], arg ptr[inout, v4l2_cropcap])
ioctl$VIDIOC_G_CROP(fd fd_video, cmd const[VIDIOC_G_CROP], arg ptr[inout, v4l2_crop])
ioctl$VIDIOC_S_CROP(fd fd_video, cmd const[VIDIOC_S_CROP], arg ptr[in, v4l2_crop])
ioctl$VIDIOC_G_JPEGCOMP(fd fd_video, cmd const[VIDIOC_G_JPEGCOMP], arg ptr[out, v4l2_jpegcompression])
ioctl$VIDIOC_S_JPEGCOMP(fd fd_video, cmd const[VIDIOC_S_JPEGCOMP], arg ptr[in, v4l2_jpegcompression])
ioctl$VIDIOC_QUERYSTD(fd fd_video, cmd const[VIDIOC_QUERYSTD], arg ptr[out, v4l2_std_id])
ioctl$VIDIOC_TRY_FMT(fd fd_video, cmd const[VIDIOC_TRY_FMT], arg ptr[inout, v4l2_format[v4l2_buf_type]])
ioctl$VIDIOC_ENUMAUDIO(fd fd_video, cmd const[VIDIOC_ENUMAUDIO], arg ptr[inout, v4l2_audio])
ioctl$VIDIOC_ENUMAUDOUT(fd fd_video, cmd const[VIDIOC_ENUMAUDOUT], arg ptr[inout, v4l2_audioout])
ioctl$VIDIOC_G_PRIORITY(fd fd_video, cmd const[VIDIOC_G_PRIORITY], arg flags[v4l2_priority])
ioctl$VIDIOC_S_PRIORITY(fd fd_video, cmd const[VIDIOC_S_PRIORITY], arg flags[v4l2_priority])
ioctl$VIDIOC_G_SLICED_VBI_CAP(fd fd_video, cmd const[VIDIOC_G_SLICED_VBI_CAP], arg ptr[inout, v4l2_sliced_vbi_cap])
ioctl$VIDIOC_LOG_STATUS(fd fd_video, cmd const[VIDIOC_LOG_STATUS], arg const[0])
ioctl$VIDIOC_G_EXT_CTRLS(fd fd_video, cmd const[VIDIOC_G_EXT_CTRLS], arg ptr[inout, v4l2_ext_controls])
ioctl$VIDIOC_S_EXT_CTRLS(fd fd_video, cmd const[VIDIOC_S_EXT_CTRLS], arg ptr[inout, v4l2_ext_controls])
ioctl$VIDIOC_TRY_EXT_CTRLS(fd fd_video, cmd const[VIDIOC_TRY_EXT_CTRLS], arg ptr[inout, v4l2_ext_controls])
ioctl$VIDIOC_ENUM_FRAMESIZES(fd fd_video, cmd const[VIDIOC_ENUM_FRAMESIZES], arg ptr[inout, v4l2_frmsizeenum])
ioctl$VIDIOC_ENUM_FRAMEINTERVALS(fd fd_video, cmd const[VIDIOC_ENUM_FRAMEINTERVALS], arg ptr[inout, v4l2_frmivalenum])
ioctl$VIDIOC_G_ENC_INDEX(fd fd_video, cmd const[VIDIOC_G_ENC_INDEX], arg ptr[out, v4l2_enc_idx])
ioctl$VIDIOC_ENCODER_CMD(fd fd_video, cmd const[VIDIOC_ENCODER_CMD], arg ptr[inout, v4l2_encoder_cmd])
ioctl$VIDIOC_TRY_ENCODER_CMD(fd fd_video, cmd const[VIDIOC_TRY_ENCODER_CMD], arg ptr[inout, v4l2_encoder_cmd])
ioctl$VIDIOC_DBG_S_REGISTER(fd fd_video, cmd const[VIDIOC_DBG_S_REGISTER], arg ptr[in, v4l2_dbg_register])
ioctl$VIDIOC_DBG_G_REGISTER(fd fd_video, cmd const[VIDIOC_DBG_G_REGISTER], arg ptr[inout, v4l2_dbg_register])
ioctl$VIDIOC_S_HW_FREQ_SEEK(fd fd_video, cmd const[VIDIOC_S_HW_FREQ_SEEK], arg ptr[in, v4l2_hw_freq_seek])
ioctl$VIDIOC_S_DV_TIMINGS(fd fd_video, cmd const[VIDIOC_S_DV_TIMINGS], arg ptr[inout, v4l2_dv_timings])
ioctl$VIDIOC_G_DV_TIMINGS(fd fd_video, cmd const[VIDIOC_G_DV_TIMINGS], arg ptr[inout, v4l2_dv_timings])
ioctl$VIDIOC_DQEVENT(fd fd_video, cmd const[VIDIOC_DQEVENT], arg ptr[out, v4l2_event])
ioctl$VIDIOC_SUBSCRIBE_EVENT(fd fd_video, cmd const[VIDIOC_SUBSCRIBE_EVENT], arg ptr[in, v4l2_event_subscription])
ioctl$VIDIOC_UNSUBSCRIBE_EVENT(fd fd_video, cmd const[VIDIOC_UNSUBSCRIBE_EVENT], arg ptr[in, v4l2_event_subscription])
ioctl$VIDIOC_CREATE_BUFS(fd fd_video, cmd const[VIDIOC_CREATE_BUFS], arg ptr[inout, v4l2_create_buffers[v4l2_buf_type]])
ioctl$VIDIOC_PREPARE_BUF(fd fd_video, cmd const[VIDIOC_PREPARE_BUF], arg ptr[inout, v4l2_buffer_t[v4l2_buf_type]])
ioctl$VIDIOC_G_SELECTION(fd fd_video, cmd const[VIDIOC_G_SELECTION], arg ptr[inout, v4l2_selection])
ioctl$VIDIOC_S_SELECTION(fd fd_video, cmd const[VIDIOC_S_SELECTION], arg ptr[inout, v4l2_selection])
ioctl$VIDIOC_DECODER_CMD(fd fd_video, cmd const[VIDIOC_DECODER_CMD], arg ptr[inout, v4l2_decoder_cmd])
ioctl$VIDIOC_TRY_DECODER_CMD(fd fd_video, cmd const[VIDIOC_TRY_DECODER_CMD], arg ptr[inout, v4l2_decoder_cmd])
ioctl$VIDIOC_ENUM_DV_TIMINGS(fd fd_video, cmd const[VIDIOC_ENUM_DV_TIMINGS], arg ptr[inout, v4l2_enum_dv_timings])
ioctl$VIDIOC_QUERY_DV_TIMINGS(fd fd_video, cmd const[VIDIOC_QUERY_DV_TIMINGS], arg ptr[out, v4l2_dv_timings])
ioctl$VIDIOC_DV_TIMINGS_CAP(fd fd_video, cmd const[VIDIOC_DV_TIMINGS_CAP], arg ptr[inout, v4l2_dv_timings_cap])
ioctl$VIDIOC_ENUM_FREQ_BANDS(fd fd_video, cmd const[VIDIOC_ENUM_FREQ_BANDS], arg ptr[inout, v4l2_frequency_band])
ioctl$VIDIOC_DBG_G_CHIP_INFO(fd fd_video, cmd const[VIDIOC_DBG_G_CHIP_INFO], arg ptr[inout, v4l2_dbg_chip_info])
ioctl$VIDIOC_QUERY_EXT_CTRL(fd fd_video, cmd const[VIDIOC_QUERY_EXT_CTRL], arg ptr[inout, v4l2_query_ext_ctrl])
ioctl$VIDIOC_SUBDEV_G_FMT(fd fd_video, cmd const[VIDIOC_SUBDEV_G_FMT], arg ptr[inout, v4l2_subdev_format])
ioctl$VIDIOC_SUBDEV_S_FMT(fd fd_video, cmd const[VIDIOC_SUBDEV_S_FMT], arg ptr[inout, v4l2_subdev_format])
ioctl$VIDIOC_SUBDEV_G_FRAME_INTERVAL(fd fd_video, cmd const[VIDIOC_SUBDEV_G_FRAME_INTERVAL], arg ptr[inout, v4l2_subdev_frame_interval])
ioctl$VIDIOC_SUBDEV_S_FRAME_INTERVAL(fd fd_video, cmd const[VIDIOC_SUBDEV_S_FRAME_INTERVAL], arg ptr[inout, v4l2_subdev_frame_interval])
ioctl$VIDIOC_SUBDEV_ENUM_MBUS_CODE(fd fd_video, cmd const[VIDIOC_SUBDEV_ENUM_MBUS_CODE], arg ptr[inout, v4l2_subdev_mbus_code_enum])
ioctl$VIDIOC_SUBDEV_ENUM_FRAME_SIZE(fd fd_video, cmd const[VIDIOC_SUBDEV_ENUM_FRAME_SIZE], arg ptr[inout, v4l2_subdev_frame_size_enum])
ioctl$VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL(fd fd_video, cmd const[VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL], arg ptr[inout, v4l2_subdev_frame_interval_enum])
ioctl$VIDIOC_SUBDEV_G_CROP(fd fd_video, cmd const[VIDIOC_SUBDEV_G_CROP], arg ptr[inout, v4l2_subdev_crop])
ioctl$VIDIOC_SUBDEV_S_CROP(fd fd_video, cmd const[VIDIOC_SUBDEV_S_CROP], arg ptr[inout, v4l2_subdev_crop])
ioctl$VIDIOC_SUBDEV_G_SELECTION(fd fd_video, cmd const[VIDIOC_SUBDEV_G_SELECTION], arg ptr[inout, v4l2_subdev_selection])
ioctl$VIDIOC_SUBDEV_S_SELECTION(fd fd_video, cmd const[VIDIOC_SUBDEV_S_SELECTION], arg ptr[inout, v4l2_subdev_selection])
ioctl$VIDIOC_SUBDEV_G_EDID(fd fd_video, cmd const[VIDIOC_SUBDEV_G_EDID], arg ptr[inout, v4l2_edid])
ioctl$VIDIOC_SUBDEV_S_EDID(fd fd_video, cmd const[VIDIOC_SUBDEV_S_EDID], arg ptr[inout, v4l2_edid])
ioctl$VIDIOC_SUBDEV_S_DV_TIMINGS(fd fd_video, cmd const[VIDIOC_SUBDEV_S_DV_TIMINGS], arg ptr[inout, v4l2_dv_timings])
ioctl$VIDIOC_SUBDEV_G_DV_TIMINGS(fd fd_video, cmd const[VIDIOC_SUBDEV_G_DV_TIMINGS], arg ptr[inout, v4l2_dv_timings])
ioctl$VIDIOC_SUBDEV_ENUM_DV_TIMINGS(fd fd_video, cmd const[VIDIOC_SUBDEV_ENUM_DV_TIMINGS], arg ptr[inout, v4l2_enum_dv_timings])
ioctl$VIDIOC_SUBDEV_QUERY_DV_TIMINGS(fd fd_video, cmd const[VIDIOC_SUBDEV_QUERY_DV_TIMINGS], arg ptr[out, v4l2_dv_timings])
ioctl$VIDIOC_SUBDEV_DV_TIMINGS_CAP(fd fd_video, cmd const[VIDIOC_SUBDEV_DV_TIMINGS_CAP], arg ptr[inout, v4l2_dv_timings_cap])

# Generally we don't specify close on resources,
# but fd_v4l2_buffer is not used as input anywhere else (why is it needed?).
# So this is added to prevent compilation errors.
close$fd_v4l2_buffer(fd fd_v4l2_buffer)

v4l2_capability {
	driver		array[int8, 16]
	card		array[int8, 32]
	bus_info	array[int8, 32]
	version		int32
	capabilities	flags[v4l2_capability_capabilities, int32]
	device_caps	int32
	reserved	array[const[0, int32], 3]
}

type v4l2_fmtdesc[BUF_TYPE] {
	index		int32
	type		flags[BUF_TYPE, int32]
	flags		flags[v4l2_fmtdesc_flags, int32]
	description	array[int8, 32]
	pixelformat	flags[v4l2_pix_format_pixelformat, int32]
	reserved	array[const[0, int32], 4]
}

type v4l2_format[BUF_TYPE] {
	type	flags[BUF_TYPE, int32]
	fmt	v4l2_format_fmt
}

v4l2_format_fmt [
	pix		v4l2_pix_format
	pix_mp		v4l2_pix_format_mplane
	win		v4l2_window
	vbi		v4l2_vbi_format
	sliced		v4l2_sliced_vbi_format
	sdr		v4l2_sdr_format
	meta		v4l2_meta_format
	raw_data	array[int8, 200]
]

v4l2_pix_format {
	width		int32
	height		int32
	pixelformat	flags[v4l2_pix_format_pixelformat, int32]
	field		flags[v4l2_field, int32]
	bytesperline	int32
	sizeimage	int32
	colorspace	flags[v4l2_colorspace, int32]
	priv		int32
	flags		flags[v4l2_pix_format_flags, int32]
	ycbcr_enc	flags[v4l2_ycbcr_encoding, int32]
	quantization	flags[v4l2_quantization, int32]
	xfer_func	flags[v4l2_xfer_func, int32]
}

v4l2_pix_format_mplane {
	width		int32
	height		int32
	pixelformat	flags[v4l2_pix_format_pixelformat, int32]
	field		flags[v4l2_field, int32]
	colorspace	flags[v4l2_colorspace, int32]
	plane_fmt	array[v4l2_plane_pix_format, 8]
	num_planes	int8
	flags		int8
	ycbcr_enc	flags[v4l2_ycbcr_encoding, int8]
	quantization	flags[v4l2_quantization, int8]
	xfer_func	flags[v4l2_xfer_func, int8]
	reserved	array[const[0, int8], 7]
} [packed]

v4l2_plane_pix_format {
	sizeimage	int32
	bytesperline	int32
	reserved	array[const[0, int16], 6]
} [packed]

v4l2_window {
	w		v4l2_rect
	field		flags[v4l2_field, int32]
	chromakey	int32
	clips		ptr[inout, v4l2_clip]
	clipcount	int32
	bitmap		buffer[inout]
	global_alpha	int8
}

v4l2_rect {
	left	int32
	top	int32
	width	int32
	height	int32
}

v4l2_clip {
	c	v4l2_rect
	next	ptr[inout, v4l2_clip, opt]
}

v4l2_vbi_format {
	sampling_rate		int32
	offset			int32
	samples_per_line	int32
	sample_format		flags[v4l2_pix_format_pixelformat, int32]
	start			array[int32, 2]
	count			array[int32, 2]
	flags			flags[v4l2_vbi_format_flags, int32]
	reserved		array[const[0, int32], 2]
}

v4l2_sliced_vbi_format {
	service_set	int16
	service_lines	array[int16, 48]
	io_size		int32
	reserved	array[const[0, int32], 2]
}

v4l2_sdr_format {
	pixelformat	flags[v4l2_pix_format_pixelformat, int32]
	buffersize	int32
	reserved	array[const[0, int8], 24]
} [packed]

v4l2_meta_format {
	dataformat	flags[v4l2_meta_data_formats, int32]
	buffersize	int32[0:0x7fffffff]
	width		int32[0:65535]
	height		int32[0:65535]
	bytesperline	int32[0:0x7fffffff]
} [packed]

type v4l2_requestbuffers[BUF_TYPE] {
	count		int32
	type		flags[BUF_TYPE, int32]
	memory		flags[v4l2_memory, int32]
	capabilities	const[0, int32]
	flags		int8
	reserved	array[const[0, int8], 3]
}

type v4l2_buffer_t[BUF_TYPE] [
	mmap			v4l2_buffer[BUF_TYPE, V4L2_MEMORY_MMAP, intptr]
	userptr			v4l2_buffer[BUF_TYPE, V4L2_MEMORY_USERPTR, ptr[out, int8]]
	overlay			v4l2_buffer[BUF_TYPE, V4L2_MEMORY_OVERLAY, int32]
	fd			v4l2_buffer[BUF_TYPE, V4L2_MEMORY_DMABUF, fd_v4l2_buffer[opt]]
	multiplanar_mmap	v4l2_buffer[BUF_TYPE, V4L2_MEMORY_MMAP, ptr[inout, array[v4l2_plane[intptr], 2]]]
	multiplanar_userptr	v4l2_buffer[BUF_TYPE, V4L2_MEMORY_USERPTR, ptr[inout, array[v4l2_plane[ptr[out, int8]], 2]]]
	multiplanar_overlay	v4l2_buffer[BUF_TYPE, V4L2_MEMORY_OVERLAY, ptr[inout, array[v4l2_plane[int32], 2]]]
	multiplanar_fd		v4l2_buffer[BUF_TYPE, V4L2_MEMORY_DMABUF, ptr[inout, array[v4l2_plane[fd_v4l2_buffer[opt]], 2]]]
]

# TODO: The field directions needs to be defined. Recursively v4l2_plane, v4l2_plane_union needs checking.
type v4l2_buffer[BUF_TYPE, MEM_TYPE, ARG_TYPE] {
	index		int32
	type		flags[BUF_TYPE, int32]
	bytesused	len[type, int32]
	flags		flags[v4l2_buffer_flags, int32]
	field		int32
	timestamp	timeval
	timecode	v4l2_timecode
	sequence	int32
	memory		const[MEM_TYPE, int32]
	m		alignptr[ARG_TYPE]	(out)
	length		int32
	reserved2	const[0, int32]
	request_fd	fd_request[opt]
}

v4l2_timecode {
	type		flags[v4l2_timecode_type, int32]
	flags		flags[v4l2_timecode_flags, int32]
	frames		int8
	seconds		int8
	minutes		int8
	hours		int8
	userbits	array[int8, 4]
}

type v4l2_plane[ARG_TYPE] {
	bytesused	int32
	length		int32
	m		alignptr[ARG_TYPE]
	data_offset	int32
	reserved	array[const[0, int32], 11]
}

v4l2_framebuffer {
	capability	flags[v4l2_framebuffer_capability, int32]
	flags		flags[v4l2_framebuffer_flags, int32]
	base		buffer[inout]
	fmt		v4l2_framebuffer_union
}

v4l2_framebuffer_union {
	width		int32
	height		int32
	pixelformat	flags[v4l2_pix_format_pixelformat, int32]
	field		flags[v4l2_field, int32]
	bytesperline	int32
	sizeimage	int32
	colorspace	flags[v4l2_colorspace, int32]
	priv		int32
}

type v4l2_exportbuffer[BUF_TYPE] {
	type		flags[BUF_TYPE, int32]
	index		int32
	plane		int32
	flags		flags[pipe_flags, int32]
	fd		fd_dma_buf	(out)
	reserved	array[const[0, int32], 11]
}

v4l2_streamparm {
	type	flags[v4l2_buf_type, int32]
	parm	v4l2_streamparm_union
}

v4l2_streamparm_union [
	capture		v4l2_captureparm
	output		v4l2_outputparm
	raw_data	array[int8, 200]
]

v4l2_captureparm {
	capability	flags[v4l2_captureparm_cap, int32]
	capturemode	flags[v4l2_captureparm_mode, int32]
	timeperframe	v4l2_fract
	extendedmode	int32
	readbuffers	int32
	reserved	array[const[0, int32], 4]
}

v4l2_fract {
	numerator	int32
	denominator	int32
}

v4l2_outputparm {
	capability	flags[v4l2_captureparm_cap, int32]
	outputmode	flags[v4l2_captureparm_mode, int32]
	timeperframe	v4l2_fract
	extendedmode	int32
	writebuffers	int32
	reserved	array[const[0, int32], 4]
}

v4l2_control {
	id	int32
	value	int32
}

v4l2_tuner {
	index		int32
	name		array[int8, 32]
	type		flags[v4l2_tuner_type, int32]
	capability	flags[v4l2_tuner_capability, int32]
	rangelow	int32
	rangehigh	int32
	rxsubchans	flags[v4l2_tuner_rxsubchans, int32]
	audmode		flags[v4l2_tuner_audmode, int32]
	signal		int32
	afc		int32
	reserved	array[const[0, int32], 4]
}

v4l2_audio {
	index		int32
	name		array[int8, 32]
	capability	flags[v4l2_audio_capability, int32]
	mode		flags[v4l2_audio_mode, int32]
	reserved	array[const[0, int32], 2]
}

v4l2_queryctrl {
	id		int32
	type		flags[v4l2_ctrl_type, int32]
	name		array[int8, 32]
	minimum		int32
	maximum		int32
	step		int32
	default_value	int32
	flags		flags[v4l2_control_flags, int32]
	reserved	array[const[0, int32], 2]
}

v4l2_querymenu {
	id		int32
	index		int32
	union		v4l2_querymenu_union
	reserved	const[0, int32]
} [packed]

v4l2_querymenu_union [
	name	array[int8, 32]
	value	int64
]

v4l2_edid {
	pad		const[0, int32]
	start_block	int32
	blocks		int32
	reserved	array[const[0, int32], 5]
	edid		ptr[inout, int8]
}

v4l2_audioout {
	index		int32
	name		array[int8, 32]
	capability	flags[v4l2_audio_capability, int32]
	mode		flags[v4l2_audio_mode, int32]
	reserved	array[const[0, int32], 2]
}

v4l2_modulator {
	index		int32
	name		array[int8, 32]
	capability	flags[v4l2_tuner_capability, int32]
	rangelow	int32
	rangehigh	int32
	txsubchans	flags[v4l2_tuner_rxsubchans, int32]
	type		flags[v4l2_tuner_type, int32]
	reserved	array[const[0, int32], 3]
}

v4l2_frequency {
	tuner		int32
	type		flags[v4l2_tuner_type, int32]
	frequency	int32
	reserved	array[const[0, int32], 8]
}

v4l2_cropcap {
	type		flags[v4l2_buf_type, int32]
	bounds		v4l2_rect
	defrect		v4l2_rect
	pixelaspect	v4l2_fract
}

v4l2_crop {
	type	flags[v4l2_buf_type, int32]
	c	v4l2_rect
}

v4l2_jpegcompression {
	quality		int32
	APPn		int32[0:15]
	APP_len		int32[0:60]
	APP_data	array[int8, 60]
	COM_len		int32[0:60]
	COM_data	array[int8, 60]
	jpeg_markers	flags[v4l2_jpeg_markers, int32]
}

v4l2_sliced_vbi_cap {
	service_set	int16
	service_lines	array[int16, 48]
	type		flags[v4l2_buf_type, int32]
	reserved	array[const[0, int32], 3]
}

v4l2_ext_controls {
	ctrl_class	flags[v4l2_ext_ctrl_class, int32]
	count		int32
	error_idx	int32
	request_fd	fd_request[opt]	(in)
	reserved	const[0, int32]
	controls	ptr[inout, v4l2_ext_control]
}

v4l2_ext_control {
	id		flags[v4l2_ext_controls, int32]
	size		int32
	reserved2	array[const[0, int32], 1]
	union		v4l2_ext_u
} [packed]

v4l2_ext_u [
	value	int32
	value64	int64
	string	ptr[inout, int8]
	p_u8	ptr[inout, int8]
	p_u16	ptr[inout, int16]
	p_u32	ptr[inout, int32]
	ptr	intptr
]

v4l2_frmsizeenum {
	index		int32
	pixel_format	flags[v4l2_pix_format_pixelformat, int32]
	type		flags[v4l2_frmsizetypes, int32]
	union		v4l2_frmsizeenum_union
	reserved	array[const[0, int32], 2]
}

v4l2_frmsizeenum_union [
	discrete	v4l2_frmsize_discrete
	stepwise	v4l2_frmsize_stepwise
]

v4l2_frmsize_discrete {
	width	int32
	height	int32
}

v4l2_frmsize_stepwise {
	min_width	int32
	max_width	int32
	step_width	int32
	min_height	int32
	max_height	int32
	step_height	int32
}

v4l2_frmivalenum {
	index		int32
	pixel_format	flags[v4l2_pix_format_pixelformat, int32]
	width		int32
	height		int32
	type		flags[v4l2_frmivaltypes, int32]
	union		v4l2_frmivalenum_union
	reserved	array[const[0, int32], 2]
}

v4l2_frmivalenum_union [
	discrete	v4l2_fract
	stepwise	v4l2_frmival_stepwise
]

v4l2_frmival_stepwise {
	min	v4l2_fract
	max	v4l2_fract
	step	v4l2_fract
}

v4l2_enc_idx {
	entries		int32
	entries_cap	int32
	reserved	array[const[0, int32], 4]
	entry		array[v4l2_enc_idx_entry, 64]
}

v4l2_enc_idx_entry {
	offset		int64
	pts		int64
	length		int32
	flags		flags[v4l2_enc_idx_flags, int32]
	reserved	array[const[0, int32], 2]
}

v4l2_dbg_register {
	match	v4l2_dbg_match
	size	bytesize[reg, int32]
	reg	int64
	val	int64
} [packed]

v4l2_dbg_match {
	type	flags[v4l2_dbg_match_type, int32]
	union	v4l2_dbg_match_union
} [packed]

v4l2_dbg_match_union [
	addr	int32
	name	array[int8, 32]
]

v4l2_hw_freq_seek {
	tuner		int32
	type		flags[v4l2_tuner_type, int32]
	seek_upward	int32
	wrap_around	int32
	spacing		int32
	rangelow	int32
	rangehigh	int32
	reserved	array[const[0, int32], 5]
}

v4l2_dv_timings {
	type	flags[v4l2_dv_timings_type, int32]
	union	v4l2_dv_timings_union
} [packed]

v4l2_dv_timings_union [
	bt		v4l2_bt_timings
	reserved	array[const[0, int32], 32]
]

v4l2_bt_timings {
	width		int32
	height		int32
	interlaced	flags[v4l2_bt_timings_interlaced, int32]
	polarities	flags[v4l2_bt_timings_polarities, int32]
	pixelclock	int64
	hfrontporch	int32
	hsync		int32
	hbackporch	int32
	vfrontporch	int32
	vsync		int32
	vbackporch	int32
	il_vfrontporch	int32
	il_vsync	int32
	il_vbackporch	int32
	standards	flags[v4l2_bt_timings_standards, int32]
	flags		flags[v4l2_bt_timings_flags, int32]
	picture_aspect	v4l2_fract
	cea861_vic	int8
	hdmi_vic	int8
	reserved	array[const[0, int8], 46]
} [packed]

v4l2_encoder_cmd {
	cmd	flags[v4l2_encoder_cmd_cmd, int32]
	flags	flags[v4l2_encoder_flags, int32]
	data	array[int32, 8]
}

v4l2_event {
	type		flags[v4l2_event_type, int32]
	u		v4l2_event_union
	pending		int32
	sequence	int32
	timestamp	timespec
	id		int32
	reserved	array[const[0, int32], 8]
}

v4l2_event_union [
	vsync		v4l2_event_vsync
	ctrl		v4l2_event_ctrl
	frame_sync	v4l2_event_frame_sync
	src_change	v4l2_event_src_change
	motion_det	v4l2_event_motion_det
	data		array[int8, 64]
]

v4l2_event_vsync {
	field	flags[v4l2_field_1, int8]
} [packed]

v4l2_event_ctrl {
	changes		flags[v4l2_event_ctrl_changes, int32]
	type		flags[v4l2_ctrl_type, int32]
	u		v4l2_event_ctrl_union
	flags		int32
	minimum		int32
	maximum		int32
	step		int32
	default_value	int32
}

v4l2_event_ctrl_union [
	value	int32
	value64	int64
]

v4l2_event_frame_sync {
	frame_sequence	int32
}

v4l2_event_src_change {
	changes	flags[v4l2_event_src_changes, int32]
}

v4l2_event_motion_det {
	flags		flags[v4l2_event_motion_det_flags, int32]
	frame_sequence	int32
	region_mask	int32
}

v4l2_event_subscription {
	type		flags[v4l2_event_type, int32]
	id		int32
	flags		flags[v4l2_event_subscription_flags, int32]
	reserved	array[const[0, int32], 5]
}

type v4l2_create_buffers[BUF_TYPE] {
	index		int32
	count		int32
	memory		flags[v4l2_memory, int32]
	format		v4l2_format[BUF_TYPE]
	capabilities	int32
	reserved	array[const[0, int32], 7]
}

v4l2_selection {
	type		flags[v4l2_buf_type_1, int32]
	target		flags[v4l2_selection_target, int32]
	flags		flags[v4l2_selection_flags, int32]
	r		v4l2_rect
	reserved	array[const[0, int32], 9]
}

v4l2_decoder_cmd {
	cmd	flags[v4l2_decoder_cmd_cmd, int32]
	flags	flags[v4l2_decoder_cmd_flags, int32]
	u	v4l2_decoder_cmd_u
}

v4l2_decoder_cmd_u [
	stop_pts	int64
	start		v4l2_decoder_cmd_start
	raw_data	array[int32, 16]
]

v4l2_decoder_cmd_start {
	speed	int32
	format	flags[v4l2_decoder_cmd_format, int32]
}

v4l2_enum_dv_timings {
	index		int32
	pad		const[0, int32]
	reserved	array[const[0, int32], 2]
	timings		v4l2_dv_timings
}

v4l2_dv_timings_cap {
	type		flags[v4l2_dv_timings_type, int32]
	pad		const[0, int32]
	reserved	array[const[0, int32], 2]
	u		v4l2_dv_timings_cap_u
}

v4l2_dv_timings_cap_u [
	bt		v4l2_bt_timings_cap
	raw_data	array[int32, 32]
]

v4l2_bt_timings_cap {
	min_width	int32
	max_width	int32
	min_height	int32
	max_height	int32
	min_pixelclock	int64
	max_pixelclock	int64
	standards	flags[v4l2_bt_timings_standards, int32]
	capabilities	flags[v4l2_bt_timings_cap_capabilities, int32]
	reserved	array[const[0, int32], 16]
} [packed]

v4l2_frequency_band {
	tuner		int32
	type		flags[v4l2_tuner_type, int32]
	index		int32
	capability	flags[v4l2_tuner_capability, int32]
	rangelow	int32
	rangehigh	int32
	modulation	flags[v4l2_frequency_band_modulation, int32]
	reserved	array[const[0, int32], 9]
}

v4l2_dbg_chip_info {
	match		v4l2_dbg_match
	name		array[int8, 32]
	flags		flags[v4l2_dbg_chip_info_flags, int32]
	reserved	array[const[0, int32], 32]
} [packed]

v4l2_query_ext_ctrl {
	id		flags[v4l2_query_ext_ctrl, int32]
	type		flags[v4l2_ctrl_type, int32]
	name		array[int8, 32]
	minimum		int64
	maximum		int64
	step		int64
	default_value	int64
	flags		int32
	elem_size	int32
	elems		int32
	nr_of_dims	int32
	dims		array[int32, 4]
	reserved	array[const[0, int32], 32]
}

type v4l2_std_id flags[v4l2_std_id, int64]

v4l2_standard {
	index		int32
	id		v4l2_std_id
	name		array[int8, 24]
	frameperiod	v4l2_fract
	framelines	int32
	reserved	array[const[0, int32], 4]
}

v4l2_input {
	index		int32
	name		array[int8, 32]
	type		flags[v4l2_input_type, int32]
	audioset	int32
	tuner		flags[v4l2_tuner_type, int32]
	std		v4l2_std_id
	status		flags[v4l2_input_status, int32]
	capabilities	flags[v4l2_input_capabilities, int32]
	reserved	array[const[0, int32], 3]
}

v4l2_output {
	index		int32
	name		array[int8, 32]
	type		flags[v4l2_output_type, int32]
	audioset	int32
	modulator	int32
	std		v4l2_std_id
	capabilities	flags[v4l2_output_capabilities, int32]
	reserved	array[const[0, int32], 3]
}

v4l2_subdev_format {
	which		flags[v4l2_subdev_format_whence, int32]
	pad		const[0, int32]
	format		v4l2_mbus_framefmt
	reserved	array[const[0, int32], 8]
}

v4l2_mbus_framefmt {
	width		int32
	height		int32
	code		flags[media_bus_fmt, int32]
	field		flags[v4l2_field, int32]
	colorspace	flags[v4l2_colorspace, int32]
	ycbcr_enc	flags[v4l2_ycbcr_encoding, int16]
	quantization	flags[v4l2_quantization, int16]
	xfer_func	flags[v4l2_xfer_func, int16]
	reserved	array[const[0, int16], 11]
}

v4l2_subdev_frame_interval {
	pad		const[0, int32]
	interval	v4l2_fract
	reserved	array[const[0, int32], 9]
}

v4l2_subdev_mbus_code_enum {
	pad		const[0, int32]
	index		int32
	code		flags[media_bus_fmt, int32]
	which		flags[v4l2_subdev_format_whence, int32]
	reserved	array[const[0, int32], 8]
}

v4l2_subdev_frame_size_enum {
	index		int32
	pad		const[0, int32]
	code		flags[media_bus_fmt, int32]
	min_width	int32
	max_width	int32
	min_height	int32
	max_height	int32
	which		flags[v4l2_subdev_format_whence, int32]
	reserved	array[const[0, int32], 8]
}

v4l2_subdev_frame_interval_enum {
	index		int32
	pad		const[0, int32]
	code		flags[media_bus_fmt, int32]
	width		int32
	height		int32
	interval	v4l2_fract
	which		flags[v4l2_subdev_format_whence, int32]
	reserved	array[const[0, int32], 8]
}

v4l2_subdev_crop {
	which		flags[v4l2_subdev_format_whence, int32]
	pad		const[0, int32]
	rect		v4l2_rect
	reserved	array[const[0, int32], 8]
}

v4l2_subdev_selection {
	which		flags[v4l2_subdev_format_whence, int32]
	pad		const[0, int32]
	target		flags[v4l2_selection_target, int32]
	flags		flags[v4l2_selection_flags, int32]
	r		v4l2_rect
	reserved	array[const[0, int32], 8]
}

v4l2_jpeg_markers = V4L2_JPEG_MARKER_DHT, V4L2_JPEG_MARKER_DQT, V4L2_JPEG_MARKER_DRI, V4L2_JPEG_MARKER_COM, V4L2_JPEG_MARKER_APP
v4l2_subdev_format_whence = V4L2_SUBDEV_FORMAT_TRY, V4L2_SUBDEV_FORMAT_ACTIVE
v4l2_buf_type_1 = V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_BUF_TYPE_VIDEO_OUTPUT, V4L2_BUF_TYPE_VIDEO_OVERLAY, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_BUF_TYPE_VBI_OUTPUT, V4L2_BUF_TYPE_SLICED_VBI_CAPTURE, V4L2_BUF_TYPE_SLICED_VBI_OUTPUT, V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY, V4L2_BUF_TYPE_SDR_CAPTURE, V4L2_BUF_TYPE_SDR_OUTPUT, V4L2_BUF_TYPE_META_CAPTURE, V4L2_BUF_TYPE_META_OUTPUT
v4l2_field_1 = V4L2_FIELD_ANY, V4L2_FIELD_NONE, V4L2_FIELD_TOP, V4L2_FIELD_BOTTOM
v4l2_field = V4L2_FIELD_INTERLACED, V4L2_FIELD_SEQ_TB, V4L2_FIELD_SEQ_BT, V4L2_FIELD_ALTERNATE, V4L2_FIELD_INTERLACED_TB, V4L2_FIELD_INTERLACED_BT, v4l2_field_1
v4l2_colorspace = V4L2_COLORSPACE_DEFAULT, V4L2_COLORSPACE_SMPTE170M, V4L2_COLORSPACE_SMPTE240M, V4L2_COLORSPACE_REC709, V4L2_COLORSPACE_BT878, V4L2_COLORSPACE_470_SYSTEM_M, V4L2_COLORSPACE_470_SYSTEM_BG, V4L2_COLORSPACE_JPEG, V4L2_COLORSPACE_SRGB, V4L2_COLORSPACE_OPRGB, V4L2_COLORSPACE_BT2020, V4L2_COLORSPACE_RAW, V4L2_COLORSPACE_DCI_P3
v4l2_ycbcr_encoding = V4L2_YCBCR_ENC_DEFAULT, V4L2_YCBCR_ENC_601, V4L2_YCBCR_ENC_709, V4L2_YCBCR_ENC_XV601, V4L2_YCBCR_ENC_XV709, V4L2_YCBCR_ENC_BT2020, V4L2_YCBCR_ENC_BT2020_CONST_LUM, V4L2_YCBCR_ENC_SMPTE240M
v4l2_quantization = V4L2_QUANTIZATION_DEFAULT, V4L2_QUANTIZATION_FULL_RANGE, V4L2_QUANTIZATION_LIM_RANGE
v4l2_xfer_func = V4L2_XFER_FUNC_DEFAULT, V4L2_XFER_FUNC_709, V4L2_XFER_FUNC_SRGB, V4L2_XFER_FUNC_OPRGB, V4L2_XFER_FUNC_SMPTE240M, V4L2_XFER_FUNC_NONE, V4L2_XFER_FUNC_DCI_P3, V4L2_XFER_FUNC_SMPTE2084
v4l2_buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, v4l2_buf_type_1
v4l2_memory = V4L2_MEMORY_MMAP, V4L2_MEMORY_USERPTR, V4L2_MEMORY_OVERLAY, V4L2_MEMORY_DMABUF
v4l2_tuner_type = V4L2_TUNER_RADIO, V4L2_TUNER_ANALOG_TV, V4L2_TUNER_DIGITAL_TV, V4L2_TUNER_SDR, V4L2_TUNER_RF
v4l2_ctrl_type = V4L2_CTRL_TYPE_INTEGER, V4L2_CTRL_TYPE_BOOLEAN, V4L2_CTRL_TYPE_MENU, V4L2_CTRL_TYPE_BUTTON, V4L2_CTRL_TYPE_INTEGER64, V4L2_CTRL_TYPE_CTRL_CLASS, V4L2_CTRL_TYPE_STRING, V4L2_CTRL_TYPE_BITMASK, V4L2_CTRL_TYPE_INTEGER_MENU, V4L2_CTRL_COMPOUND_TYPES, V4L2_CTRL_TYPE_U8, V4L2_CTRL_TYPE_U16, V4L2_CTRL_TYPE_U32, V4L2_CTRL_TYPE_AREA, V4L2_CTRL_TYPE_RECT, V4L2_CTRL_TYPE_HDR10_CLL_INFO, V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY, V4L2_CTRL_TYPE_H264_SPS, V4L2_CTRL_TYPE_H264_PPS, V4L2_CTRL_TYPE_H264_SCALING_MATRIX, V4L2_CTRL_TYPE_H264_SLICE_PARAMS, V4L2_CTRL_TYPE_H264_DECODE_PARAMS, V4L2_CTRL_TYPE_H264_PRED_WEIGHTS, V4L2_CTRL_TYPE_FWHT_PARAMS, V4L2_CTRL_TYPE_VP8_FRAME, V4L2_CTRL_TYPE_MPEG2_QUANTISATION, V4L2_CTRL_TYPE_MPEG2_SEQUENCE, V4L2_CTRL_TYPE_MPEG2_PICTURE, V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR, V4L2_CTRL_TYPE_VP9_FRAME, V4L2_CTRL_TYPE_HEVC_SPS, V4L2_CTRL_TYPE_HEVC_PPS, V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS, V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX, V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS, V4L2_CTRL_TYPE_AV1_SEQUENCE, V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY, V4L2_CTRL_TYPE_AV1_FRAME, V4L2_CTRL_TYPE_AV1_FILM_GRAIN
v4l2_priority = V4L2_PRIORITY_UNSET, V4L2_PRIORITY_BACKGROUND, V4L2_PRIORITY_INTERACTIVE, V4L2_PRIORITY_RECORD, V4L2_PRIORITY_DEFAULT
media_bus_fmt = MEDIA_BUS_FMT_FIXED, MEDIA_BUS_FMT_RGB444_1X12, MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE, MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE, MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, MEDIA_BUS_FMT_RGB565_1X16, MEDIA_BUS_FMT_BGR565_2X8_BE, MEDIA_BUS_FMT_BGR565_2X8_LE, MEDIA_BUS_FMT_RGB565_2X8_BE, MEDIA_BUS_FMT_RGB565_2X8_LE, MEDIA_BUS_FMT_RGB666_1X18, MEDIA_BUS_FMT_RBG888_1X24, MEDIA_BUS_FMT_RGB666_1X24_CPADHI, MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, MEDIA_BUS_FMT_BGR888_1X24, MEDIA_BUS_FMT_GBR888_1X24, MEDIA_BUS_FMT_RGB888_1X24, MEDIA_BUS_FMT_RGB888_2X12_BE, MEDIA_BUS_FMT_RGB888_2X12_LE, MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, MEDIA_BUS_FMT_ARGB8888_1X32, MEDIA_BUS_FMT_RGB888_1X32_PADHI, MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_UV8_1X8, MEDIA_BUS_FMT_UYVY8_1_5X8, MEDIA_BUS_FMT_VYUY8_1_5X8, MEDIA_BUS_FMT_YUYV8_1_5X8, MEDIA_BUS_FMT_YVYU8_1_5X8, MEDIA_BUS_FMT_UYVY8_2X8, MEDIA_BUS_FMT_VYUY8_2X8, MEDIA_BUS_FMT_YUYV8_2X8, MEDIA_BUS_FMT_YVYU8_2X8, MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_UYVY10_2X10, MEDIA_BUS_FMT_VYUY10_2X10, MEDIA_BUS_FMT_YUYV10_2X10, MEDIA_BUS_FMT_YVYU10_2X10, MEDIA_BUS_FMT_Y12_1X12, MEDIA_BUS_FMT_UYVY12_2X12, MEDIA_BUS_FMT_VYUY12_2X12, MEDIA_BUS_FMT_YUYV12_2X12, MEDIA_BUS_FMT_YVYU12_2X12, MEDIA_BUS_FMT_UYVY8_1X16, MEDIA_BUS_FMT_VYUY8_1X16, MEDIA_BUS_FMT_YUYV8_1X16, MEDIA_BUS_FMT_YVYU8_1X16, MEDIA_BUS_FMT_YDYUYDYV8_1X16, MEDIA_BUS_FMT_UYVY10_1X20, MEDIA_BUS_FMT_VYUY10_1X20, MEDIA_BUS_FMT_YUYV10_1X20, MEDIA_BUS_FMT_YVYU10_1X20, MEDIA_BUS_FMT_VUY8_1X24, MEDIA_BUS_FMT_YUV8_1X24, MEDIA_BUS_FMT_UYVY12_1X24, MEDIA_BUS_FMT_VYUY12_1X24, MEDIA_BUS_FMT_YUYV12_1X24, MEDIA_BUS_FMT_YVYU12_1X24, MEDIA_BUS_FMT_YUV10_1X30, MEDIA_BUS_FMT_AYUV8_1X32, MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8, MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8, MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8, MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8, MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8, MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8, MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8, MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE, MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE, MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE, MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_JPEG_1X8, MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8, MEDIA_BUS_FMT_AHSV8888_1X32
v4l2_pix_format_flags = V4L2_PIX_FMT_FLAG_PREMUL_ALPHA
v4l2_pix_format_pixelformat = V4L2_PIX_FMT_RGB332, V4L2_PIX_FMT_RGB444, V4L2_PIX_FMT_ARGB444, V4L2_PIX_FMT_XRGB444, V4L2_PIX_FMT_RGB555, V4L2_PIX_FMT_ARGB555, V4L2_PIX_FMT_XRGB555, V4L2_PIX_FMT_RGB565, V4L2_PIX_FMT_RGB555X, V4L2_PIX_FMT_ARGB555X, V4L2_PIX_FMT_XRGB555X, V4L2_PIX_FMT_RGB565X, V4L2_PIX_FMT_BGR666, V4L2_PIX_FMT_BGR24, V4L2_PIX_FMT_RGB24, V4L2_PIX_FMT_BGR32, V4L2_PIX_FMT_ABGR32, V4L2_PIX_FMT_XBGR32, V4L2_PIX_FMT_RGB32, V4L2_PIX_FMT_ARGB32, V4L2_PIX_FMT_XRGB32, V4L2_PIX_FMT_GREY, V4L2_PIX_FMT_Y4, V4L2_PIX_FMT_Y6, V4L2_PIX_FMT_Y10, V4L2_PIX_FMT_Y12, V4L2_PIX_FMT_Y16, V4L2_PIX_FMT_Y16_BE, V4L2_PIX_FMT_Y10BPACK, V4L2_PIX_FMT_PAL8, V4L2_PIX_FMT_UV8, V4L2_PIX_FMT_YUYV, V4L2_PIX_FMT_YYUV, V4L2_PIX_FMT_YVYU, V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_VYUY, V4L2_PIX_FMT_Y41P, V4L2_PIX_FMT_YUV444, V4L2_PIX_FMT_YUV555, V4L2_PIX_FMT_YUV565, V4L2_PIX_FMT_YUV32, V4L2_PIX_FMT_HI240, V4L2_PIX_FMT_NV12_16L16, V4L2_PIX_FMT_M420, V4L2_PIX_FMT_NV12, V4L2_PIX_FMT_NV21, V4L2_PIX_FMT_NV16, V4L2_PIX_FMT_NV61, V4L2_PIX_FMT_NV24, V4L2_PIX_FMT_NV42, V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_NV21M, V4L2_PIX_FMT_NV16M, V4L2_PIX_FMT_NV61M, V4L2_PIX_FMT_NV12MT, V4L2_PIX_FMT_NV12MT_16X16, V4L2_PIX_FMT_YUV410, V4L2_PIX_FMT_YVU410, V4L2_PIX_FMT_YUV411P, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_YVU420, V4L2_PIX_FMT_YUV422P, V4L2_PIX_FMT_YUV420M, V4L2_PIX_FMT_YVU420M, V4L2_PIX_FMT_YUV422M, V4L2_PIX_FMT_YVU422M, V4L2_PIX_FMT_YUV444M, V4L2_PIX_FMT_YVU444M, V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SGBRG8, V4L2_PIX_FMT_SGRBG8, V4L2_PIX_FMT_SRGGB8, V4L2_PIX_FMT_SBGGR10, V4L2_PIX_FMT_SGBRG10, V4L2_PIX_FMT_SGRBG10, V4L2_PIX_FMT_SRGGB10, V4L2_PIX_FMT_SBGGR10P, V4L2_PIX_FMT_SGBRG10P, V4L2_PIX_FMT_SGRBG10P, V4L2_PIX_FMT_SRGGB10P, V4L2_PIX_FMT_SBGGR10ALAW8, V4L2_PIX_FMT_SGBRG10ALAW8, V4L2_PIX_FMT_SGRBG10ALAW8, V4L2_PIX_FMT_SRGGB10ALAW8, V4L2_PIX_FMT_SBGGR10DPCM8, V4L2_PIX_FMT_SGBRG10DPCM8, V4L2_PIX_FMT_SGRBG10DPCM8, V4L2_PIX_FMT_SRGGB10DPCM8, V4L2_PIX_FMT_SBGGR12, V4L2_PIX_FMT_SGBRG12, V4L2_PIX_FMT_SGRBG12, V4L2_PIX_FMT_SRGGB12, V4L2_PIX_FMT_SBGGR16, V4L2_PIX_FMT_MJPEG, V4L2_PIX_FMT_JPEG, V4L2_PIX_FMT_DV, V4L2_PIX_FMT_MPEG, V4L2_PIX_FMT_H264, V4L2_PIX_FMT_H264_NO_SC, V4L2_PIX_FMT_H264_MVC, V4L2_PIX_FMT_H263, V4L2_PIX_FMT_MPEG1, V4L2_PIX_FMT_MPEG2, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_XVID, V4L2_PIX_FMT_VC1_ANNEX_G, V4L2_PIX_FMT_VC1_ANNEX_L, V4L2_PIX_FMT_VP8, V4L2_PIX_FMT_VP9, V4L2_PIX_FMT_HEVC, V4L2_PIX_FMT_CPIA1, V4L2_PIX_FMT_WNVA, V4L2_PIX_FMT_SN9C10X, V4L2_PIX_FMT_SN9C20X_I420, V4L2_PIX_FMT_PWC1, V4L2_PIX_FMT_PWC2, V4L2_PIX_FMT_ET61X251, V4L2_PIX_FMT_SPCA501, V4L2_PIX_FMT_SPCA505, V4L2_PIX_FMT_SPCA508, V4L2_PIX_FMT_SPCA561, V4L2_PIX_FMT_PAC207, V4L2_PIX_FMT_MR97310A, V4L2_PIX_FMT_JL2005BCD, V4L2_PIX_FMT_SN9C2028, V4L2_PIX_FMT_SQ905C, V4L2_PIX_FMT_PJPG, V4L2_PIX_FMT_OV511, V4L2_PIX_FMT_OV518, V4L2_PIX_FMT_STV0680, V4L2_PIX_FMT_TM6000, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_PIX_FMT_KONICA420, V4L2_PIX_FMT_JPGL, V4L2_PIX_FMT_SE401, V4L2_PIX_FMT_S5C_UYVY_JPG, V4L2_PIX_FMT_Y8I, V4L2_PIX_FMT_Y12I, V4L2_PIX_FMT_Z16
v4l2_meta_data_formats = V4L2_META_FMT_VSP1_HGO, V4L2_META_FMT_VSP1_HGT, V4L2_META_FMT_UVC, V4L2_META_FMT_D4XX, V4L2_META_FMT_UVC_MSXU_1_5, V4L2_META_FMT_VIVID, V4L2_META_FMT_RK_ISP1_PARAMS, V4L2_META_FMT_RK_ISP1_STAT_3A, V4L2_META_FMT_RK_ISP1_EXT_PARAMS, V4L2_META_FMT_C3ISP_PARAMS, V4L2_META_FMT_C3ISP_STATS, V4L2_META_FMT_RPI_BE_CFG, V4L2_META_FMT_RPI_FE_CFG, V4L2_META_FMT_RPI_FE_STATS, V4L2_META_FMT_MALI_C55_PARAMS, V4L2_META_FMT_MALI_C55_STATS, V4L2_META_FMT_GENERIC_8, V4L2_META_FMT_GENERIC_CSI2_10, V4L2_META_FMT_GENERIC_CSI2_12, V4L2_META_FMT_GENERIC_CSI2_14, V4L2_META_FMT_GENERIC_CSI2_16, V4L2_META_FMT_GENERIC_CSI2_20, V4L2_META_FMT_GENERIC_CSI2_24
v4l2_fmtdesc_flags = V4L2_FMT_FLAG_COMPRESSED, V4L2_FMT_FLAG_EMULATED, V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM, V4L2_FMT_FLAG_DYN_RESOLUTION, V4L2_FMT_FLAG_ENC_CAP_FRAME_INTERVAL, V4L2_FMT_FLAG_CSC_COLORSPACE, V4L2_FMT_FLAG_CSC_XFER_FUNC, V4L2_FMT_FLAG_CSC_YCBCR_ENC, V4L2_FMT_FLAG_CSC_HSV_ENC, V4L2_FMT_FLAG_CSC_QUANTIZATION, V4L2_FMT_FLAG_META_LINE_BASED
v4l2_capability_capabilities = V4L2_CAP_VIDEO_CAPTURE, V4L2_CAP_VIDEO_OUTPUT, V4L2_CAP_VIDEO_OVERLAY, V4L2_CAP_VBI_CAPTURE, V4L2_CAP_VBI_OUTPUT, V4L2_CAP_SLICED_VBI_CAPTURE, V4L2_CAP_SLICED_VBI_OUTPUT, V4L2_CAP_RDS_CAPTURE, V4L2_CAP_VIDEO_OUTPUT_OVERLAY, V4L2_CAP_HW_FREQ_SEEK, V4L2_CAP_RDS_OUTPUT, V4L2_CAP_VIDEO_CAPTURE_MPLANE, V4L2_CAP_VIDEO_OUTPUT_MPLANE, V4L2_CAP_VIDEO_M2M_MPLANE, V4L2_CAP_VIDEO_M2M, V4L2_CAP_TUNER, V4L2_CAP_AUDIO, V4L2_CAP_RADIO, V4L2_CAP_MODULATOR, V4L2_CAP_SDR_CAPTURE, V4L2_CAP_EXT_PIX_FORMAT, V4L2_CAP_SDR_OUTPUT, V4L2_CAP_META_CAPTURE, V4L2_CAP_READWRITE, V4L2_CAP_EDID, V4L2_CAP_STREAMING, V4L2_CAP_META_OUTPUT, V4L2_CAP_TOUCH, V4L2_CAP_IO_MC, V4L2_CAP_DEVICE_CAPS
v4l2_framebuffer_capability = V4L2_FBUF_CAP_EXTERNOVERLAY, V4L2_FBUF_CAP_CHROMAKEY, V4L2_FBUF_CAP_LOCAL_ALPHA, V4L2_FBUF_CAP_GLOBAL_ALPHA, V4L2_FBUF_CAP_LOCAL_INV_ALPHA, V4L2_FBUF_CAP_SRC_CHROMAKEY
v4l2_framebuffer_flags = V4L2_FBUF_FLAG_PRIMARY, V4L2_FBUF_FLAG_OVERLAY, V4L2_FBUF_FLAG_CHROMAKEY, V4L2_FBUF_FLAG_LOCAL_ALPHA, V4L2_FBUF_FLAG_GLOBAL_ALPHA, V4L2_FBUF_FLAG_LOCAL_INV_ALPHA, V4L2_FBUF_FLAG_SRC_CHROMAKEY
v4l2_vbi_format_flags = V4L2_VBI_UNSYNC, V4L2_VBI_INTERLACED, V4L2_VBI_ITU_525_F1_START, V4L2_VBI_ITU_525_F2_START, V4L2_VBI_ITU_625_F1_START, V4L2_VBI_ITU_625_F2_START
v4l2_buffer_flags = V4L2_BUF_FLAG_MAPPED, V4L2_BUF_FLAG_QUEUED, V4L2_BUF_FLAG_DONE, V4L2_BUF_FLAG_KEYFRAME, V4L2_BUF_FLAG_PFRAME, V4L2_BUF_FLAG_BFRAME, V4L2_BUF_FLAG_ERROR, V4L2_BUF_FLAG_IN_REQUEST, V4L2_BUF_FLAG_TIMECODE, V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF, V4L2_BUF_FLAG_PREPARED, V4L2_BUF_FLAG_NO_CACHE_INVALIDATE, V4L2_BUF_FLAG_NO_CACHE_CLEAN, V4L2_BUF_FLAG_TIMESTAMP_MASK, V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN, V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC, V4L2_BUF_FLAG_TIMESTAMP_COPY, V4L2_BUF_FLAG_TSTAMP_SRC_MASK, V4L2_BUF_FLAG_TSTAMP_SRC_EOF, V4L2_BUF_FLAG_TSTAMP_SRC_SOE, V4L2_BUF_FLAG_LAST, V4L2_BUF_FLAG_REQUEST_FD
v4l2_timecode_type = V4L2_TC_TYPE_24FPS, V4L2_TC_TYPE_25FPS, V4L2_TC_TYPE_30FPS, V4L2_TC_TYPE_50FPS, V4L2_TC_TYPE_60FPS
v4l2_timecode_flags = V4L2_TC_FLAG_DROPFRAME, V4L2_TC_FLAG_COLORFRAME, V4L2_TC_USERBITS_field, V4L2_TC_USERBITS_USERDEFINED, V4L2_TC_USERBITS_8BITCHARS
v4l2_captureparm_cap = V4L2_CAP_TIMEPERFRAME
v4l2_captureparm_mode = V4L2_MODE_HIGHQUALITY
v4l2_tuner_capability = V4L2_TUNER_CAP_LOW, V4L2_TUNER_CAP_NORM, V4L2_TUNER_CAP_HWSEEK_BOUNDED, V4L2_TUNER_CAP_HWSEEK_WRAP, V4L2_TUNER_CAP_STEREO, V4L2_TUNER_CAP_LANG2, V4L2_TUNER_CAP_SAP, V4L2_TUNER_CAP_LANG1, V4L2_TUNER_CAP_RDS, V4L2_TUNER_CAP_RDS_BLOCK_IO, V4L2_TUNER_CAP_RDS_CONTROLS, V4L2_TUNER_CAP_FREQ_BANDS, V4L2_TUNER_CAP_HWSEEK_PROG_LIM, V4L2_TUNER_CAP_1HZ
v4l2_tuner_rxsubchans = V4L2_TUNER_SUB_MONO, V4L2_TUNER_SUB_STEREO, V4L2_TUNER_SUB_LANG2, V4L2_TUNER_SUB_SAP, V4L2_TUNER_SUB_LANG1, V4L2_TUNER_SUB_RDS
v4l2_tuner_audmode = V4L2_TUNER_MODE_MONO, V4L2_TUNER_MODE_STEREO, V4L2_TUNER_MODE_LANG2, V4L2_TUNER_MODE_SAP, V4L2_TUNER_MODE_LANG1, V4L2_TUNER_MODE_LANG1_LANG2
v4l2_audio_capability = V4L2_AUDCAP_STEREO, V4L2_AUDCAP_AVL
v4l2_audio_mode = V4L2_AUDMODE_AVL
v4l2_control_flags = V4L2_CTRL_FLAG_DISABLED, V4L2_CTRL_FLAG_GRABBED, V4L2_CTRL_FLAG_READ_ONLY, V4L2_CTRL_FLAG_UPDATE, V4L2_CTRL_FLAG_INACTIVE, V4L2_CTRL_FLAG_SLIDER, V4L2_CTRL_FLAG_WRITE_ONLY, V4L2_CTRL_FLAG_VOLATILE, V4L2_CTRL_FLAG_HAS_PAYLOAD, V4L2_CTRL_FLAG_EXECUTE_ON_WRITE, V4L2_CTRL_FLAG_MODIFY_LAYOUT, V4L2_CTRL_FLAG_DYNAMIC_ARRAY, V4L2_CTRL_FLAG_HAS_WHICH_MIN_MAX, V4L2_CTRL_FLAG_NEXT_CTRL, V4L2_CTRL_FLAG_NEXT_COMPOUND
v4l2_ext_ctrl_class = V4L2_CTRL_CLASS_USER, V4L2_CTRL_CLASS_CODEC, V4L2_CTRL_CLASS_CAMERA, V4L2_CTRL_CLASS_FM_TX, V4L2_CTRL_CLASS_FLASH, V4L2_CTRL_CLASS_JPEG, V4L2_CTRL_CLASS_IMAGE_SOURCE, V4L2_CTRL_CLASS_IMAGE_PROC, V4L2_CTRL_CLASS_DV, V4L2_CTRL_CLASS_FM_RX, V4L2_CTRL_CLASS_RF_TUNER, V4L2_CTRL_CLASS_DETECT, V4L2_CTRL_ID_MASK, V4L2_CTRL_MAX_DIMS, V4L2_CTRL_WHICH_CUR_VAL, V4L2_CTRL_WHICH_DEF_VAL
#Comeback and add others from include/uapi/linux/videodev2.h#1617. Once after syz-extract able to detect with special chars
v4l2_ext_controls = V4L2_CID_USER_CLASS, V4L2_CID_BRIGHTNESS, V4L2_CID_CONTRAST, V4L2_CID_SATURATION, V4L2_CID_HUE, V4L2_CID_AUDIO_VOLUME, V4L2_CID_AUDIO_BALANCE, V4L2_CID_AUDIO_BASS, V4L2_CID_AUDIO_TREBLE, V4L2_CID_AUDIO_MUTE, V4L2_CID_AUDIO_LOUDNESS, V4L2_CID_BLACK_LEVEL, V4L2_CID_AUTO_WHITE_BALANCE, V4L2_CID_DO_WHITE_BALANCE, V4L2_CID_RED_BALANCE, V4L2_CID_BLUE_BALANCE, V4L2_CID_GAMMA, V4L2_CID_EXPOSURE, V4L2_CID_AUTOGAIN, V4L2_CID_GAIN, V4L2_CID_HFLIP, V4L2_CID_VFLIP, V4L2_CID_POWER_LINE_FREQUENCY, V4L2_CID_HUE_AUTO, V4L2_CID_WHITE_BALANCE_TEMPERATURE, V4L2_CID_SHARPNESS, V4L2_CID_BACKLIGHT_COMPENSATION, V4L2_CID_CHROMA_AGC, V4L2_CID_COLOR_KILLER, V4L2_CID_COLORFX, V4L2_CID_AUTOBRIGHTNESS, V4L2_CID_BAND_STOP_FILTER, V4L2_CID_ROTATE, V4L2_CID_BG_COLOR, V4L2_CID_CHROMA_GAIN, V4L2_CID_ILLUMINATORS_1, V4L2_CID_ILLUMINATORS_2, V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, V4L2_CID_ALPHA_COMPONENT, V4L2_CID_COLORFX_CBCR, V4L2_CID_CODEC_CLASS, V4L2_CID_MPEG_STREAM_TYPE, V4L2_CID_MPEG_STREAM_PID_PMT, V4L2_CID_MPEG_STREAM_PID_AUDIO, V4L2_CID_MPEG_STREAM_PID_VIDEO, V4L2_CID_MPEG_STREAM_PID_PCR, V4L2_CID_MPEG_STREAM_PES_ID_AUDIO, V4L2_CID_MPEG_STREAM_PES_ID_VIDEO, V4L2_CID_MPEG_STREAM_VBI_FMT, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, V4L2_CID_MPEG_AUDIO_ENCODING, V4L2_CID_MPEG_AUDIO_L1_BITRATE, V4L2_CID_MPEG_AUDIO_L2_BITRATE, V4L2_CID_MPEG_AUDIO_L3_BITRATE, V4L2_CID_MPEG_AUDIO_MODE, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION, V4L2_CID_MPEG_AUDIO_EMPHASIS, V4L2_CID_MPEG_AUDIO_CRC, V4L2_CID_MPEG_AUDIO_MUTE, V4L2_CID_MPEG_AUDIO_AAC_BITRATE, V4L2_CID_MPEG_AUDIO_AC3_BITRATE, V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK, V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK, V4L2_CID_MPEG_VIDEO_ENCODING, V4L2_CID_MPEG_VIDEO_ASPECT, V4L2_CID_MPEG_VIDEO_B_FRAMES, V4L2_CID_MPEG_VIDEO_GOP_SIZE, V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, V4L2_CID_MPEG_VIDEO_PULLDOWN, V4L2_CID_MPEG_VIDEO_BITRATE_MODE, V4L2_CID_MPEG_VIDEO_BITRATE, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION, V4L2_CID_MPEG_VIDEO_MUTE, V4L2_CID_MPEG_VIDEO_MUTE_YUV, V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE, V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER, V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB, V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE, V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE, V4L2_CID_MPEG_VIDEO_HEADER_MODE, V4L2_CID_MPEG_VIDEO_MAX_REF_PIC, V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP, V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP, V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP, V4L2_CID_MPEG_VIDEO_H263_MIN_QP, V4L2_CID_MPEG_VIDEO_H263_MAX_QP, V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP, V4L2_CID_MPEG_VIDEO_H264_MAX_QP, V4L2_CID_MPEG_VIDEO_H264_MIN_QP, V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM, V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE, V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE, V4L2_CID_MPEG_VIDEO_H264_I_PERIOD, V4L2_CID_MPEG_VIDEO_H264_LEVEL, V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA, V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE, V4L2_CID_MPEG_VIDEO_H264_PROFILE, V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT, V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH, V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE, V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC, V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING, V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0, V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE, V4L2_CID_MPEG_VIDEO_H264_FMO, V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE, V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP, V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION, V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE, V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH, V4L2_CID_MPEG_VIDEO_H264_ASO, V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER, V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING, V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE, V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER, V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP, V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP, V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP, V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP, V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP, V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP, V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL, V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE, V4L2_CID_MPEG_VIDEO_MPEG4_QPEL, V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES, V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB, V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE, V4L2_CID_MPEG_VIDEO_VBV_SIZE, V4L2_CID_MPEG_VIDEO_DEC_PTS, V4L2_CID_MPEG_VIDEO_DEC_FRAME, V4L2_CID_MPEG_VIDEO_VBV_DELAY, V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE, V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE, V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER, V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME, V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS, V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4, V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES, V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL, V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS, V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD, V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL, V4L2_CID_MPEG_VIDEO_VPX_MIN_QP, V4L2_CID_MPEG_VIDEO_VPX_MAX_QP, V4L2_CID_MPEG_VIDEO_VPX_I_FRAME_QP, V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP, V4L2_CID_MPEG_VIDEO_VPX_PROFILE, V4L2_CID_CAMERA_CLASS, V4L2_CID_EXPOSURE_AUTO, V4L2_CID_EXPOSURE_ABSOLUTE, V4L2_CID_EXPOSURE_AUTO_PRIORITY, V4L2_CID_PAN_RELATIVE, V4L2_CID_TILT_RELATIVE, V4L2_CID_PAN_RESET, V4L2_CID_TILT_RESET, V4L2_CID_PAN_ABSOLUTE, V4L2_CID_TILT_ABSOLUTE, V4L2_CID_FOCUS_ABSOLUTE, V4L2_CID_FOCUS_RELATIVE, V4L2_CID_FOCUS_AUTO, V4L2_CID_ZOOM_ABSOLUTE, V4L2_CID_ZOOM_RELATIVE, V4L2_CID_ZOOM_CONTINUOUS, V4L2_CID_PRIVACY, V4L2_CID_IRIS_ABSOLUTE, V4L2_CID_IRIS_RELATIVE, V4L2_CID_AUTO_EXPOSURE_BIAS, V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE, V4L2_CID_WIDE_DYNAMIC_RANGE, V4L2_CID_IMAGE_STABILIZATION, V4L2_CID_ISO_SENSITIVITY, V4L2_CID_ISO_SENSITIVITY_AUTO, V4L2_CID_EXPOSURE_METERING, V4L2_CID_SCENE_MODE, V4L2_CID_3A_LOCK, V4L2_CID_AUTO_FOCUS_START, V4L2_CID_AUTO_FOCUS_STOP, V4L2_CID_AUTO_FOCUS_STATUS, V4L2_CID_AUTO_FOCUS_RANGE, V4L2_CID_PAN_SPEED, V4L2_CID_TILT_SPEED, V4L2_CID_FM_TX_CLASS, V4L2_CID_RDS_TX_DEVIATION, V4L2_CID_RDS_TX_PI, V4L2_CID_RDS_TX_PTY, V4L2_CID_RDS_TX_PS_NAME, V4L2_CID_RDS_TX_RADIO_TEXT, V4L2_CID_RDS_TX_MONO_STEREO, V4L2_CID_RDS_TX_ARTIFICIAL_HEAD, V4L2_CID_RDS_TX_COMPRESSED, V4L2_CID_RDS_TX_DYNAMIC_PTY, V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT, V4L2_CID_RDS_TX_TRAFFIC_PROGRAM, V4L2_CID_RDS_TX_MUSIC_SPEECH, V4L2_CID_RDS_TX_ALT_FREQS_ENABLE, V4L2_CID_RDS_TX_ALT_FREQS, V4L2_CID_AUDIO_LIMITER_ENABLED, V4L2_CID_AUDIO_LIMITER_RELEASE_TIME, V4L2_CID_AUDIO_LIMITER_DEVIATION, V4L2_CID_AUDIO_COMPRESSION_ENABLED, V4L2_CID_AUDIO_COMPRESSION_GAIN, V4L2_CID_AUDIO_COMPRESSION_THRESHOLD, V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME, V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME, V4L2_CID_PILOT_TONE_ENABLED, V4L2_CID_PILOT_TONE_DEVIATION, V4L2_CID_PILOT_TONE_FREQUENCY, V4L2_CID_TUNE_PREEMPHASIS, V4L2_CID_TUNE_POWER_LEVEL, V4L2_CID_TUNE_ANTENNA_CAPACITOR, V4L2_CID_FLASH_CLASS, V4L2_CID_FLASH_LED_MODE, V4L2_CID_FLASH_STROBE_SOURCE, V4L2_CID_FLASH_STROBE, V4L2_CID_FLASH_STROBE_STOP, V4L2_CID_FLASH_STROBE_STATUS, V4L2_CID_FLASH_TIMEOUT, V4L2_CID_FLASH_INTENSITY, V4L2_CID_FLASH_TORCH_INTENSITY, V4L2_CID_FLASH_INDICATOR_INTENSITY, V4L2_CID_FLASH_FAULT, V4L2_CID_FLASH_CHARGE, V4L2_CID_FLASH_READY, V4L2_CID_JPEG_CLASS, V4L2_CID_JPEG_CHROMA_SUBSAMPLING, V4L2_CID_JPEG_RESTART_INTERVAL, V4L2_CID_JPEG_COMPRESSION_QUALITY, V4L2_CID_JPEG_ACTIVE_MARKER, V4L2_CID_IMAGE_SOURCE_CLASS, V4L2_CID_VBLANK, V4L2_CID_HBLANK, V4L2_CID_ANALOGUE_GAIN, V4L2_CID_TEST_PATTERN_RED, V4L2_CID_TEST_PATTERN_GREENR, V4L2_CID_TEST_PATTERN_BLUE, V4L2_CID_TEST_PATTERN_GREENB, V4L2_CID_IMAGE_PROC_CLASS, V4L2_CID_LINK_FREQ, V4L2_CID_PIXEL_RATE, V4L2_CID_TEST_PATTERN, V4L2_CID_DV_CLASS, V4L2_CID_DV_TX_HOTPLUG, V4L2_CID_DV_TX_RXSENSE, V4L2_CID_DV_TX_EDID_PRESENT, V4L2_CID_DV_TX_MODE, V4L2_CID_DV_TX_RGB_RANGE, V4L2_CID_DV_TX_IT_CONTENT_TYPE, V4L2_CID_DV_RX_POWER_PRESENT, V4L2_CID_DV_RX_RGB_RANGE, V4L2_CID_DV_RX_IT_CONTENT_TYPE, V4L2_CID_FM_RX_CLASS, V4L2_CID_TUNE_DEEMPHASIS, V4L2_CID_RDS_RECEPTION, V4L2_CID_RF_TUNER_CLASS, V4L2_CID_RF_TUNER_RF_GAIN, V4L2_CID_RF_TUNER_LNA_GAIN_AUTO, V4L2_CID_RF_TUNER_LNA_GAIN, V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO, V4L2_CID_RF_TUNER_MIXER_GAIN, V4L2_CID_RF_TUNER_IF_GAIN_AUTO, V4L2_CID_RF_TUNER_IF_GAIN, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, V4L2_CID_RF_TUNER_BANDWIDTH, V4L2_CID_RF_TUNER_PLL_LOCK, V4L2_CID_RDS_RX_PTY, V4L2_CID_RDS_RX_PS_NAME, V4L2_CID_RDS_RX_RADIO_TEXT, V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT, V4L2_CID_RDS_RX_TRAFFIC_PROGRAM, V4L2_CID_RDS_RX_MUSIC_SPEECH, V4L2_CID_DETECT_CLASS, V4L2_CID_DETECT_MD_MODE, V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD, V4L2_CID_DETECT_MD_THRESHOLD_GRID, V4L2_CID_DETECT_MD_REGION_GRID
v4l2_frmsizetypes = V4L2_FRMSIZE_TYPE_DISCRETE, V4L2_FRMSIZE_TYPE_CONTINUOUS, V4L2_FRMSIZE_TYPE_STEPWISE
v4l2_frmivaltypes = V4L2_FRMIVAL_TYPE_DISCRETE, V4L2_FRMIVAL_TYPE_CONTINUOUS, V4L2_FRMIVAL_TYPE_STEPWISE
v4l2_enc_idx_flags = V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_P, V4L2_ENC_IDX_FRAME_B, V4L2_ENC_IDX_FRAME_MASK
v4l2_dbg_match_type = V4L2_CHIP_MATCH_BRIDGE, V4L2_CHIP_MATCH_SUBDEV, V4L2_CHIP_MATCH_I2C_DRIVER, V4L2_CHIP_MATCH_I2C_ADDR, V4L2_CHIP_MATCH_AC97
v4l2_frequency_band_modulation = V4L2_BAND_MODULATION_VSB, V4L2_BAND_MODULATION_FM, V4L2_BAND_MODULATION_AM
v4l2_dv_timings_type = V4L2_DV_BT_656_1120
v4l2_bt_timings_interlaced = V4L2_DV_PROGRESSIVE, V4L2_DV_INTERLACED
v4l2_bt_timings_polarities = V4L2_DV_VSYNC_POS_POL, V4L2_DV_HSYNC_POS_POL
v4l2_bt_timings_standards = V4L2_DV_BT_STD_CEA861, V4L2_DV_BT_STD_DMT, V4L2_DV_BT_STD_CVT, V4L2_DV_BT_STD_GTF, V4L2_DV_BT_STD_SDI
v4l2_bt_timings_flags = V4L2_DV_FL_REDUCED_BLANKING, V4L2_DV_FL_CAN_REDUCE_FPS, V4L2_DV_FL_REDUCED_FPS, V4L2_DV_FL_HALF_LINE, V4L2_DV_FL_IS_CE_VIDEO, V4L2_DV_FL_FIRST_FIELD_EXTRA_LINE
v4l2_encoder_cmd_cmd = V4L2_ENC_CMD_START, V4L2_ENC_CMD_STOP, V4L2_ENC_CMD_PAUSE, V4L2_ENC_CMD_RESUME
v4l2_encoder_flags = V4L2_ENC_CMD_STOP_AT_GOP_END
v4l2_decoder_cmd_cmd = V4L2_DEC_CMD_START, V4L2_DEC_CMD_STOP, V4L2_DEC_CMD_PAUSE, V4L2_DEC_CMD_RESUME
v4l2_decoder_cmd_flags = V4L2_DEC_CMD_START_MUTE_AUDIO, V4L2_DEC_CMD_PAUSE_TO_BLACK, V4L2_DEC_CMD_STOP_TO_BLACK, V4L2_DEC_CMD_STOP_IMMEDIATELY
v4l2_decoder_cmd_format = V4L2_DEC_START_FMT_NONE, V4L2_DEC_START_FMT_GOP
v4l2_event_src_changes = V4L2_EVENT_SRC_CH_RESOLUTION
v4l2_event_type = V4L2_EVENT_ALL, V4L2_EVENT_VSYNC, V4L2_EVENT_EOS, V4L2_EVENT_CTRL, V4L2_EVENT_FRAME_SYNC, V4L2_EVENT_SOURCE_CHANGE, V4L2_EVENT_MOTION_DET, V4L2_EVENT_PRIVATE_START
v4l2_event_ctrl_changes = V4L2_EVENT_CTRL_CH_VALUE, V4L2_EVENT_CTRL_CH_FLAGS, V4L2_EVENT_CTRL_CH_RANGE
v4l2_event_motion_det_flags = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ
v4l2_event_subscription_flags = V4L2_EVENT_SUB_FL_SEND_INITIAL, V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK
v4l2_selection_target = V4L2_SEL_TGT_CROP, V4L2_SEL_TGT_CROP_DEFAULT, V4L2_SEL_TGT_CROP_BOUNDS, V4L2_SEL_TGT_NATIVE_SIZE, V4L2_SEL_TGT_COMPOSE, V4L2_SEL_TGT_COMPOSE_DEFAULT, V4L2_SEL_TGT_COMPOSE_BOUNDS, V4L2_SEL_TGT_COMPOSE_PADDED
v4l2_selection_flags = V4L2_SEL_FLAG_GE, V4L2_SEL_FLAG_LE, V4L2_SEL_FLAG_KEEP_CONFIG
v4l2_bt_timings_cap_capabilities = V4L2_DV_BT_CAP_INTERLACED, V4L2_DV_BT_CAP_PROGRESSIVE, V4L2_DV_BT_CAP_REDUCED_BLANKING, V4L2_DV_BT_CAP_CUSTOM
v4l2_dbg_chip_info_flags = V4L2_CHIP_FL_READABLE, V4L2_CHIP_FL_WRITABLE
v4l2_std_id = V4L2_STD_PAL_B, V4L2_STD_PAL_B1, V4L2_STD_PAL_G, V4L2_STD_PAL_H, V4L2_STD_PAL_I, V4L2_STD_PAL_D, V4L2_STD_PAL_D1, V4L2_STD_PAL_K, V4L2_STD_PAL_M, V4L2_STD_PAL_N, V4L2_STD_PAL_Nc, V4L2_STD_PAL_60, V4L2_STD_NTSC_M, V4L2_STD_NTSC_M_JP, V4L2_STD_NTSC_443, V4L2_STD_NTSC_M_KR, V4L2_STD_SECAM_B, V4L2_STD_SECAM_D, V4L2_STD_SECAM_G, V4L2_STD_SECAM_H, V4L2_STD_SECAM_K, V4L2_STD_SECAM_K1, V4L2_STD_SECAM_L, V4L2_STD_SECAM_LC, V4L2_STD_ATSC_8_VSB, V4L2_STD_ATSC_16_VSB, V4L2_STD_NTSC, V4L2_STD_SECAM_DK, V4L2_STD_SECAM, V4L2_STD_PAL_BG, V4L2_STD_PAL_DK, V4L2_STD_PAL, V4L2_STD_B, V4L2_STD_G, V4L2_STD_H, V4L2_STD_L, V4L2_STD_GH, V4L2_STD_DK, V4L2_STD_BG, V4L2_STD_MN, V4L2_STD_MTS, V4L2_STD_525_60, V4L2_STD_625_50, V4L2_STD_ATSC, V4L2_STD_UNKNOWN, V4L2_STD_ALL
v4l2_input_status = V4L2_IN_ST_NO_POWER, V4L2_IN_ST_NO_SIGNAL, V4L2_IN_ST_NO_COLOR, V4L2_IN_ST_HFLIP, V4L2_IN_ST_VFLIP, V4L2_IN_ST_NO_H_LOCK, V4L2_IN_ST_COLOR_KILL, V4L2_IN_ST_NO_V_LOCK, V4L2_IN_ST_NO_STD_LOCK, V4L2_IN_ST_NO_SYNC, V4L2_IN_ST_NO_EQU, V4L2_IN_ST_NO_CARRIER, V4L2_IN_ST_MACROVISION, V4L2_IN_ST_NO_ACCESS, V4L2_IN_ST_VTR
v4l2_input_type = V4L2_INPUT_TYPE_TUNER, V4L2_INPUT_TYPE_CAMERA, V4L2_INPUT_TYPE_TOUCH
v4l2_input_capabilities = V4L2_IN_CAP_DV_TIMINGS, V4L2_IN_CAP_CUSTOM_TIMINGS, V4L2_IN_CAP_STD, V4L2_IN_CAP_NATIVE_SIZE
v4l2_output_type = V4L2_OUTPUT_TYPE_MODULATOR, V4L2_OUTPUT_TYPE_ANALOG, V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY
v4l2_output_capabilities = V4L2_OUT_CAP_DV_TIMINGS, V4L2_OUT_CAP_CUSTOM_TIMINGS, V4L2_OUT_CAP_STD, V4L2_OUT_CAP_NATIVE_SIZE
v4l2_query_ext_ctrl = V4L2_CTRL_FLAG_NEXT_CTRL, V4L2_CTRL_FLAG_NEXT_COMPOUND

# These are actually defined in the newer kernel versions.
# But the newer kernel versions don't build with make extract.
# This can be removed once we can regenerate consts on at least v6.19-rc3.
define V4L2_META_FMT_MALI_C55_PARAMS	1345664323
define V4L2_META_FMT_MALI_C55_STATS	1395995971
]

185/2 2026/07/30 12:38 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 50795
							output: 475
							thoughts: 280
						

Thoughts:
**Understanding Syzkaller's Device Open Functions**

Okay, so I'm looking at this `syz_open_dev$video` function call and I'm seeing a device string like `/dev/video#` and it's throwing a `bad string value` error, specifically expecting `/dev/video#\x00`. Right, right. That means the string *must* be exactly `"/dev/video#\x00"`, the null-terminated version. And Syzkaller is going to replace the `#` with the `id` argument. Hmm, okay, so looking at the function signature again: `syz_open_dev$video(dev ptr[in, string["/dev/video#"]], id intptr, flags flags[open_flags]) fd_video`. The `id` is an `intptr`. Got it.

So, for this `syz_open_dev$video` call, I need to provide `"/dev/video#\x00"` as the device string and I should pass `0` for the `id`.

Thinking ahead, the same principle applies to other similar functions. I look at `syz_open_dev$I2C`: `syz_open_dev$I2C(dev ptr[in, string["/dev/i2c-#"]], id intptr, flags flags[open_flags]) fd_i2c`.  Yep, clearly, I should use `"/dev/i2c-#\x00"` and `0` for the `id` there as well. The pattern is clear now.



186/2 2026/07/30 12:38 tool reproduce-crash
2m Args:
map[ReproSyz:r0 = syz_usb_connect$hid(3, 0, &AUTO, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r4 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r3, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r4, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID:repro/396707d321d3e0ce83a74314715d5b162d86ae82 ReproducedBugTitle: ReproducedCrashReport:]

187/2 2026/07/30 12:40 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 51971
							output: 60
							thoughts: 11
						

Thoughts:
Okay, here's my take on those thoughts, tailored for an expert audience:

**Analyzing the Stability and Scope**

No crash. Good. That's the baseline we were aiming for. Now, let's drill down into the coverage. What specifically is meant here? Are we talking about test coverage, error handling coverage, or perhaps even performance envelope coverage? I need to understand the intent to interpret the following statement effectively. Let's see what's being looked at here.



188/2 2026/07/30 12:41 tool get-coverage-files
0m Args:
map[ExecutionCachedID:repro/396707d321d3e0ce83a74314715d5b162d86ae82]

Results:
map[Files:[arch/x86/entry/vsyscall/vsyscall_64.c arch/x86/include/asm/atomic64_64.h arch/x86/include/asm/bitops.h arch/x86/include/asm/compat.h arch/x86/include/asm/cpufeature.h arch/x86/include/asm/irqflags.h arch/x86/include/asm/jump_label.h arch/x86/include/asm/mmu_context.h arch/x86/include/asm/page.h arch/x86/include/asm/pgtable.h arch/x86/include/asm/pkru.h arch/x86/include/asm/preempt.h arch/x86/include/asm/trace/fpu.h arch/x86/kernel/cpu/aperfmperf.c arch/x86/kernel/fpu/context.h arch/x86/kernel/fpu/core.c arch/x86/kernel/fpu/internal.h arch/x86/kernel/fpu/xstate.c arch/x86/kernel/tsc.c arch/x86/mm/fault.c arch/x86/mm/maccess.c arch/x86/mm/pgtable.c arch/x86/pci/common.c arch/x86/pci/direct.c block/blk-cgroup.c drivers/acpi/acpica/nsaccess.c drivers/acpi/acpica/nsdump.c drivers/acpi/acpica/nssearch.c drivers/acpi/acpica/nsutils.c drivers/acpi/acpica/nsxfname.c drivers/acpi/acpica/utascii.c drivers/acpi/acpica/utdebug.c drivers/acpi/acpica/utmutex.c drivers/acpi/acpica/utstring.c drivers/acpi/device_pm.c drivers/acpi/osl.c drivers/acpi/property.c drivers/acpi/utils.c drivers/base/core.c drivers/base/map.c drivers/base/power/qos.c drivers/base/power/runtime.c drivers/base/power/wakeirq.c drivers/char/misc.c drivers/i2c/busses/i2c-i801.c drivers/i2c/i2c-core-base.c drivers/i2c/i2c-core-smbus.c drivers/i2c/i2c-core.h drivers/i2c/i2c-dev.c drivers/media/common/videobuf2/videobuf2-core.c drivers/media/common/videobuf2/videobuf2-v4l2.c drivers/media/mc/mc-request.c drivers/media/test-drivers/vicodec/codec-v4l2-fwht.c drivers/media/test-drivers/vicodec/vicodec-core.c drivers/media/v4l2-core/v4l2-ctrls-core.c drivers/media/v4l2-core/v4l2-ctrls-defs.c drivers/media/v4l2-core/v4l2-ctrls-request.c drivers/media/v4l2-core/v4l2-dev.c drivers/media/v4l2-core/v4l2-fh.c drivers/media/v4l2-core/v4l2-mem2mem.c drivers/pci/access.c drivers/pci/ats.c drivers/pci/host-bridge.c drivers/pci/iov.c drivers/pci/msi/api.c drivers/pci/msi/msi.c drivers/pci/pci-acpi.c drivers/pci/pci-driver.c drivers/pci/pci.c drivers/pci/pcie/aer.c drivers/pci/pcie/aspm.c drivers/pci/quirks.c drivers/pci/rebar.c drivers/pci/vc.c drivers/usb/gadget/legacy/raw_gadget.c fs/char_dev.c fs/d_path.c fs/dcache.c fs/file.c fs/file_table.c fs/ioctl.c fs/libfs.c fs/mnt_idmapping.c fs/namei.c fs/namespace.c fs/notify/fsnotify.c fs/open.c include/acpi/acpi_bus.h include/asm-generic/bitops/instrumented-non-atomic.h include/linux/atomic/atomic-arch-fallback.h include/linux/atomic/atomic-instrumented.h include/linux/atomic/atomic-long.h include/linux/audit.h include/linux/bit_spinlock.h include/linux/cgroup.h include/linux/clockchips.h include/linux/cpumask.h include/linux/cred.h include/linux/dcache.h include/linux/delayed_call.h include/linux/device.h include/linux/device_cgroup.h include/linux/err.h include/linux/file.h include/linux/file_ref.h include/linux/filelock.h include/linux/find.h include/linux/folio_batch.h include/linux/fortify-string.h include/linux/fs.h include/linux/fs/super.h include/linux/fsnotify.h include/linux/fsnotify_backend.h include/linux/hrtimer.h include/linux/instrumented.h include/linux/jiffies.h include/linux/jump_label.h include/linux/kernel.h include/linux/kref.h include/linux/list.h include/linux/list_bl.h include/linux/llist.h include/linux/log2.h include/linux/lsm_hook_defs.h include/linux/maple_tree.h include/linux/memcontrol.h include/linux/mempolicy.h include/linux/mm.h include/linux/mmzone.h include/linux/mount.h include/linux/nodemask.h include/linux/page-flags.h include/linux/page_ext.h include/linux/page_ref.h include/linux/pagemap.h include/linux/perf_event.h include/linux/pgtable.h include/linux/pid.h include/linux/pm_qos.h include/linux/preempt.h include/linux/rbtree.h include/linux/rbtree_latch.h include/linux/rculist_bl.h include/linux/rcupdate.h include/linux/refcount.h include/linux/rmap.h include/linux/rtmutex.h include/linux/sched.h include/linux/sched/isolation.h include/linux/seqlock.h include/linux/spinlock_rt.h include/linux/srcu.h include/linux/swap.h include/linux/thread_info.h include/linux/uaccess.h include/linux/ucopysize.h include/linux/userfaultfd_k.h include/linux/workqueue.h include/linux/xarray.h include/trace/events/exceptions.h include/trace/events/filemap.h include/trace/events/kmem.h include/trace/events/rpm.h include/trace/events/smbus.h include/trace/events/timer.h kernel/bpf/core.c kernel/cgroup/rstat.c kernel/kthread.c kernel/pid.c kernel/printk/printk_safe.c kernel/time/clockevents.c kernel/time/hrtimer.c kernel/time/posix-timers.c kernel/time/tick-oneshot.c kernel/time/tick-sched.c kernel/time/time.c kernel/time/timekeeping.c lib/cpumask.c lib/errseq.c lib/idr.c lib/iomap.c lib/kobject.c lib/lockref.c lib/maple_tree.c lib/percpu_counter.c lib/plist.c lib/radix-tree.c lib/strncpy_from_user.c lib/timerqueue.c lib/usercopy.c lib/vsprintf.c lib/xarray.c mm/backing-dev.c mm/fail_page_alloc.c mm/filemap.c mm/internal.h mm/list_lru.c mm/maccess.c mm/memory.c mm/mempolicy.c mm/mmap_lock.c mm/page_counter.c mm/page_ext.c mm/page_owner.c mm/page_table_check.c mm/pgtable-generic.c mm/readahead.c mm/rmap.c mm/swap.c mm/swapfile.c security/device_cgroup.c security/integrity/ima/ima_main.c security/landlock/cred.h security/landlock/fs.c security/landlock/ruleset.c security/security.c security/smack/smack_access.c security/smack/smack_lsm.c security/tomoyo/audit.c security/tomoyo/common.c security/tomoyo/common.h security/tomoyo/domain.c security/tomoyo/file.c security/tomoyo/realpath.c security/tomoyo/tomoyo.c security/tomoyo/util.c usercopy_64.c]]

189/2 2026/07/30 12:41 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 55049
							output: 19
							thoughts: 245
						

Thoughts:
**USB Device Matching and Syzkaller Configuration**

Okay, so I've been digging through the syzkaller coverage, and I see that the `raw_gadget.c` driver is covered. Good, good. But I'm missing something... the coverage doesn't seem to include the `si4713`, `au0828`, or `go7007` drivers! That's a red flag.

Right, I remember now. I was using `syz_usb_connect$hid(3, 0, &AUTO, 0)` to connect a HID device. That explains the lack of coverage for those other drivers. That function is specifically tailored for HID devices, and I need to connect something that corresponds to one of those other device types. Those are radio and video drivers, not HID.

So, how does syzkaller handle USB device matching? It must be by vendor and product IDs, I'd guess. Ah, that's it! When I use `syz_usb_connect$hid`, syzkaller automatically tweaks the vendor/product IDs to align with some known HID driver. Makes perfect sense.

I need to use the more generic `syz_usb_connect` function and provide the correct vendor and product IDs for my target device. Let me check the documentation.

Okay, let's see... `syz_usb_connect` takes `speed`, `dev_len`, `dev`, `cb_len`, and `cb` as arguments. Now to find the right vendor and product IDs... I'll check `vusb.txt`.



190/2 2026/07/30 12:41 tool read-description
0m Args:
map[File:vusb.txt]

Results:
map[Output:# Copyright 2019 syzkaller project authors. All rights reserved.
# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

include <linux/types.h>
include <linux/byteorder/generic.h>

include <uapi/linux/usb/ch9.h>
include <uapi/linux/usb/ch11.h>

include <uapi/linux/usb/midi.h>
include <uapi/linux/usb/audio.h>
include <linux/usb/audio-v2.h>
include <linux/usb/audio-v3.h>
include <uapi/linux/hid.h>
include <linux/hid.h>
include <uapi/linux/usb/cdc.h>
include <uapi/linux/if_ether.h>
include <linux/interrupt.h>
include <linux/usb/cdc_ncm.h>
include <drivers/net/usb/asix.h>

# This is a special fd for USB fuzzing and should only be used with syz_usb_* pseudo-syscalls.
# We don't inherit it from the fd resource, to discourage syzkaller calling raw ioctls on it.
resource fd_usb[int32]: -1

# These are generic pseudo-syscalls for emulating arbitrary USB devices.
# They are mostly targeted to cover the enumeration process.
syz_usb_connect(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io(fd fd_usb, descs ptr[in, vusb_descriptors], resps ptr[in, vusb_responses]) (timeout[300], remote_cover)
syz_usb_ep_write(fd fd_usb, ep int8, len len[data], data ptr[in, array[int8, 0:256]]) (timeout[300], remote_cover)
syz_usb_ep_read(fd fd_usb, ep int8, len len[data], data buffer[out]) (timeout[300], remote_cover)
syz_usb_disconnect(fd fd_usb) (timeout[300], remote_cover)

usb_device_speed = USB_SPEED_UNKNOWN, USB_SPEED_LOW, USB_SPEED_FULL, USB_SPEED_HIGH, USB_SPEED_WIRELESS, USB_SPEED_SUPER, USB_SPEED_SUPER_PLUS

# TODO: consider patching idVendor and idProduct for all class specific descriptions in Go code to cover more drivers.
# TODO: custom syz_usb_ep_write() descriptions for all class specific descriptions.
# TODO: consider adding custom vusb_connect_descriptors definitions to all class specific descriptions.

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

type usb_device_descriptor_verbose_t[USB, CLASS, SUBCLASS, PROTOCOL, PACKET, VENDOR, PRODUCT, DEVICE, CFS] {
	bLength			const[USB_DT_DEVICE_SIZE, int8]
	bDescriptorType		const[USB_DT_DEVICE, int8]

	bcdUSB			USB
	bDeviceClass		const[CLASS, int8]
	bDeviceSubClass		const[SUBCLASS, int8]
	bDeviceProtocol		const[PROTOCOL, int8]
	bMaxPacketSize0		PACKET
	idVendor		const[VENDOR, int16]
	idProduct		const[PRODUCT, int16]
	bcdDevice		const[DEVICE, int16]
	iManufacturer		const[1, int8]
	iProduct		const[2, int8]
	iSerialNumber		const[3, int8]
	bNumConfigurations	len[configs, int8]

	configs			CFS
} [packed]

type usb_device_descriptor_t[CLASS, SUBCLASS, PROTOCOL, VENDOR, PRODUCT, DEVICE, CFS] usb_device_descriptor_verbose_t[flags[usb_versions, int16], CLASS, SUBCLASS, PROTOCOL, flags[usb_device_max_packet_sizes, int8], VENDOR, PRODUCT, DEVICE, CFS]
type usb_device_descriptor_fixed_t[USB, CLASS, SUBCLASS, PROTOCOL, PACKET, VENDOR, PRODUCT, DEVICE, CFS] usb_device_descriptor_verbose_t[const[USB, int16], CLASS, SUBCLASS, PROTOCOL, const[PACKET, int8], VENDOR, PRODUCT, DEVICE, CFS]

usb_versions = 0x110, 0x200, 0x201, 0x250, 0x300, 0x310

# https://elixir.bootlin.com/linux/v5.1.7/source/drivers/usb/core/hub.c#L4661
usb_device_max_packet_sizes = 8, 16, 32, 64, 255

type usb_config_descriptor_verbose_t[NUM, IFSNUM, ICONFIG, ATTRS, POWER, EXTRA, IFS] {
	bLength			const[USB_DT_CONFIG_SIZE, int8]
	bDescriptorType		const[USB_DT_CONFIG, int8]

	wTotalLength		len[parent, int16]
	bNumInterfaces		IFSNUM
	bConfigurationValue	NUM
	iConfiguration		ICONFIG
	bmAttributes		ATTRS
	bMaxPower		POWER

	extra			EXTRA
	interfaces		IFS
} [packed]

type usb_config_descriptor_t[NUM, IFSNUM, IFS] usb_config_descriptor_verbose_t[NUM, IFSNUM, int8, flags[usb_config_attributes, int8], int8, void, IFS]
type usb_config_descriptor_ifaces_array_t[NUM, IFS] usb_config_descriptor_t[NUM, len[interfaces, int8], IFS]
type usb_config_descriptor_fixed_t[NUM, IFSNUM, ATTRS, POWER, IFS] usb_config_descriptor_verbose_t[const[NUM, int8], const[IFSNUM, int8], const[0, int8], const[ATTRS, int8], const[POWER, int8], void, IFS]
type usb_config_descriptor_extra_t[NUM, IFSNUM, EXTRA, IFS] usb_config_descriptor_verbose_t[NUM, IFSNUM, int8, flags[usb_config_attributes, int8], int8, EXTRA, IFS]

type usb_interface_descriptor_verbose_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, IIF, EXTRA, EPS] {
	bLength			const[USB_DT_INTERFACE_SIZE, int8]
	bDescriptorType		const[USB_DT_INTERFACE, int8]

	bInterfaceNumber	IFNUM
	bAlternateSetting	ALTNUM
	bNumEndpoints		EPSNUM
	bInterfaceClass		CLASS
	bInterfaceSubClass	SUBCLASS
	bInterfaceProtocol	PROTOCOL
	iInterface		IIF

	extra			EXTRA
	endpoints		EPS
} [packed]

type usb_interface_descriptor_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS] usb_interface_descriptor_verbose_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, int8, EXTRA, EPS]
type usb_interface_descriptor_eps_array_t[IFNUM, ALTNUM, CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS] usb_interface_descriptor_t[IFNUM, ALTNUM, len[endpoints, int8], CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS]
type usb_interface_descriptor_fixed_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS] usb_interface_descriptor_verbose_t[const[IFNUM, int8], const[ALTNUM, int8], const[EPSNUM, int8], const[CLASS, int8], const[SUBCLASS, int8], const[PROTOCOL, int8], const[0, int8], EXTRA, EPS]

# TODO: non-audio endpoints have USB_DT_ENDPOINT_SIZE.
type usb_endpoint_descriptor_verbose_t[ADDR, ATTRS, PACKET, INTERVAL, REFRESH, SYNCH, EXTRA] {
	bLength			const[USB_DT_ENDPOINT_AUDIO_SIZE, int8]
	bDescriptorType		const[USB_DT_ENDPOINT, int8]

	bEndpointAddress	ADDR
	bmAttributes		ATTRS
	wMaxPacketSize		PACKET
	bInterval		INTERVAL

	bRefresh		REFRESH
	bSynchAddress		SYNCH

	extra			EXTRA
} [packed]

type usb_endpoint_descriptor_t[ADDR, ATTRS, EXTRA] usb_endpoint_descriptor_verbose_t[ADDR, ATTRS, flags[usb_endpoint_max_packet_sizes, int16], int8, int8, int8, EXTRA]
type usb_endpoint_descriptor_fixed_t[ADDR, ATTRS, PACKET, INTERVAL, EXTRA] usb_endpoint_descriptor_verbose_t[const[ADDR, int8], const[ATTRS, int8], const[PACKET, int16], const[INTERVAL, int8], const[0, int8], const[0, int8], EXTRA]

# TODO: dummy driver has complex requirements for packet sizes, account for those:
# https://elixir.bootlin.com/linux/v5.3.6/source/drivers/usb/gadget/udc/dummy_hcd.c#L497
usb_endpoint_max_packet_sizes = 8, 16, 32, 64, 512, 1023, 1024

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Generic USB device, configuration, interface and endpoint descriptors.

# We only support one configuration per device.
# bDeviceClass, bDeviceSubClass, bDeviceProtocol, idVendor, idProduct
# and bcdDevice are patched by Go code, see sys/linux/init_vusb.go.
usb_device_descriptor {
	inner	usb_device_descriptor_t[0, 0, 0, 0, 0, 0, array[usb_config_descriptor, 1]]
} [packed]

usb_config_descriptor {
	inner	usb_config_descriptor_ifaces_array_t[int8, array[usb_interface_descriptor, 1:4]]
} [packed]

usb_config_attributes = USB_CONFIG_ATT_ONE, USB_CONFIG_ATT_SELFPOWER, USB_CONFIG_ATT_WAKEUP, USB_CONFIG_ATT_BATTERY

# bInterfaceNumber, bInterfaceClass, bInterfaceSubClass and bInterfaceProtocol
# are patched by Go code, see sys/linux/init_vusb.go.
usb_interface_descriptor {
	inner	usb_interface_descriptor_eps_array_t[int8, int8, const[0, int8], const[0, int8], const[0, int8], array[usb_interface_extra_descriptor, 0:2], array[usb_endpoint_descriptor, 0:16]]
} [packed]

usb_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], flags[usb_endpoint_attributes, int8], array[usb_endpoint_extra_descriptor, 0:2]]
} [packed]

usb_endpoint_addresses = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, USB_DIR_OUT, USB_DIR_IN

usb_endpoint_attributes = USB_ENDPOINT_XFER_CONTROL, USB_ENDPOINT_XFER_ISOC, USB_ENDPOINT_XFER_BULK, USB_ENDPOINT_XFER_INT, USB_ENDPOINT_INTR_PERIODIC, USB_ENDPOINT_INTR_NOTIFICATION, USB_ENDPOINT_SYNC_NONE, USB_ENDPOINT_SYNC_ASYNC, USB_ENDPOINT_SYNC_ADAPTIVE, USB_ENDPOINT_SYNC_SYNC, USB_ENDPOINT_USAGE_DATA, USB_ENDPOINT_USAGE_FEEDBACK, USB_ENDPOINT_USAGE_FEEDBACK

vusb_connect_descriptors {
	qual_len	len[qual, int32]
	qual		ptr[in, usb_qualifier_descriptor]
	bos_len		len[bos, int32]
	bos		ptr[in, usb_bos_descriptor]
	strs_len	len[strs, int32]
	strs		array[vusb_connect_string_descriptor]
} [packed]

vusb_connect_string_descriptor {
	len	len[str, int32]
	str	ptr[in, usb_string_descriptor]
} [packed]

vusb_descriptors {
	len	len[parent, int32]
	generic	ptr[in, vusb_descriptor_generic]

	string	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
	bos	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_BOS, usb_bos_descriptor]]

	hub_hs	ptr[in, vusb_descriptor_t[USB_TYPE_CLASS, USB_DT_HUB, usb_hub_descriptor_hs]]
	hub_ss	ptr[in, vusb_descriptor_t[USB_TYPE_CLASS, USB_DT_SS_HUB, usb_hub_descriptor_ss]]
} [packed]

vusb_descriptor_generic {
	req_type	flags[usb_request_types, int8]
	desc_type	flags[usb_descriptor_types, int8]
	len		bytesize[data, int32]
	data		usb_generic_descriptor
} [packed]

usb_request_types = USB_TYPE_STANDARD, USB_TYPE_CLASS, USB_TYPE_VENDOR

type vusb_descriptor_t[CLASS, REQ, DATA] {
	type	const[CLASS, int8]
	req	const[REQ, int8]
	len	bytesize[data, int32]
	data	DATA
} [packed]

# TODO: consider doing lookups based on USB_RECIP values.
vusb_responses {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	get_interface			ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	get_configuration		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

# TODO: move these into custom descriptions for hub class when they are added.
	hub_USB_REQ_GET_STATUS_hub	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_REQ_GET_STATUS, usb_hub_status]]
	hub_USB_REQ_GET_STATUS_port	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_REQ_GET_STATUS, usb_port_status]]

# TODO: move these into custom descriptions for asix driver when they are added.
	asix_AX_CMD_READ_MII_REG	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_MII_REG, int16]]
	asix_AX_CMD_STATMNGSTS_REG	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_STATMNGSTS_REG, int8]]
	asix_AX_CMD_READ_EEPROM		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_EEPROM, array[int8, 2]]]
	asix_AX_CMD_READ_RX_CTL		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_RX_CTL, int16]]
	asix_AX_CMD_READ_NODE_ID	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_NODE_ID, mac_addr]]
	asix_AX88172_CMD_READ_NODE_ID	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX88172_CMD_READ_NODE_ID, mac_addr]]
	asix_AX_CMD_READ_PHY_ID		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_PHY_ID, array[int8, 2]]]
	asix_AX_CMD_READ_MEDIUM_STATUS	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_MEDIUM_STATUS, int16]]
	asix_AX_CMD_READ_MONITOR_MODE	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_MONITOR_MODE, int8]]
	asix_AX_CMD_READ_GPIOS		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_GPIOS, int8]]
	asix_AX_CMD_SW_PHY_STATUS	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_SW_PHY_STATUS, int8]]
} [packed]

vusb_response_generic {
	type	flags[usb_request_types, int8]
	req	flags[usb_requests, int8]
	len	bytesize[data, int32]
	data	array[int8, 0:256]
} [packed]

usb_requests = USB_REQ_GET_STATUS, USB_REQ_CLEAR_FEATURE, USB_REQ_SET_FEATURE, USB_REQ_SET_ADDRESS, USB_REQ_GET_DESCRIPTOR, USB_REQ_SET_DESCRIPTOR, USB_REQ_GET_CONFIGURATION, USB_REQ_SET_CONFIGURATION, USB_REQ_GET_INTERFACE, USB_REQ_SET_INTERFACE, USB_REQ_SYNCH_FRAME, USB_REQ_SET_SEL, USB_REQ_SET_ISOCH_DELAY, USB_REQ_SET_ENCRYPTION, USB_REQ_GET_ENCRYPTION, USB_REQ_RPIPE_ABORT, USB_REQ_SET_HANDSHAKE, USB_REQ_RPIPE_RESET, USB_REQ_GET_HANDSHAKE, USB_REQ_SET_CONNECTION, USB_REQ_SET_SECURITY_DATA, USB_REQ_GET_SECURITY_DATA, USB_REQ_SET_WUSB_DATA, USB_REQ_LOOPBACK_DATA_WRITE, USB_REQ_LOOPBACK_DATA_READ, USB_REQ_SET_INTERFACE_DS, USB_REQ_GET_PARTNER_PDO, USB_REQ_GET_BATTERY_STATUS, USB_REQ_SET_PDO, USB_REQ_GET_VDM, USB_REQ_SEND_VDM

type vusb_response_t[CLASS, REQ, DATA] {
	type	const[CLASS, int8]
	req	const[REQ, int8]
	len	bytesize[data, int32]
	data	DATA
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# USB descriptors requested by the kernel before the SET_CONFIGURATION request.

# TODO: figure out when is the USB_DT_OTG descriptor used.
# TODO: figure out when is the USB_DT_INTERFACE_ASSOCIATION descriptor used.
# TODO: figure out when is the USB_DT_BOS descriptor used.

type usb_string_descriptor_t[DATA] {
	bLength		len[parent, int8]
	bDescriptorType	const[USB_DT_STRING, int8]

	data		DATA
} [packed]

usb_string_descriptor [
	lang_id	usb_string_descriptor_t[flags[usb_lang_ids, int16]]
	string	usb_string_descriptor_t[array[int8, 0:256]]
] [varlen]

usb_lang_ids = 0x436, 0x41c, 0x401, 0x801, 0xc01, 0x1001, 0x1401, 0x1801, 0x1c01, 0x2001, 0x2401, 0x2801, 0x2c01, 0x3001, 0x3401, 0x3801, 0x3c01, 0x4001, 0x42b, 0x44d, 0x42c, 0x82c, 0x42d, 0x423, 0x445, 0x402, 0x455, 0x403, 0x404, 0x804, 0xc04, 0x1004, 0x1404, 0x41a, 0x405, 0x406, 0x413, 0x813, 0x409, 0x809, 0xc09, 0x1009, 0x1409, 0x1809, 0x1c09, 0x2009, 0x2409, 0x2809, 0x2c09, 0x3009, 0x3409, 0x425, 0x438, 0x429, 0x40b, 0x40c, 0x80c, 0xc0c, 0x100c, 0x140c, 0x180c, 0x437, 0x407, 0x807, 0xc07, 0x1007, 0x1407, 0x408, 0x447, 0x40d, 0x439, 0x40e, 0x40f, 0x421, 0x410, 0x810, 0x411, 0x44b, 0x860, 0x43f, 0x457, 0x412, 0x812, 0x426, 0x427, 0x827, 0x42f, 0x43e, 0x83e, 0x44c, 0x458, 0x44e, 0x861, 0x414, 0x814, 0x448, 0x415, 0x416, 0x816, 0x446, 0x418, 0x419, 0x44f, 0xc1a, 0x81a, 0x459, 0x41b, 0x424, 0x40a, 0x80a, 0xc0a, 0x100a, 0x140a, 0x180a, 0x1c0a, 0x200a, 0x240a, 0x280a, 0x2c0a, 0x300a, 0x340a, 0x380a, 0x3c0a, 0x400a, 0x440a, 0x480a, 0x4c0a, 0x500a, 0x430, 0x441, 0x41d, 0x81d, 0x449, 0x444, 0x44a, 0x41e, 0x41f, 0x422, 0x420, 0x820, 0x443, 0x843, 0x42a, 0x4ff, 0xf0ff, 0xf4ff, 0xf8ff, 0xfcff

usb_qualifier_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_QUALIFIER, int8]

	bcdUSB			flags[usb_versions, int16]
	bDeviceClass		int8
	bDeviceSubClass		int8
	bDeviceProtocol		int8
	bMaxPacketSize0		flags[usb_device_max_packet_sizes, int8]
	bNumConfigurations	int8
	bRESERVED		const[0, int8]
} [packed]

usb_bos_descriptor {
	bLength		const[USB_DT_BOS_SIZE, int8]
	bDescriptorType	const[USB_DT_BOS, int8]

	wTotalLength	len[parent, int16]
	bNumDeviceCaps	len[caps, int8]

	caps		array[usb_dev_cap, 0:6]
} [packed]

usb_dev_cap [
	generic		usb_generic_cap_descriptor
	wireless	usb_wireless_cap_descriptor
	ext_cap		usb_ext_cap_descriptor
	ss_cap		usb_ss_cap_descriptor
	ss_container_id	usb_ss_container_id_descriptor
	ssp_cap		usb_ssp_cap_descriptor
	ptm_cap		usb_ptm_cap_descriptor
] [varlen]

usb_generic_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	flags[usb_capability_types, int8]

	data			array[int8, 0:256]
} [packed]

usb_capability_types = USB_CAP_TYPE_WIRELESS_USB, USB_CAP_TYPE_EXT, USB_SS_CAP_TYPE, USB_SSP_CAP_TYPE, CONTAINER_ID_TYPE, USB_PTM_CAP_TYPE

usb_wireless_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_CAP_TYPE_WIRELESS_USB, int8]

	bmAttributes		flags[usb_wireless_cap_attributes, int8]
	wPHYRates		flags[usb_wireless_cap_phyrates, int16]
	bmTFITXPowerInfo	int8
	bmFFITXPowerInfo	int8
	bmBandGroup		int16
	bReserved		int8
} [packed]

usb_wireless_cap_attributes = USB_WIRELESS_P2P_DRD, USB_WIRELESS_BEACON_MASK, USB_WIRELESS_BEACON_SELF, USB_WIRELESS_BEACON_DIRECTED, USB_WIRELESS_BEACON_NONE

usb_wireless_cap_phyrates = USB_WIRELESS_PHY_53, USB_WIRELESS_PHY_80, USB_WIRELESS_PHY_107, USB_WIRELESS_PHY_160, USB_WIRELESS_PHY_200, USB_WIRELESS_PHY_320, USB_WIRELESS_PHY_400, USB_WIRELESS_PHY_480

usb_ext_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_CAP_TYPE_EXT, int8]

	bmAttributes1		flags[usb_ext_cap_attributes, int32:8]
	bmAttributes2		int32:4
	bmAttributes3		int32:4
	bmAttributes4		int32:16
} [packed]

usb_ext_cap_attributes = USB_LPM_SUPPORT, USB_BESL_SUPPORT, USB_BESL_BASELINE_VALID, USB_BESL_DEEP_VALID

usb_ss_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_SS_CAP_TYPE, int8]

	bmAttributes		flags[usb_ss_cap_attributes, int8]
	wSpeedSupported		flags[usb_ss_cap_speed, int16]
	bFunctionalitySupport	int8
	bU1devExitLat		int8
	bU2DevExitLat		int16
} [packed]

usb_ss_cap_attributes = USB_LTM_SUPPORT

usb_ss_cap_speed = USB_LOW_SPEED_OPERATION, USB_FULL_SPEED_OPERATION, USB_HIGH_SPEED_OPERATION, USB_5GBPS_OPERATION

usb_ss_container_id_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[CONTAINER_ID_TYPE, int8]

	bReserved		int8
	ContainerID		array[int8, 16]
} [packed]

usb_ssp_cap_descriptor {
	bLength				len[parent, int8]
	bDescriptorType			const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType		const[USB_SSP_CAP_TYPE, int8]

	bReserved			int8
	bmAttributesSublinkSpeeds	len[bmSublinkSpeedAttr, int32:5]
	bmAttributesSpeedIDs		int32:27
	wFunctionalitySupport		flags[usb_ssp_cap_funcs, int16]
	wReserved			int16
	bmSublinkSpeedAttr		array[flags[usb_ssp_cap_sublink_speeds, int32], 0:6]
} [packed]

usb_ssp_cap_funcs = USB_SSP_MIN_SUBLINK_SPEED_ATTRIBUTE_ID, USB_SSP_MIN_RX_LANE_COUNT, USB_SSP_MIN_TX_LANE_COUNT

usb_ssp_cap_sublink_speeds = USB_SSP_SUBLINK_SPEED_SSID, USB_SSP_SUBLINK_SPEED_LSE, USB_SSP_SUBLINK_SPEED_ST, USB_SSP_SUBLINK_SPEED_RSVD, USB_SSP_SUBLINK_SPEED_LP, USB_SSP_SUBLINK_SPEED_LSM

usb_ptm_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_PTM_CAP_TYPE, int8]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Extra USB descriptors that come after an interface or an endpoint descriptor.

# TODO: consider removing class specific descriptors here for described classes.
usb_interface_extra_descriptor [
	generic		usb_generic_descriptor
	hid_hid		usb_hid_descriptor_hid
	cdc_ecm		usb_cdc_header_ecm
	cdc_ncm		usb_cdc_header_ncm
	uac_control	uac_control_iface_extra_descriptors
	uac_as		uac_as_iface_extra_descriptors
] [varlen]

usb_endpoint_extra_descriptor [
	generic	usb_generic_descriptor
	uac_iso	uac_iso_endpoint_descriptor
] [varlen]

usb_generic_descriptor {
	bLength		len[parent, int8]
	bDescriptorType	flags[usb_descriptor_types, int8]

	data		array[int8, 0:256]
} [packed]

usb_descriptor_types = USB_DT_DEVICE, USB_DT_CONFIG, USB_DT_STRING, USB_DT_INTERFACE, USB_DT_ENDPOINT, USB_DT_DEVICE_QUALIFIER, USB_DT_OTHER_SPEED_CONFIG, USB_DT_INTERFACE_POWER, USB_DT_OTG, USB_DT_DEBUG, USB_DT_INTERFACE_ASSOCIATION, USB_DT_SECURITY, USB_DT_KEY, USB_DT_ENCRYPTION_TYPE, USB_DT_BOS, USB_DT_DEVICE_CAPABILITY, USB_DT_WIRELESS_ENDPOINT_COMP, USB_DT_WIRE_ADAPTER, USB_DT_RPIPE, USB_DT_CS_RADIO_CONTROL, USB_DT_PIPE_USAGE, USB_DT_SS_ENDPOINT_COMP, USB_DT_SSP_ISOC_ENDPOINT_COMP, HID_DT_HID, HID_DT_REPORT, HID_DT_PHYSICAL

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# USB descriptors requested after the SET_CONFIGURATION request.

usb_hub_descriptor_hs {
	bDescLength		len[parent, int8]
	bDescriptorType		const[USB_DT_HUB, int8]

	bNbrPorts		int8
	wHubCharacteristics	flags[usb_hub_characteristics, int16]
	bPwrOn2PwrGood		int8
	bHubContrCurrent	int8

	DeviceRemovable		array[int8, USB_HUB_PORTS_BITS]
	PortPwrCtrlMask		array[int8, USB_HUB_PORTS_BITS]
} [packed]

usb_hub_descriptor_ss {
	bDescLength		len[parent, int8]
	bDescriptorType		const[USB_DT_SS_HUB, int8]

	bNbrPorts		int8
	wHubCharacteristics	flags[usb_hub_characteristics, int16]
	bPwrOn2PwrGood		int8
	bHubContrCurrent	int8

	bHubHdrDecLat		int8
	wHubDelay		int16
	DeviceRemovable		int16
} [packed]

define USB_HUB_PORTS_BITS	((USB_MAXCHILDREN + 1 + 7) / 8)

usb_hub_characteristics = HUB_CHAR_LPSM, HUB_CHAR_COMMON_LPSM, HUB_CHAR_INDV_PORT_LPSM, HUB_CHAR_NO_LPSM, HUB_CHAR_COMPOUND, HUB_CHAR_OCPM, HUB_CHAR_COMMON_OCPM, HUB_CHAR_INDV_PORT_OCPM, HUB_CHAR_NO_OCPM, HUB_CHAR_TTTT, HUB_CHAR_PORTIND

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Replies to USB control requests requested after the SET_CONFIGURATION request.

usb_port_status {
	wPortStatus	flags[usb_port_status_flags, int16]
	wPortChange	flags[usb_port_change_flags, int16]
	dwExtPortStatus	array[flags[usb_ext_port_status_flags, int32], 0:1]
} [packed]

usb_port_status_flags = USB_PORT_STAT_CONNECTION, USB_PORT_STAT_ENABLE, USB_PORT_STAT_SUSPEND, USB_PORT_STAT_OVERCURRENT, USB_PORT_STAT_RESET, USB_PORT_STAT_L1, USB_PORT_STAT_POWER, USB_PORT_STAT_LOW_SPEED, USB_PORT_STAT_HIGH_SPEED, USB_PORT_STAT_TEST, USB_PORT_STAT_INDICATOR, USB_PORT_STAT_LINK_STATE, USB_SS_PORT_STAT_POWER, USB_SS_PORT_STAT_SPEED, USB_PORT_STAT_SPEED_5GBPS, USB_SS_PORT_LS_U0, USB_SS_PORT_LS_U1, USB_SS_PORT_LS_U2, USB_SS_PORT_LS_U3, USB_SS_PORT_LS_SS_DISABLED, USB_SS_PORT_LS_RX_DETECT, USB_SS_PORT_LS_SS_INACTIVE, USB_SS_PORT_LS_POLLING, USB_SS_PORT_LS_RECOVERY, USB_SS_PORT_LS_HOT_RESET, USB_SS_PORT_LS_COMP_MOD, USB_SS_PORT_LS_LOOPBACK

usb_port_change_flags = USB_PORT_STAT_C_CONNECTION, USB_PORT_STAT_C_ENABLE, USB_PORT_STAT_C_SUSPEND, USB_PORT_STAT_C_OVERCURRENT, USB_PORT_STAT_C_RESET, USB_PORT_STAT_C_L1, USB_PORT_STAT_C_BH_RESET, USB_PORT_STAT_C_LINK_STATE, USB_PORT_STAT_C_CONFIG_ERROR

usb_ext_port_status_flags = USB_EXT_PORT_STAT_RX_SPEED_ID, USB_EXT_PORT_STAT_TX_SPEED_ID, USB_EXT_PORT_STAT_RX_LANES, USB_EXT_PORT_STAT_TX_LANES

usb_hub_status {
	wHubStatus	flags[usb_hub_status_flags, int16]
	wHubChange	flags[usb_hub_change_flags, int16]
} [packed]

usb_hub_status_flags = HUB_STATUS_LOCAL_POWER, HUB_STATUS_OVERCURRENT

usb_hub_change_flags = HUB_CHANGE_LOCAL_POWER, HUB_CHANGE_OVERCURRENT

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# HID device class specific descriptions.
# https://www.usb.org/sites/default/files/documents/hid1_11.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/hid/usbhid/hid-core.c
# https://elixir.bootlin.com/linux/latest/source/drivers/hid/hid-core.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/hid.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_hid.c

# Connected HID devices are known to create the following /dev/ files:
# /dev/hidraw#, /dev/usb/hiddev# and /dev/input/event#.

resource fd_usb_hid[fd_usb]

syz_usb_connect$hid(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_hid], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_hid (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$hid(fd fd_usb_hid, descs ptr[in, vusb_descriptors_hid], resps ptr[in, vusb_responses_hid]) (timeout[300], remote_cover)

# idVendor and idProduct are patched by Go code, see sys/linux/init_vusb.go.
usb_device_descriptor_hid {
	inner	usb_device_descriptor_t[0, 0, 0, 0, 0, 64, array[usb_config_descriptor_hid, 1]]
} [packed]

usb_config_descriptor_hid {
	inner	usb_config_descriptor_ifaces_array_t[const[1, int8], array[usb_interface_descriptor_hid, 1]]
} [packed]

usb_interface_descriptor_hid {
	inner	usb_interface_descriptor_t[const[0, int8], int8, int8[1:2], const[USB_CLASS_HID, int8], const[USB_INTERFACE_SUBCLASS_BOOT, int8], flags[usb_hid_protocols, int8], usb_hid_descriptor_hid, usb_endpoint_descriptors_hid]
} [packed]

usb_hid_protocols = USB_INTERFACE_PROTOCOL_KEYBOARD, USB_INTERFACE_PROTOCOL_MOUSE

usb_endpoint_descriptors_hid {
	in	usb_endpoint_descriptor_hid_in
	out	array[usb_endpoint_descriptor_hid_out, 0:1]
} [packed]

usb_endpoint_descriptor_hid_in {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_HID_IN_ADDRESS, int8], const[USB_ENDPOINT_HID_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_hid_out {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_HID_OUT_ADDRESS, int8], const[USB_ENDPOINT_HID_ATTRIBUTES, int8], void]
} [packed]

define USB_ENDPOINT_HID_ATTRIBUTES	(USB_ENDPOINT_XFER_INT)
define USB_ENDPOINT_HID_IN_ADDRESS	(1 | USB_DIR_IN)
define USB_ENDPOINT_HID_OUT_ADDRESS	(2)

vusb_descriptors_hid {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]

# For unknown reasons these are requested as USB_TYPE_STANDARD and not as USB_TYPE_CLASS.
# Linux doesn't request HID_DT_HID, but some hosts might do that.
	HID_DT_REPORT	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, HID_DT_REPORT, hid_descriptor_report]]
	HID_DT_HID	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, HID_DT_HID, usb_hid_descriptor_hid]]
} [packed]

vusb_responses_hid {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	HID_REQ_GET_REPORT		ptr[in, vusb_response_t[USB_TYPE_CLASS, HID_REQ_GET_REPORT, array[int8, 0:256]]]
	HID_REQ_GET_PROTOCOL		ptr[in, vusb_response_t[USB_TYPE_CLASS, HID_REQ_GET_PROTOCOL, int8]]
} [packed]

# USB HID specifications allows for multiple report and physical descriptors
# to be present, but I don't see any support for them in the Linux kernel,
# except for a single report descriptor.
usb_hid_descriptor_hid {
	bLength		len[parent, int8]
	bDescriptorType	const[HID_DT_HID, int8]

	bcdHID		int16
	bCountryCode	int8
	bNumDescriptors	const[1, int8]

	report_desc	usb_hid_class_descriptor_report
} [packed]

usb_hid_class_descriptor_report {
	bDescriptorType		const[HID_DT_REPORT, int8]
	wDescriptorLength	int16[0:HID_MAX_DESCRIPTOR_SIZE]
} [packed]

# TODO: it's hard to describe the REPORT descriptor structure via syzkaller
# descriptions, so consider generating it in Go code.
# TODO: the length of REPORT descriptor must match the value in HID descriptor.
# TODO: there are vendor specific REPORT descriptor formats (Logitech HID++).

# Linux HID stack doesn't support long items.
hid_descriptor_report {
	items	array[hid_report_item_short]
} [packed]

type hid_report_item_short_012_t[TYPE, TAGS] {
	bSize	len[data, int8:2]
	bType	const[TYPE, int8:2]
	bTag	flags[TAGS, int8:4]
	data	array[int8, 0:2]
} [packed]

type hid_report_item_short_4_t[TYPE, TAGS] {
	bSize	const[3, int8:2]
	bType	const[TYPE, int8:2]
	bTag	flags[TAGS, int8:4]
	data	array[int8, 4]
} [packed]

type hid_report_item_short_t[TYPE, TAGS] [
	item_012	hid_report_item_short_012_t[TYPE, TAGS]
	item_4		hid_report_item_short_4_t[TYPE, TAGS]
] [varlen]

hid_report_item_short [
	main	hid_report_item_short_t[HID_ITEM_TYPE_MAIN, hid_report_item_main_tags]
	global	hid_report_item_short_t[HID_ITEM_TYPE_GLOBAL, hid_report_item_global_tags]
	local	hid_report_item_short_t[HID_ITEM_TYPE_LOCAL, hid_report_item_local_tags]
] [varlen]

hid_report_item_main_tags = HID_MAIN_ITEM_TAG_INPUT, HID_MAIN_ITEM_TAG_OUTPUT, HID_MAIN_ITEM_TAG_FEATURE, HID_MAIN_ITEM_TAG_BEGIN_COLLECTION, HID_MAIN_ITEM_TAG_END_COLLECTION
hid_report_item_global_tags = HID_GLOBAL_ITEM_TAG_USAGE_PAGE, HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM, HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM, HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM, HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM, HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT, HID_GLOBAL_ITEM_TAG_UNIT, HID_GLOBAL_ITEM_TAG_REPORT_SIZE, HID_GLOBAL_ITEM_TAG_REPORT_ID, HID_GLOBAL_ITEM_TAG_REPORT_COUNT, HID_GLOBAL_ITEM_TAG_PUSH, HID_GLOBAL_ITEM_TAG_POP
hid_report_item_local_tags = HID_LOCAL_ITEM_TAG_USAGE, HID_LOCAL_ITEM_TAG_USAGE_MINIMUM, HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM, HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX, HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM, HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM, HID_LOCAL_ITEM_TAG_STRING_INDEX, HID_LOCAL_ITEM_TAG_STRING_MINIMUM, HID_LOCAL_ITEM_TAG_STRING_MAXIMUM, HID_LOCAL_ITEM_TAG_DELIMITER

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# PRINTER device class specific descriptions.
# https://www.usb.org/sites/default/files/usbprint11a021811.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/class/usblp.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/printer.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_printer.c

# Connected PRINTER devices are known to create the following /dev/ files:
# /dev/usb/lp#.
# TODO: write descriptions for those.

# drivers/usb/class/usblp.c
define USBLP_REQ_GET_ID	0x00
define USBLP_REQ_GET_STATUS	0x01
define USBLP_REQ_RESET	0x02
define USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST	0x00
define USBLP_FIRST_PROTOCOL	1
define USBLP_LAST_PROTOCOL	3

resource fd_usb_printer[fd_usb]

syz_usb_connect$printer(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_printer], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_printer (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$printer(fd fd_usb_printer, descs ptr[in, vusb_descriptors_printer], resps ptr[in, vusb_responses_printer]) (timeout[300], remote_cover)

usb_device_descriptor_printer {
	inner	usb_device_descriptor_t[0, 0, 0, 0x525, 0xa4a8, 64, array[usb_config_descriptor_printer, 1]]
} [packed]

usb_config_descriptor_printer {
	inner	usb_config_descriptor_ifaces_array_t[const[1, int8], array[usb_interface_descriptor_printer, 1]]
} [packed]

usb_interface_descriptor_printer {
	inner	usb_interface_descriptor_t[const[0, int8], int8, int8[1:2], const[USB_CLASS_PRINTER, int8], const[1, int8], int8[USBLP_FIRST_PROTOCOL:USBLP_LAST_PROTOCOL], void, usb_endpoint_descriptors_printer]
} [packed]

usb_endpoint_descriptors_printer {
	in	usb_endpoint_descriptor_printer_out
	out	array[usb_endpoint_descriptor_printer_in, 0:1]
} [packed]

usb_endpoint_descriptor_printer_out {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_PRINTER_OUT_ADDRESS, int8], const[USB_ENDPOINT_PRINTER_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_printer_in {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_PRINTER_IN_ADDRESS, int8], const[USB_ENDPOINT_PRINTER_ATTRIBUTES, int8], void]
} [packed]

define USB_ENDPOINT_PRINTER_ATTRIBUTES	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_PRINTER_OUT_ADDRESS	(1)
define USB_ENDPOINT_PRINTER_IN_ADDRESS	(2 | USB_DIR_IN)

vusb_descriptors_printer {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_printer {
	len					len[parent, int32]
	generic					ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE			ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	USBLP_REQ_GET_ID			ptr[in, vusb_response_t[USB_TYPE_CLASS, USBLP_REQ_GET_ID, usb_printer_get_id_response]]
	USBLP_REQ_GET_STATUS			ptr[in, vusb_response_t[USB_TYPE_CLASS, USBLP_REQ_GET_STATUS, int8]]
	USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST	ptr[in, vusb_response_t[USB_TYPE_CLASS, USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST, int8]]
} [packed]

usb_printer_get_id_response {
	length	len[id, int16be]
	id	array[int8, 0:256]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# CDC ECM (Ethernet) device class specific descriptions.
# https://www.usb.org/document-library/class-definitions-communication-devices-12
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/cdc_ether.c
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/usbnet.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/ether.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_ecm.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/u_ether.c

# Connected CDC ECM devices are known to create usbN network interfaces.
# TODO: write descriptions for those.

resource fd_usb_cdc_ecm[fd_usb]

syz_usb_connect$cdc_ecm(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_cdc_ecm], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_cdc_ecm (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$cdc_ecm(fd fd_usb_cdc_ecm, descs ptr[in, vusb_descriptors_cdc_ecm], resps ptr[in, vusb_responses_cdc_ecm]) (timeout[300], remote_cover)

usb_device_descriptor_cdc_ecm {
	inner	usb_device_descriptor_t[USB_CLASS_COMM, 0, 0, 0x525, 0xa4a1, 64, array[usb_config_descriptor_cdc_ecm, 1]]
} [packed]

usb_config_descriptor_cdc_ecm {
	inner	usb_config_descriptor_ifaces_array_t[const[1, int8], array[usb_interface_descriptor_cdc_ecm, 1]]
} [packed]

# Per specification CDC ECM devices have two interfaces (control and data),
# but here we're merging them into one for simplicity since Linux supports that.
usb_interface_descriptor_cdc_ecm {
	inner	usb_interface_descriptor_t[const[0, int8], int8, int8[2:3], const[USB_CLASS_COMM, int8], const[USB_CDC_SUBCLASS_ETHERNET, int8], const[USB_CDC_PROTO_NONE, int8], usb_cdc_header_ecm, usb_endpoint_descriptors_cdc_ecm]
} [packed]

usb_endpoint_descriptors_cdc_ecm {
	notify	array[usb_endpoint_descriptor_cdc_ecm_notify, 0:1]
	in	usb_endpoint_descriptor_cdc_ecm_in
	out	usb_endpoint_descriptor_cdc_ecm_out
} [packed]

usb_endpoint_descriptor_cdc_ecm_notify {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_CDC_ECM_NOTIFY_ADDRESS, int8], const[USB_ENDPOINT_CDC_ECM_NOTIFY_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_cdc_ecm_in {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_CDC_ECM_IN_ADDRESS, int8], const[USB_ENDPOINT_CDC_ECM_DATA_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_cdc_ecm_out {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_CDC_ECM_OUT_ADDRESS, int8], const[USB_ENDPOINT_CDC_ECM_DATA_ATTRIBUTES, int8], void]
} [packed]

define USB_ENDPOINT_CDC_ECM_NOTIFY_ATTRIBUTES	(USB_ENDPOINT_XFER_INT)
define USB_ENDPOINT_CDC_ECM_DATA_ATTRIBUTES	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_CDC_ECM_NOTIFY_ADDRESS	(1 | USB_DIR_IN)
define USB_ENDPOINT_CDC_ECM_IN_ADDRESS	(2 | USB_DIR_IN)
define USB_ENDPOINT_CDC_ECM_OUT_ADDRESS	(3)

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/usb/core/message.c#L2137
# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/cdc_ether.c#L155
usb_cdc_header_ecm {
	union	usb_cdc_union_desc_t[0, 0]
	header	usb_cdc_header_desc
	ether	usb_cdc_ether_desc

	other	array[usb_cdc_header_ecm_other, 0:6]
} [packed]

usb_cdc_header_ecm_other [
	call_mgmt		usb_cdc_call_mgmt_descriptor
	acm			usb_cdc_acm_descriptor
	country_functional	usb_cdc_country_functional_desc
	network_terminal	usb_cdc_network_terminal_desc
	dmm			usb_cdc_dmm_desc
	mdlm			usb_cdc_mdlm_desc
	mdlm_detail		usb_cdc_mdlm_detail_desc
	obex			usb_cdc_obex_desc
	ncm			usb_cdc_ncm_desc
	mbim			usb_cdc_mbim_desc
	mbim_extended		usb_cdc_mbim_extended_desc
] [varlen]

usb_cdc_header_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_HEADER_TYPE, int8]

	bcdCDC			int16
} [packed]

usb_cdc_call_mgmt_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_CALL_MANAGEMENT_TYPE, int8]

	bmCapabilities		flags[usb_cdc_call_mgmt_caps, int8]
	bDataInterface		int8
} [packed]

usb_cdc_call_mgmt_caps = USB_CDC_CALL_MGMT_CAP_CALL_MGMT, USB_CDC_CALL_MGMT_CAP_DATA_INTF

usb_cdc_acm_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_ACM_TYPE, int8]

	bmCapabilities		flags[usb_cdc_acm_caps, int8]
} [packed]

usb_cdc_acm_caps = USB_CDC_COMM_FEATURE, USB_CDC_CAP_LINE, USB_CDC_CAP_BRK, USB_CDC_CAP_NOTIFY

type usb_cdc_union_desc_t[MASTER, SLAVE] {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_UNION_TYPE, int8]

	bMasterInterface0	const[MASTER, int8]
	bSlaveInterface0	const[SLAVE, int8]
	slave_interfaces	array[int8, 0:6]
} [packed]

usb_cdc_country_functional_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_COUNTRY_TYPE, int8]

	iCountryCodeRelDate	int8
	wCountyCode0		int16
	country_codes		array[int16, 0:6]
} [packed]

usb_cdc_network_terminal_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_NETWORK_TERMINAL_TYPE, int8]

	bEntityId		int8
	iName			int8
	bChannelIndex		int8
	bPhysicalInterface	int8
} [packed]

usb_cdc_ether_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_ETHERNET_TYPE, int8]

	iMACAddress		const[1, int8]
	bmEthernetStatistics	int32
	wMaxSegmentSize		int16
	wNumberMCFilters	int16
	bNumberPowerFilters	int8
} [packed]

usb_cdc_dmm_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_DMM_TYPE, int8]

	bcdVersion		int16
	wMaxCommand		int16
} [packed]

usb_cdc_mdlm_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_MDLM_TYPE, int8]

	bcdVersion		int16
	bGUID			usb_cdc_ecm_mbm_guid
} [packed]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/cdc_ether.c#L61
usb_cdc_ecm_mbm_guid {
	id0	const[0x14f5e048ba817a3, int64]
	id1	const[0x2a397ecbffc007a6, int64]
} [packed]

usb_cdc_mdlm_detail_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_MDLM_DETAIL_TYPE, int8]

	bGuidDescriptorType	int8
	bDetailData		array[int8, 0:256]
} [packed]

usb_cdc_obex_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_OBEX_TYPE, int8]

	bcdVersion		int16
} [packed]

usb_cdc_ncm_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_NCM_TYPE, int8]

	bcdNcmVersion		int16
	bmNetworkCapabilities	flags[usb_cdc_ncm_ncaps, int8]
} [packed]

usb_cdc_ncm_ncaps = USB_CDC_NCM_NCAP_ETH_FILTER, USB_CDC_NCM_NCAP_NET_ADDRESS, USB_CDC_NCM_NCAP_ENCAP_COMMAND, USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE, USB_CDC_NCM_NCAP_CRC_MODE, USB_CDC_NCM_NCAP_NTB_INPUT_SIZE

usb_cdc_mbim_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_MBIM_TYPE, int8]

	bcdMBIMVersion		int16
	wMaxControlMessage	int16
	bNumberFilters		int8
	bMaxFilterSize		int8
	wMaxSegmentSize		int16
	bmNetworkCapabilities	int8
} [packed]

usb_cdc_mbim_extended_desc {
	bLength				len[parent, int8]
	bDescriptorType			const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType		const[USB_CDC_MBIM_EXTENDED_TYPE, int8]

	bcdMBIMExtendedVersion		int16
	bMaxOutstandingCommandMessages	int8
	wMTU				int16
} [packed]

vusb_descriptors_cdc_ecm {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/usbnet.c#L147
	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor_t[usb_cdc_ecm_mac]]]
} [packed]

usb_cdc_ecm_mac {
# This is a UTF16 encoded string "424242424242".
	data0	const[0x3400320034003200, int64be]
	data1	const[0x3400320034003200, int64be]
	data2	const[0x3400320034003200, int64be]
} [packed]

vusb_responses_cdc_ecm {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# CDC NCM class specific descriptions.
# CDC NCM is based on CDC ECM, so some of the descriptions are reused.
# https://www.usb.org/document-library/network-control-model-devices-specification-v10-and-errata-and-adopters-agreement
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/cdc_ncm.c
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/usbnet.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/ncm.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_ncm.c

resource fd_usb_cdc_ncm[fd_usb]

syz_usb_connect$cdc_ncm(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_cdc_ncm], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_cdc_ncm (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$cdc_ncm(fd fd_usb_cdc_ncm, descs ptr[in, vusb_descriptors_cdc_ncm], resps ptr[in, vusb_responses_cdc_ncm]) (timeout[300], remote_cover)

usb_device_descriptor_cdc_ncm {
	inner	usb_device_descriptor_t[USB_CLASS_COMM, 0, 0, 0x525, 0xa4a1, 64, array[usb_config_descriptor_cdc_ncm, 1]]
} [packed]

usb_config_descriptor_cdc_ncm {
	inner	usb_config_descriptor_t[const[1, int8], const[2, int8], usb_interface_descriptors_cdc_ncm]
} [packed]

usb_interface_descriptors_cdc_ncm {
	control		usb_interface_descriptor_fixed_t[0, CDC_NCM_COMM_ALTSETTING_NCM, 1, USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE, usb_cdc_header_ncm, usb_endpoint_descriptor_cdc_ecm_notify]
	data_nop	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE, void, void]
	data		usb_interface_descriptor_fixed_t[1, CDC_NCM_DATA_ALTSETTING_NCM, 2, USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE, void, usb_endpoint_descriptors_cdc_ncm_data]
} [packed]

usb_endpoint_descriptors_cdc_ncm_data {
	in	usb_endpoint_descriptor_cdc_ecm_in
	out	usb_endpoint_descriptor_cdc_ecm_out
} [packed]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/usb/core/message.c#L2137
# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/cdc_ncm.c#L798
usb_cdc_header_ncm {
	union	usb_cdc_union_desc_t[0, 1]
	header	usb_cdc_header_desc
	ether	usb_cdc_ether_desc
	ncm	usb_cdc_ncm_desc

	other	array[usb_cdc_header_ncm_other, 0:6]
} [packed]

usb_cdc_header_ncm_other [
	call_mgmt		usb_cdc_call_mgmt_descriptor
	acm			usb_cdc_acm_descriptor
	country_functional	usb_cdc_country_functional_desc
	network_terminal	usb_cdc_network_terminal_desc
	dmm			usb_cdc_dmm_desc
	mdlm			usb_cdc_mdlm_desc
	mdlm_detail		usb_cdc_mdlm_detail_desc
	obex			usb_cdc_obex_desc
	mbim			usb_cdc_mbim_desc
	mbim_extended		usb_cdc_mbim_extended_desc
] [varlen]

vusb_descriptors_cdc_ncm {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/usbnet.c#L147
	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor_t[usb_cdc_ecm_mac]]]
} [packed]

vusb_responses_cdc_ncm {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	USB_CDC_GET_NTB_PARAMETERS	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_NTB_PARAMETERS, usb_cdc_ncm_ntb_parameters]]
	USB_CDC_GET_NTB_INPUT_SIZE	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_NTB_INPUT_SIZE, int32]]
	USB_CDC_GET_NTB_FORMAT		ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_NTB_FORMAT, int16[0:1]]]
	USB_CDC_GET_MAX_DATAGRAM_SIZE	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_MAX_DATAGRAM_SIZE, int16]]
	USB_CDC_GET_CRC_MODE		ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_CRC_MODE, int16[0:1]]]
} [packed]

usb_cdc_ncm_ntb_parameters {
	wLength			int16
	bmNtbFormatsSupported	int16
	dwNtbInMaxSize		int32
	wNdpInDivisor		int16
	wNdpInPayloadRemainder	int16
	wNdpInAlignment		int16
	wPadding1		int16
	dwNtbOutMaxSize		int32
	wNdpOutDivisor		int16
	wNdpOutPayloadRemainder	int16
	wNdpOutAlignment	int16
	wNtbOutMaxDatagrams	int16
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC1 device class specific descriptions.
# https://www.usb.org/sites/default/files/audio10.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/audio.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac1.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac1_legacy.c
# https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/usb/audio.h

# TODO: find out which /dev/ files are created by connected UAC1 devices and add descriptions for those.

resource fd_usb_uac1[fd_usb]

syz_usb_connect$uac1(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_uac1], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_uac1 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$uac1(fd fd_usb_uac1, descs ptr[in, vusb_descriptors_uac1], resps ptr[in, vusb_responses_uac1]) (timeout[300], remote_cover)

usb_device_descriptor_uac1 {
	inner	usb_device_descriptor_t[0, 0, 0, 0x1d6b, 0x101, 64, array[usb_config_descriptor_uac1, 1]]
} [packed]

usb_config_descriptor_uac1 {
	inner	usb_config_descriptor_t[const[1, int8], const[3, int8], usb_interface_descriptors_uac1]
} [packed]

# TODO: control interface might have and optional interrupt endpoint.
usb_interface_descriptors_uac1 {
	inner	usb_interface_descriptors_uac1_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_uac1_inner {
	control		usb_interface_descriptor_fixed_t[0, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOCONTROL, 0, uac_control_iface_extra_descriptors, void]
	as_out_alt_0	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, void, void]
	as_out_alt_1	usb_interface_descriptor_fixed_t[1, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, uac_as_iface_extra_descriptors, uac_as_out_endpoint_descriptor]
	as_in_alt_0	usb_interface_descriptor_fixed_t[2, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, void, void]
	as_in_alt_1	usb_interface_descriptor_fixed_t[2, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, uac_as_iface_extra_descriptors, uac_as_in_endpoint_descriptor]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC uses IDs to make it possible for terminals and units to refer to each other.
# We don't have a way to describe this, so just use a limited number of ids.
type uac_id int8[1:6]

uac_control_iface_extra_descriptors {
	header	uac1_ac_header_descriptor
	others	array[uac_control_iface_extra_descriptor, 0:6]
} [packed]

uac1_ac_header_descriptor {
	bLength			const[UAC_DT_AC_HEADER_LENGTH, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_HEADER, int8]

	bcdADC			int16
	wTotalLength		len[uac_control_iface_extra_descriptors, int16]
	bInCollection		const[F_AUDIO_NUM_INTERFACES, int8]

# These must match interfaces numbers.
	baInterfaceNr0		const[1, int8]
	baInterfaceNr1		const[2, int8]
} [packed]

uac_control_iface_extra_descriptor [
	input_terminal	uac_input_terminal_descriptor
	output_terminal	uac1_output_terminal_descriptor
	mixer_unit	uac_mixer_unit_descriptor
	selector_unit	uac_selector_unit_descriptor
	feature_unit	uac_feature_unit_descriptor
	processing_unit	uac_processing_unit_descriptor
	extension_unit	uac_extension_unit_descriptor
] [varlen]

define F_AUDIO_NUM_INTERFACES	2
define UAC_DT_AC_HEADER_LENGTH	UAC_DT_AC_HEADER_SIZE(F_AUDIO_NUM_INTERFACES)

uac_input_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_INPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_input_terminal_types, int16]
	bAssocTerminal		uac_id
	bNrChannels		int8
	wChannelConfig		int16
	iChannelNames		int8
	iTerminal		int8
} [packed]

# The following list contains input terminal types and inout terminal types.
uac_input_terminal_types = UAC_TERMINAL_UNDEFINED, UAC_TERMINAL_STREAMING, UAC_TERMINAL_VENDOR_SPEC, UAC_INPUT_TERMINAL_UNDEFINED, UAC_INPUT_TERMINAL_MICROPHONE, UAC_INPUT_TERMINAL_DESKTOP_MICROPHONE, UAC_INPUT_TERMINAL_PERSONAL_MICROPHONE, UAC_INPUT_TERMINAL_OMNI_DIR_MICROPHONE, UAC_INPUT_TERMINAL_MICROPHONE_ARRAY, UAC_INPUT_TERMINAL_PROC_MICROPHONE_ARRAY, UAC_BIDIR_TERMINAL_UNDEFINED, UAC_BIDIR_TERMINAL_HANDSET, UAC_BIDIR_TERMINAL_HEADSET, UAC_BIDIR_TERMINAL_SPEAKER_PHONE, UAC_BIDIR_TERMINAL_ECHO_SUPPRESSING, UAC_BIDIR_TERMINAL_ECHO_CANCELING
# The following list contains output terminal types and inout terminal types.
uac_output_terminal_types = UAC_TERMINAL_UNDEFINED, UAC_TERMINAL_STREAMING, UAC_TERMINAL_VENDOR_SPEC, UAC_OUTPUT_TERMINAL_UNDEFINED, UAC_OUTPUT_TERMINAL_SPEAKER, UAC_OUTPUT_TERMINAL_HEADPHONES, UAC_OUTPUT_TERMINAL_HEAD_MOUNTED_DISPLAY_AUDIO, UAC_OUTPUT_TERMINAL_DESKTOP_SPEAKER, UAC_OUTPUT_TERMINAL_ROOM_SPEAKER, UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER, UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER, UAC_BIDIR_TERMINAL_UNDEFINED, UAC_BIDIR_TERMINAL_HANDSET, UAC_BIDIR_TERMINAL_HEADSET, UAC_BIDIR_TERMINAL_SPEAKER_PHONE, UAC_BIDIR_TERMINAL_ECHO_SUPPRESSING, UAC_BIDIR_TERMINAL_ECHO_CANCELING

uac1_output_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_OUTPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_output_terminal_types, int16]
	bAssocTerminal		uac_id
	bSourceID		uac_id
	iTerminal		int8
} [packed]

uac_mixer_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIXER_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac_selector_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_SELECTOR_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac_feature_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FEATURE_UNIT, int8]

	bUnitID			uac_id
	bSourceID		uac_id
	bControlSize		len[bmaControls, int8]
	bmaControls		array[flags[uac_feature_unit_controls, int16], 1:6]
	iFeature		int8
} [packed]

uac_feature_unit_controls = UAC_FU_MUTE, UAC_FU_VOLUME, UAC_FU_BASS, UAC_FU_MID, UAC_FU_TREBLE, UAC_FU_GRAPHIC_EQUALIZER, UAC_FU_AUTOMATIC_GAIN, UAC_FU_DELAY, UAC_FU_BASS_BOOST, UAC_FU_LOUDNESS

uac_processing_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC1_PROCESSING_UNIT, int8]

	bUnitID			uac_id
	wProcessType		flags[uac_processing_unit_types, int16]
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac_processing_unit_types = UAC_PROCESS_UNDEFINED, UAC_PROCESS_UP_DOWNMIX, UAC_PROCESS_DOLBY_PROLOGIC, UAC_PROCESS_STEREO_EXTENDER, UAC_PROCESS_REVERB, UAC_PROCESS_CHORUS, UAC_PROCESS_DYN_RANGE_COMP

uac_extension_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC1_EXTENSION_UNIT, int8]

	bUnitID			uac_id
	wProcessType		int16
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac_as_iface_extra_descriptors {
	others	array[uac_as_iface_extra_descriptor, 0:6]
} [packed]

uac_as_iface_extra_descriptor [
	as_header			uac1_as_header_descriptor
	format_type_i_continuous	uac_format_type_i_continuous_descriptor
	format_type_i_discrete		uac_format_type_i_discrete_descriptor
	format_type_ii_discrete		uac_format_type_ii_discrete_descriptor
	format_type_ii_ext		uac_format_type_ii_ext_descriptor
	format_type_i_ext		uac_format_type_i_ext_descriptor
] [varlen]

uac1_as_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_AS_GENERAL, int8]

	bTerminalLink		int8
	bDelay			int8
	wFormatTag		flags[uac_format_tags, int16]
} [packed]

uac_format_tags = UAC_FORMAT_TYPE_I_UNDEFINED, UAC_FORMAT_TYPE_I_PCM, UAC_FORMAT_TYPE_I_PCM8, UAC_FORMAT_TYPE_I_IEEE_FLOAT, UAC_FORMAT_TYPE_I_ALAW, UAC_FORMAT_TYPE_I_MULAW, UAC_FORMAT_TYPE_II_MPEG, UAC_FORMAT_TYPE_II_AC3
uac_usb_format_types_i = UAC_FORMAT_TYPE_I, UAC_FORMAT_TYPE_II, UAC_FORMAT_TYPE_III, UAC_FORMAT_TYPE_UNDEFINED

uac_format_type_i_continuous_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bNrChannels		int8
	bSubframeSize		int8[1:4]
	bBitResolution		int8
	bSamFreqType		int8
	tLowerSamFreq		array[int8, 0:3]
	tUpperSamFreq		array[int8, 0:3]
} [packed]

uac_format_type_i_discrete_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bNrChannels		int8
	bSubframeSize		int8[1:4]
	bBitResolution		int8
	bSamFreqType		int8
	tSamFreq		array[int8, 0:9]
} [packed]

uac_format_type_ii_discrete_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_II, int8]
	wMaxBitRate		int16
	wSamplesPerFrame	int16
	bSamFreqType		int8
	tSamFreq		array[int8, 0:9]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac_as_out_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac_iso_endpoint_descriptor]
} [packed]

uac_as_in_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_IN_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac_iso_endpoint_descriptor]
} [packed]

define USB_ENDPOINT_UAC1_AS_OUT_ADDRESS	(1 | USB_DIR_OUT)
define USB_ENDPOINT_UAC1_AS_IN_ADDRESS	(2 | USB_DIR_IN)
define USB_ENDPOINT_UAC1_AS_ATTRIBUTES	(USB_ENDPOINT_SYNC_ADAPTIVE | USB_ENDPOINT_XFER_ISOC)

uac_iso_ep_attributes = USB_ENDPOINT_SYNCTYPE, USB_ENDPOINT_SYNC_NONE, USB_ENDPOINT_SYNC_ASYNC, USB_ENDPOINT_SYNC_ADAPTIVE, USB_ENDPOINT_SYNC_SYNC

uac_iso_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubType	const[UAC_EP_GENERAL, int8]

	bmAttributes		flags[uac_iso_ep_attributes, int8]
	bLockDelayUnits		int8
	wLockDelay		int16
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

vusb_descriptors_uac1 {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_uac1 {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	audio_UAC_GET_CUR		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_CUR, array[int8, 1:3]]]
	audio_UAC_GET_MIN		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_MIN, array[int8, 1:3]]]
	audio_UAC_GET_MAX		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_MAX, array[int8, 1:3]]]
	audio_UAC_GET_RES		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_RES, array[int8, 1:4]]]
	audio_UAC_GET_MEM		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_MEM, array[int8, 3]]]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC2 device class specific descriptions.
# https://www.usb.org/sites/default/files/audio10.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/audio.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac2.c
# https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/usb/audio.h

resource fd_usb_uac2[fd_usb]

syz_usb_connect$uac2(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_uac2], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_uac2 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$uac2(fd fd_usb_uac2, descs ptr[in, vusb_descriptors_uac1], resps ptr[in, vusb_responses_uac1]) (timeout[300], remote_cover)

usb_device_descriptor_uac2 {
	inner	usb_device_descriptor_t[0, 0, 0, 0x41e, 0x3000, 64, array[usb_config_descriptor_uac2, 1]]
} [packed]

usb_config_descriptor_uac2 {
	inner	usb_config_descriptor_extra_t[const[1, int8], const[3, int8], uac2_interface_assoc_descriptor, usb_interface_descriptors_uac2]
} [packed]

uac2_interface_assoc_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_INTERFACE_ASSOCIATION, int8]

	bFirstInterface		int8[0:2]
	bInterfaceCount		int8[0:2]
	bFunctionClass		const[USB_CLASS_AUDIO, int8]
	bFunctionSubClass	flags[audio_function_category_types, int8]
	bFunctionProtocol	const[UAC_VERSION_2, int8]
	iFunction		int8
} [packed]

audio_function_category_types = UAC2_FUNCTION_SUBCLASS_UNDEFINED, UAC2_FUNCTION_DESKTOP_SPEAKER, UAC2_FUNCTION_HOME_THEATER, UAC2_FUNCTION_MICROPHONE, UAC2_FUNCTION_HEADSET, UAC2_FUNCTION_TELEPHONE, UAC2_FUNCTION_CONVERTER, UAC2_FUNCTION_SOUND_RECORDER, UAC2_FUNCTION_IO_BOX, UAC2_FUNCTION_MUSICAL_INSTRUMENT, UAC2_FUNCTION_PRO_AUDIO, UAC2_FUNCTION_AUDIO_VIDEO, UAC2_FUNCTION_CONTROL_PANEL, UAC2_FUNCTION_OTHER

usb_interface_descriptors_uac2 {
	inner	usb_interface_descriptors_uac2_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_uac2_inner {
	control		usb_interface_descriptor_fixed_t[0, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOCONTROL, UAC_VERSION_2, uac2_control_iface_extra_descriptors, void]
	as_out_alt_0	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, void, void]
	as_out_alt_1	usb_interface_descriptor_fixed_t[1, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, uac2_as_iface_extra_descriptors, uac2_as_out_endpoint_descriptor]
	as_in_alt_0	usb_interface_descriptor_fixed_t[2, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, void, void]
	as_in_alt_1	usb_interface_descriptor_fixed_t[2, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, uac2_as_iface_extra_descriptors, uac2_as_in_endpoint_descriptor]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac2_control_iface_extra_descriptors {
	header	uac2_ac_header_descriptor
	others	array[uac2_control_iface_extra_descriptor, 0:6]
} [packed]

uac2_ac_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MS_HEADER, int8]
	bcdADC			int16
	bCategory		flags[uac2_feature_unit_controls, int8]
	wTotalLength		len[uac2_control_iface_extra_descriptors, int16]
	bmControls		int8
} [packed]

uac2_feature_unit_controls = UAC2_FUNCTION_SUBCLASS_UNDEFINED, UAC2_FUNCTION_DESKTOP_SPEAKER, UAC2_FUNCTION_HOME_THEATER, UAC2_FUNCTION_MICROPHONE, UAC2_FUNCTION_HEADSET, UAC2_FUNCTION_TELEPHONE, UAC2_FUNCTION_CONVERTER, UAC2_FUNCTION_SOUND_RECORDER, UAC2_FUNCTION_IO_BOX, UAC2_FUNCTION_MUSICAL_INSTRUMENT, UAC2_FUNCTION_PRO_AUDIO, UAC2_FUNCTION_AUDIO_VIDEO, UAC2_FUNCTION_CONTROL_PANEL, UAC2_FUNCTION_OTHER, uac_feature_unit_controls

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac2_as_iface_extra_descriptors {
	others	array[uac2_as_iface_extra_descriptor, 0:6]
} [packed]

uac2_as_iface_extra_descriptor [
	as_header			uac2_as_header_descriptor
	format_type_i_descriptor	uac2_format_type_i_descriptor
	format_type_i_continuous	uac_format_type_i_continuous_descriptor
	format_type_i_discrete		uac_format_type_i_discrete_descriptor
	format_type_ii_discrete		uac_format_type_ii_discrete_descriptor
	format_type_i_ext		uac2_format_type_i_ext_descriptor
	format_type_ii_ext		uac_format_type_ii_ext_descriptor
] [varlen]

uac2_as_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_AS_GENERAL, int8]
	bTerminalLink		int8
	bmControls		int8
	bFormatType		flags[uac_usb_format_types_i, int8]
	bmFormats		flags[uac_format_tags, int32]
	bNrChannels		int8
	bmChannelConfig		int32
	iChannelNames		int8
} [packed]

b_sub_slot_sizes = 1, 2, 3, 4

uac2_format_type_i_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]
	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bSubslotSize		flags[b_sub_slot_sizes, int8]
	bBitResolution		int8
} [packed]

uac2_format_type_i_ext_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bSubslotSize		int8
	bBitResolution		int8
	bHeaderLength		int8
	bControlSize		int8
	bSideBandProtocol	int8
} [packed]

uac_format_type_ii_ext_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]
	bFormatType		const[UAC_FORMAT_TYPE_II, int8]
	wMaxBitRate		int16
	wSamplesPerFrame	int16
	bHeaderLength		int8
	bSideBandProtocol	int8
} [packed]

uac_format_type_i_ext_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]
	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bSubslotSize		int8
	bBitResolution		int8
	bHeaderLength		int8
	bControlSize		int8
	bSideBandProtocol	int8
} [packed]

uac2_as_out_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac2_iso_endpoint_descriptor]
} [packed]

uac2_as_in_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_IN_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac2_iso_endpoint_descriptor]
} [packed]

uac2_iso_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubtype	const[UAC_EP_GENERAL, int8]

	bmAttributes		flags[csep_bm_attributes, int8]
	bmControls		flags[csep_bm_controls, int8]
	bLockDelayUnits		int8
	wLockDelay		int16
} [packed]

csep_bm_attributes = UAC_EP_CS_ATTR_SAMPLE_RATE, UAC_EP_CS_ATTR_PITCH_CONTROL, UAC_EP_CS_ATTR_FILL_MAX
csep_bm_controls = UAC2_CONTROL_PITCH, UAC2_CONTROL_DATA_OVERRUN, UAC2_CONTROL_DATA_UNDERRUN

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac2_control_iface_extra_descriptor [
	input_terminal	uac2_input_terminal_descriptor
	output_terminal	uac2_output_terminal_descriptor
	mixer_unit	uac2_mixer_unit_descriptor
	selector_unit	uac2_clock_selector_descriptor

	feature_unit	uac2_feature_unit_descriptor
	processing_unit	uac2_processing_unit_descriptor
	extension_unit	uac2_extension_unit_descriptor

	effect_unit	uac2_effect_unit_descriptor
	sample_rate	uac2_sample_rate_descriptor
	source_unit	uac2_clock_source_descriptor
	multiply_unit	uac2_clock_multiplier_descriptor
] [varlen]

uac2_input_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_INPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_input_terminal_types, int16]
	bAssocTerminal		uac_id
	bCSourceID		int8
	bNrChannels		int8
	bmChannelConfig		int32
	iChannelNames		int8
	bmControls		int8
	iTerminal		int8
} [packed]

uac2_output_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_OUTPUT_TERMINAL, int8]
	bTerminalID		uac_id
	wTerminalType		flags[uac_output_terminal_types, int16]
	bAssocTerminal		int8
	bSourceID		uac_id
	bCSourceID		int8
	bmControls		int16
	iTerminal		int8
} [packed]

uac2_mixer_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIXER_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

# TODO: Figure out if bmControls and iClockSelector should be a part of this structure.
uac2_clock_selector_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_CLOCK_SELECTOR, int8]
	bClockID		int8
	bNrInPins		len[baCSourceID, int8]
	baCSourceID		array[int8, 0:8]
} [packed]

# TODO: Verify coverage.
uac2_processing_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC2_PROCESSING_UNIT_V2, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac2_processing_unit_types, int16], 1:6]
} [packed]

uac2_processing_unit_types = UAC2_PROCESS_UNDEFINED, UAC2_PROCESS_UP_DOWNMIX, UAC2_PROCESS_DOLBY_PROLOCIC, UAC2_PROCESS_STEREO_EXTENDER

uac2_extension_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_EXTENSION_UNIT_V2, int8]

	bUnitID			uac_id
	wProcessType		int16
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

# TODO: Verify coverage.
uac2_effect_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC2_EFFECT_UNIT, int8]
	bUnitID			uac_id
	wEffectType		flags[uac2_effect_unit_types, int16]
	bSourceID		uac_id
	bmaControls		array[flags[uac2_processing_unit_types, int16], 1:6]
} [packed]

uac2_effect_unit_types = UAC2_EFFECT_UNDEFINED, UAC2_EFFECT_PARAM_EQ, UAC2_EFFECT_REVERB, UAC2_EFFECT_MOD_DELAY, UAC2_EFFECT_DYN_RANGE_COMP

uac2_sample_rate_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC2_SAMPLE_RATE_CONVERTER, int8]
	bUnitID			uac_id
	wProcessType		flags[uac2_processing_unit_types, int16]
	bSourceID		uac_id
	bmaControls		array[flags[uac2_processing_unit_types, int16], 1:6]
} [packed]

uac2_feature_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_FEATURE_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac2_feature_unit_controls, int16], 1:6]
} [packed]

uac2_clock_source_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_CLOCK_SOURCE, int8]
	bClockID		int8
	bmAttributes		flags[uac2_clock_bmattribute_types, int8]
	bmControls		int8
	bAssocTerminal		int8
	iClockSource		flags[uac2_clock_source_types, int8]
} [packed]

uac2_clock_bmattribute_types = UAC_CLOCK_SOURCE_TYPE_EXT, UAC_CLOCK_SOURCE_TYPE_INT_FIXED, UAC_CLOCK_SOURCE_TYPE_INT_VAR, UAC_CLOCK_SOURCE_TYPE_INT_PROG, UAC_CLOCK_SOURCE_SYNCED_TO_SOF
uac2_clock_source_types = UAC_CLOCK_SOURCE_TYPE_EXT, UAC_CLOCK_SOURCE_TYPE_INT_FIXED, UAC_CLOCK_SOURCE_TYPE_INT_VAR, UAC_CLOCK_SOURCE_TYPE_INT_PROG, UAC_CLOCK_SOURCE_SYNCED_TO_SOF

uac2_clock_multiplier_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_CLOCK_MULTIPLIER, int8]
	bClockID		int8
	bCSourceID		int8
	bmControls		int8
	iClockMultiplier	int8
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC3 device class specific descriptions.
# https://www.usb.org/sites/default/files/audio10.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/audio.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac3.c
# https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/usb/audio.h

resource fd_usb_uac3[fd_usb]

syz_usb_connect$uac3(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_uac3], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_uac3 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$uac3(fd fd_usb_uac3, descs ptr[in, vusb_descriptors_uac1], resps ptr[in, vusb_responses_uac1]) (timeout[300], remote_cover)

usb_device_descriptor_uac3 {
	inner	usb_device_descriptor_t[0, 0, 0, 0x582, 0x582, 64, array[usb_config_descriptor_uac3, 1]]
} [packed]

usb_config_descriptor_uac3 {
	inner	usb_config_descriptor_extra_t[const[1, int8], const[3, int8], uac3_interface_assoc_descriptor, usb_interface_descriptors_uac3]
} [packed]

uac3_interface_assoc_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_INTERFACE_ASSOCIATION, int8]

	bFirstInterface		int8[0:2]
	bInterfaceCount		int8[0:2]
	bFunctionClass		const[USB_CLASS_AUDIO, int8]
	bFunctionSubClass	flags[uac3_all_subclasses, int8]
	bFunctionProtocol	const[UAC_VERSION_3, int8]
	iFunction		int8
} [packed]

usb_interface_descriptors_uac3 {
	inner	usb_interface_descriptors_uac3_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_uac3_inner {
	control		usb_interface_descriptor_fixed_t[0, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOCONTROL, UAC_VERSION_3, uac3_control_iface_extra_descriptors, void]
	as_out_alt_0	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, void, void]
	as_out_alt_1	usb_interface_descriptor_fixed_t[1, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, uac3_as_iface_extra_descriptors, uac3_as_out_endpoint_descriptor]
	as_in_alt_0	usb_interface_descriptor_fixed_t[2, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, void, void]
	as_in_alt_1	usb_interface_descriptor_fixed_t[2, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, uac3_as_iface_extra_descriptors, uac3_as_in_endpoint_descriptor]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac3_control_iface_extra_descriptors {
	header	uac3_ac_header_descriptor
	others	array[uac3_control_iface_extra_descriptor, 0:6]
} [packed]

uac3_ac_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MS_HEADER, int8]

	bCategory		flags[uac3_feature_unit_controls, int8]
	wTotalLength		len[uac3_control_iface_extra_descriptors, int16]
	bmControls		int32
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac3_as_iface_extra_descriptors {
	others	array[uac3_as_iface_extra_descriptor, 0:6]
} [packed]

uac3_as_iface_extra_descriptor [
	as_header			uac3_as_header_descriptor
	format_type_i_descriptor	uac2_format_type_i_descriptor
	format_type_i_continuous	uac_format_type_i_continuous_descriptor
	format_type_i_discrete		uac_format_type_i_discrete_descriptor
	format_type_ii_discrete		uac_format_type_ii_discrete_descriptor
	format_type_i_ext		uac2_format_type_i_ext_descriptor
	format_type_ii_ext		uac_format_type_ii_ext_descriptor
] [varlen]

# TODO: Figure out how wClusterDescrID is used in the kernel.
uac3_as_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_AS_GENERAL, int8]
	bTerminalLink		int8

	bmControls		int32
	wClusterDescrID		int16

	bmFormats		flags[uac_format_tags, int64]

	bSubslotSize		int8
	bBitResolution		int8
	bmAuxProtocols		int16
	bControlSize		int8
} [packed]

uac3_as_out_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac3_iso_endpoint_descriptor]
} [packed]

uac3_as_in_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_IN_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac3_iso_endpoint_descriptor]
} [packed]

uac3_iso_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubType	const[UAC3_CS_ENDPOINT, int8]
	bmControls		int32
	bLockDelayUnits		int8
	wLockDelay		int16
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac3_control_iface_extra_descriptor [
	input_terminal		uac3_input_terminal_descriptor
	output_terminal		uac3_output_terminal_descriptor
	mixer_unit		uac3_mixer_unit_descriptor
	selector_unit		uac3_clock_selector_descriptor
	source_unit		uac3_clock_source_descriptor
	multiply_unit		uac3_clock_multiplier_descriptor
	feature_unit		uac3_feature_unit_descriptor
	processing_unit		uac3_processing_unit_descriptor
	extension_unit		uac3_extension_unit_descriptor
	power_domain		uac3_power_domain_descriptor
	cluster_info_segment	uac3_cluster_information_segment_descriptor
# Only cluster information segment is currently used in the kernel.See: sound/usb/stream.c
# cluster_segment 		uac3_cluster_segment_descriptor
# cluster_end_segment		uac3_cluster_end_segment_descriptor
# The following units are not yet supported by the kernel.
# See audio_validators[] in sound/usb/validate.c:
#	effect_unit 		uac3_effect_unit_descriptor
#	sample_rate			uac3_sample_rate_descriptor
#	connectors_unit		uac3_connectors_unit_descriptor
#	extended_term_unit	uac3_extended_terminal_unit
] [varlen]

uac3_input_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_INPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_input_terminal_types, int16]
	bAssocTerminal		uac_id
	bCSourceID		int8

	bmControls		int32
	wClusterDescrID		int16
	wExTerminalDescrID	int16
	wConnectorsDescrID	int16
	wTerminalDescrStr	int16
} [packed]

uac3_output_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_OUTPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_output_terminal_types, int16]
	bAssocTerminal		uac_id
	bSourceID		uac_id
	bCSourceID		int8

	bmControls		int32
	wExTerminalDescrID	int16
	wConnectorsDescrID	int16
	wTerminalDescrStr	int16
} [packed]

uac3_mixer_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_MIXER_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac3_clock_selector_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_CLOCK_SELECTOR, int8]
	bClockID		int8
	bNrInPins		len[baCSourceID, int8]
	baCSourceID		array[int8, 0:8]
} [packed]

uac3_clock_source_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_CLOCK_SOURCE, int8]
	bClockID		int8
	bmAttributes		flags[uac3_clock_bmattribute_types, int8]
	bmControls		int32
	bReferenceTerminal	int8
	wClockSourceStr		int16
} [packed]

uac3_clock_bmattribute_types = UAC3_CLOCK_SOURCE_TYPE_EXT, UAC3_CLOCK_SOURCE_TYPE_INT, UAC3_CLOCK_SOURCE_ASYNC, UAC3_CLOCK_SOURCE_SYNCED_TO_SOF

uac3_clock_multiplier_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_CLOCK_MULTIPLIER, int8]
	bClockID		int8
	bCSourceID		int8
	bmControls		int32
	wCMultiplierDescrStr	int16
} [packed]

uac3_feature_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC3_FEATURE_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac3_feature_unit_controls, int32], 1:6]
} [packed]

uac3_processing_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC3_PROCESSING_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac3_processing_unit_types, int32], 1:6]
} [packed]

uac3_processing_unit_types = UAC3_PROCESS_UNDEFINED, UAC3_PROCESS_UP_DOWNMIX, UAC3_PROCESS_STEREO_EXTENDER, UAC3_PROCESS_MULTI_FUNCTION

uac3_extension_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC3_EXTENSION_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac3_processing_unit_types, int32], 1:6]
} [packed]

uac3_power_domain_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_POWER_DOMAIN, int8]

	bPowerDomainID		int8
	waRecoveryTime1		int16
	waRecoveryTime2		int16
	bNrEntities		int8
	baEntityID		array[int8, 0:8]
} [packed]

uac3_cluster_information_segment_descriptor {
	bLength		len[parent, int16]
	bSegmentType	const[UAC3_CHANNEL_INFORMATION, int8]
	bChPurpose	flags[uac3_cluster_channel_purposes, int8]
	bChRelationship	flags[uac3_cluster_channel_relationships, int8]
	bChGroupID	int8
} [packed]

uac3_cluster_channel_purposes = UAC3_PURPOSE_UNDEFINED, UAC3_PURPOSE_GENERIC_AUDIO, UAC3_PURPOSE_VOICE, UAC3_PURPOSE_SPEECH, UAC3_PURPOSE_AMBIENT, UAC3_PURPOSE_REFERENCE, UAC3_PURPOSE_ULTRASONIC, UAC3_PURPOSE_VIBROKINETIC, UAC3_PURPOSE_NON_AUDIO
uac3_cluster_channel_relationships = UAC3_CH_RELATIONSHIP_UNDEFINED, UAC3_CH_MONO, UAC3_CH_LEFT, UAC3_CH_RIGHT, UAC3_CH_ARRAY, UAC3_CH_PATTERN_X, UAC3_CH_PATTERN_Y, UAC3_CH_PATTERN_A, UAC3_CH_PATTERN_B, UAC3_CH_PATTERN_M, UAC3_CH_PATTERN_S, UAC3_CH_FRONT_LEFT, UAC3_CH_FRONT_RIGHT, UAC3_CH_FRONT_CENTER, UAC3_CH_FRONT_LEFT_OF_CENTER, UAC3_CH_FRONT_RIGHT_OF_CENTER, UAC3_CH_FRONT_WIDE_LEFT, UAC3_CH_FRONT_WIDE_RIGHT, UAC3_CH_SIDE_LEFT, UAC3_CH_SIDE_RIGHT, UAC3_CH_SURROUND_ARRAY_LEFT, UAC3_CH_SURROUND_ARRAY_RIGHT, UAC3_CH_BACK_LEFT, UAC3_CH_BACK_RIGHT, UAC3_CH_BACK_CENTER, UAC3_CH_BACK_LEFT_OF_CENTER, UAC3_CH_BACK_RIGHT_OF_CENTER, UAC3_CH_BACK_WIDE_LEFT, UAC3_CH_BACK_WIDE_RIGHT, UAC3_CH_TOP_CENTER, UAC3_CH_TOP_FRONT_LEFT, UAC3_CH_TOP_FRONT_RIGHT, UAC3_CH_TOP_FRONT_CENTER, UAC3_CH_TOP_FRONT_LOC, UAC3_CH_TOP_FRONT_ROC, UAC3_CH_TOP_FRONT_WIDE_LEFT, UAC3_CH_TOP_FRONT_WIDE_RIGHT, UAC3_CH_TOP_SIDE_LEFT, UAC3_CH_TOP_SIDE_RIGHT, UAC3_CH_TOP_SURR_ARRAY_LEFT, UAC3_CH_TOP_SURR_ARRAY_RIGHT, UAC3_CH_TOP_BACK_LEFT, UAC3_CH_TOP_BACK_RIGHT, UAC3_CH_TOP_BACK_CENTER, UAC3_CH_TOP_BACK_LOC, UAC3_CH_TOP_BACK_ROC, UAC3_CH_TOP_BACK_WIDE_LEFT, UAC3_CH_TOP_BACK_WIDE_RIGHT, UAC3_CH_BOTTOM_CENTER, UAC3_CH_BOTTOM_FRONT_LEFT, UAC3_CH_BOTTOM_FRONT_RIGHT, UAC3_CH_BOTTOM_FRONT_CENTER, UAC3_CH_BOTTOM_FRONT_LOC, UAC3_CH_BOTTOM_FRONT_ROC, UAC3_CH_BOTTOM_FRONT_WIDE_LEFT, UAC3_CH_BOTTOM_FRONT_WIDE_RIGHT, UAC3_CH_BOTTOM_SIDE_LEFT, UAC3_CH_BOTTOM_SIDE_RIGHT, UAC3_CH_BOTTOM_SURR_ARRAY_LEFT, UAC3_CH_BOTTOM_SURR_ARRAY_RIGHT, UAC3_CH_BOTTOM_BACK_LEFT, UAC3_CH_BOTTOM_BACK_RIGHT, UAC3_CH_BOTTOM_BACK_CENTER, UAC3_CH_BOTTOM_BACK_LOC, UAC3_CH_BOTTOM_BACK_ROC, UAC3_CH_BOTTOM_BACK_WIDE_LEFT, UAC3_CH_BOTTOM_BACK_WIDE_RIGHT, UAC3_CH_LOW_FREQUENCY_EFFECTS, UAC3_CH_LFE_LEFT, UAC3_CH_LFE_RIGHT, UAC3_CH_HEADPHONE_LEFT, UAC3_CH_HEADPHONE_RIGHT

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# This list consists of uac3_func_subclasses + uac3_badd_classes.
uac3_all_subclasses = UAC3_FUNCTION_SUBCLASS_UNDEFINED, UAC3_FUNCTION_SUBCLASS_FULL_ADC_3_0, UAC3_FUNCTION_SUBCLASS_GENERIC_IO, UAC3_FUNCTION_SUBCLASS_HEADPHONE, UAC3_FUNCTION_SUBCLASS_SPEAKER, UAC3_FUNCTION_SUBCLASS_MICROPHONE, UAC3_FUNCTION_SUBCLASS_HEADSET, UAC3_FUNCTION_SUBCLASS_HEADSET_ADAPTER, UAC3_FUNCTION_SUBCLASS_SPEAKERPHONE

uac3_feature_unit_controls = UAC3_FUNCTION_SUBCLASS_UNDEFINED, UAC3_FUNCTION_DESKTOP_SPEAKER, UAC3_FUNCTION_HOME_THEATER, UAC3_FUNCTION_MICROPHONE, UAC3_FUNCTION_HEADSET, UAC3_FUNCTION_TELEPHONE, UAC3_FUNCTION_CONVERTER, UAC3_FUNCTION_SOUND_RECORDER, UAC3_FUNCTION_IO_BOX, UAC3_FUNCTION_MUSICAL_INSTRUMENT, UAC3_FUNCTION_PRO_AUDIO, UAC3_FUNCTION_AUDIO_VIDEO, UAC3_FUNCTION_CONTROL_PANEL, UAC3_FUNCTION_HEADPHONE, UAC3_FUNCTION_GENERIC_SPEAKER, UAC3_FUNCTION_HEADSET_ADAPTER, UAC3_FUNCTION_SPEAKERPHONE, UAC3_FUNCTION_OTHER

# TODO: Support uac3 badd profiles. See sound/usb/mixer.c: snd_usb_mixer_controls_badd()
# uac3_badd_endpoint_descriptor {
# 	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac3_iso_endpoint_descriptor]
# } [packed]

#uac3_badd_maxsizes = UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16,UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16,UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24,UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24,UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16,UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16,UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24,UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# MIDI device class specific descriptions.
# https://www.usb.org/sites/default/files/midi10.pdf
# https://elixir.bootlin.com/linux/latest/source/sound/usb/midi.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_midi.c

syz_usb_connect$midi(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_midi], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb (timeout[3000], prog_timeout[3000], remote_cover)

usb_device_descriptor_midi {
	inner	usb_device_descriptor_t[0, 0, 0, 0x1430, 0x474b, 64, array[usb_config_descriptor_midi, 1]]
} [packed]

usb_config_descriptor_midi {
	inner	usb_config_descriptor_t[const[1, int8], const[1, int8], usb_interface_descriptors_midi]
} [packed]

usb_interface_descriptors_midi {
	inner	usb_interface_descriptors_midi_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_midi_inner {
	control	usb_interface_descriptor_eps_array_t[const[0, int8], const[0, int8], const[USB_CLASS_AUDIO, int8], const[USB_SUBCLASS_MIDISTREAMING, int8], flags[uac_version_types, int8], array[usb_midi_iface_extra], array[usb_endpoint_descriptor_midi, 0:8]]
} [packed]

usb_endpoint_descriptor_midi {
	inner	usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], flags[usb_endpoint_attributes, int8], usb_ms_endpoint_descriptor]
} [packed]

midi_jack_type = USB_MS_EMBEDDED, USB_MS_EXTERNAL
uac_version_types = UAC_VERSION_1, UAC_VERSION_2, UAC_VERSION_3

usb_ms_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubType	const[USB_MS_GENERAL, int8]
	bNumEmbMIDIJack		len[baAssocJackID, int8]
	baAssocJackID		array[int8, 0:16]
} [packed]

usb_midi_iface_extra [
	ms_header	usb_ms_header_descriptor
	midi_in_jack	usb_midi_in_jack_descriptor
	midi_out_jack	usb_midi_out_jack_descriptor
] [varlen]

usb_ms_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_HEADER, int8]
	bcdMSC			int16
	wTotalLength		len[parent, int16]
} [packed]

usb_midi_in_jack_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIDI_IN_JACK, int8]
	bJackType		flags[midi_jack_type, int8]
	bJackID			int8
	iJack			int8
} [packed]

usb_midi_out_jack_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIDI_OUT_JACK, int8]
	bJackType		flags[midi_jack_type, int8]
	bJackID			int8
	bNrInputPins		len[pins, int8]
	pins			array[usb_midi_source_pin]
	iJack			int8
} [packed]

usb_midi_source_pin {
	baSourceID	int8
	baSourcePin	int8
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# ath9k driver specific descriptions.

include <drivers/net/wireless/ath/ath9k/htc_hst.h>
include <drivers/net/wireless/ath/ath9k/hif_usb.h>

define USB_ENDPOINT_ATH9K_BULK_OUT_ADDRESS	(1)
define USB_ENDPOINT_ATH9K_BULK_IN_ADDRESS	(2 | USB_DIR_IN)
define USB_ENDPOINT_ATH9K_INT_IN_ADDRESS	(3 | USB_DIR_IN)
define USB_ENDPOINT_ATH9K_INT_OUT_ADDRESS	(4)
define USB_ENDPOINT_ATH9K_BULK_EXTRA1_ADDRESS	(5)
define USB_ENDPOINT_ATH9K_BULK_EXTRA2_ADDRESS	(6)

resource fd_usb_ath9k[fd_usb]

syz_usb_connect_ath9k(speed const[USB_SPEED_HIGH], dev_len len[dev], dev ptr[in, usb_device_descriptor_ath9k], conn_descs const[0]) fd_usb_ath9k (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_ep_write$ath9k_ep1(fd fd_usb_ath9k, ep const[USB_ENDPOINT_ATH9K_BULK_IN_ADDRESS], len bytesize[data], data ptr[in, ath9k_bulk_frame]) (timeout[300], remote_cover)
syz_usb_ep_write$ath9k_ep2(fd fd_usb_ath9k, ep const[USB_ENDPOINT_ATH9K_INT_IN_ADDRESS], len bytesize[data], data ptr[in, htc_frame]) (timeout[300], remote_cover)

usb_device_descriptor_ath9k {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0xcf3, 0x9271, 0x108, array[usb_config_descriptor_ath9k, 1]]
} [packed]

usb_config_descriptor_ath9k {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_ath9k]
} [packed]

usb_interface_descriptor_ath9k {
	iface	usb_interface_descriptor_fixed_t[0, 0, 6, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_ath9k]
} [packed]

usb_endpoint_descriptors_ath9k {
	bulk_out	usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_OUT_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
	bulk_in		usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_IN_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
	int_in		usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_INT_IN_ADDRESS, USB_ENDPOINT_ATH9K_INT_ATTRIBUTES, 64, 1, void]
	int_out		usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_INT_OUT_ADDRESS, USB_ENDPOINT_ATH9K_INT_ATTRIBUTES, 64, 1, void]
	bulk_extra1	usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_EXTRA1_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
	bulk_extra2	usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_EXTRA2_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
} [packed]

define USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_ATH9K_INT_ATTRIBUTES	(USB_ENDPOINT_XFER_INT)

ath9k_bulk_frame {
	packets	array[ath9k_bulk_packet]
} [packed]

ath9k_bulk_packet {
	pkt_len	len[data, int16]
	pkt_tag	const[ATH_USB_RX_STREAM_MODE_TAG, int16]
	data	array[int8]
} [packed, align[4]]

htc_frame [
	ready		htc_ready_frame
	conn_svc_rsp	htc_conn_svc_rsp_frame
	generic		htc_generic_frame
] [varlen]

# This is actually wrong, as the driver is buggy and doesn't skip the header
# before processing the frame payload, but let's leave it like thise for now.
htc_ready_frame {
	endpoint_id	const[0, int8]
	flags		const[0, int8]
	payload_len	len[payload, int16be]
	control		array[int8, 4]
	payload		htc_ready_msg
} [packed]

htc_ready_msg {
	message_id	const[HTC_MSG_READY_ID, int16be]
	credits		int16be
	credit_size	int16be
	max_endpoints	int8
	pad		int8
} [packed]

htc_conn_svc_rsp_frame {
	endpoint_id	const[0, int8]
	flags		const[0, int8]
	payload_len	len[payload, int16be]
	control		array[int8, 4]
	payload		htc_conn_svc_rspmsg
} [packed]

htc_conn_svc_rspmsg {
	message_id	const[HTC_MSG_CONNECT_SERVICE_RESPONSE_ID, int16be]
	service_id	flags[htc_svcs, int16be]
	status		const[HTC_SERVICE_SUCCESS, int8]
	endpoint_id	int8
	max_msg_len	int16be
	svc_meta_len	int8
	pad		int8
} [packed]

htc_svcs = HTC_CTRL_RSVD_SVC, HTC_LOOPBACK_RSVD_SVC, WMI_CONTROL_SVC, WMI_BEACON_SVC, WMI_CAB_SVC, WMI_UAPSD_SVC, WMI_MGMT_SVC, WMI_DATA_VO_SVC, WMI_DATA_VI_SVC, WMI_DATA_BE_SVC, WMI_DATA_BE_SVC

htc_generic_frame {
	endpoint_id	int8[0:8]
	flags		flags[htc_frame_flags, int8]
	payload_len	len[payload, int16be]
	control		array[int8, 4]
	payload		array[int8, 0:256]
} [packed]

htc_frame_flags = HTC_FLAGS_RECV_TRAILER

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Assorted driver-specific descriptions of generic syz_* calls' variants.

# Generic calls such as syz_usb_connect() and syz_usb_control_io() should be enough
# (in theory) to emulate a proper device and finish driver probes without a hitch.
# However, there are cases when syzkaller fails to come up with correct inputs to achieve it.
# Use fixed descriptors to quickly pass through probe() to access select drivers' post-probe functionality.

# It is important to note that, one way or another, drivers in question require multiple control requests
# between a driver and a device processed during probe(). Descriptions below do not deal with specific
# CTRL requests as such (except for basic information included in vusb_responses_XXX). Instead, rely on
# seeds, created both manually and with syzkaller's help. For examples, see sys/linux/test/vusb_XXX.

# Common constants for endpoint descriptors.
define USB_ENDPOINT_BULK_ATTR	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_INT_ATTR	(USB_ENDPOINT_XFER_INT)

define USB_FIXED_ENDPOINT_BULK_IN_ADDR	(1 | USB_DIR_IN)
define USB_FIXED_ENDPOINT_BULK_OUT_ADDR	(2)
define USB_FIXED_ENDPOINT_INT_IN_ADDR	(3 | USB_DIR_IN)

define USB_RECIP_DEVICE	0x00

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# rtl8150 driver specific descriptions.

resource fd_usb_rtl8150[fd_usb]

syz_usb_connect$rtl8150(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_rtl8150], conn_descs const[0]) fd_usb_rtl8150 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$rtl8150(fd fd_usb_rtl8150, descs ptr[in, vusb_descriptors_rtl8150], resps ptr[in, vusb_responses_rtl8150]) (timeout[300], remote_cover)

usb_device_descriptor_rtl8150 {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0xbda, 0x8150, 0, array[usb_config_descriptor_rtl8150, 1]]
} [packed]

usb_config_descriptor_rtl8150 {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_rtl8150]
} [packed]

usb_interface_descriptor_rtl8150 {
	iface	usb_interface_descriptor_fixed_t[0, 0, 3, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_rtl8150]
} [packed]

usb_endpoint_descriptors_rtl8150 {
	bulk_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_IN_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	bulk_out	usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_OUT_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	int_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_INT_IN_ADDR, USB_ENDPOINT_INT_ATTR, 64, 1, void]
} [packed]

vusb_descriptors_rtl8150 {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_rtl8150 {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	RTL8150_REQ_GET_REGS		ptr[in, vusb_response_t[RTL8150_REQT_READ, RTL8150_REQ_GET_REGS, array[int8, 0:6]]]
	RTL8150_REQ_SET_REGS		ptr[in, vusb_response_t[RTL8150_REQT_WRITE, RTL8150_REQ_SET_REGS, array[int8, 0:6]]]
} [packed]

define RTL8150_REQ_GET_REGS	0x05
define RTL8150_REQ_SET_REGS	0x05
define RTL8150_REQT_READ	0xc0
define RTL8150_REQT_WRITE	0x40

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# sierra_net driver specific descriptions.

resource fd_usb_sierra_net[fd_usb]

syz_usb_connect$sierra_net(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_sierra_net], conn_descs const[0]) fd_usb_sierra_net (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$sierra_net(fd fd_usb_sierra_net, descs ptr[in, vusb_descriptors_sierra_net], resps ptr[in, vusb_responses_sierra_net]) (timeout[300], remote_cover)

usb_device_descriptor_sierra_net {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0x1199, 0x68a3, 0, array[usb_config_descriptor_sierra_net, 1]]
} [packed]

usb_config_descriptor_sierra_net {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_sierra_net]
} [packed]

usb_interface_descriptor_sierra_net {
	iface	usb_interface_descriptor_fixed_t[7, 0, 3, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_sierra_net]
} [packed]

# sierra_net driver does not expect fixed ep addresses, so refrain from being too specific here.
# As long as we ensure there are 3 endpoints, 2 bulk and 1 int, syzkaller should figure it out.
usb_endpoint_descriptors_sierra_net {
	bulk_in		usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], const[USB_ENDPOINT_BULK_ATTR, int8], void]
	bulk_out	usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], const[USB_ENDPOINT_BULK_ATTR, int8], void]
	status		usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], const[USB_ENDPOINT_INT_ATTR, int8], void]
} [packed]

vusb_descriptors_sierra_net {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_sierra_net {
	len					len[parent, int32]
	generic					ptr[in, vusb_response_generic]

	USB_CDC_GET_ENCAPSULATED_RESPONSE	ptr[in, vusb_response_t[SIERRA_CMD_TYPE_IN, USB_CDC_GET_ENCAPSULATED_RESPONSE, array[int8, 1024]]]
	USB_CDC_SEND_ENCAPSULATED_COMMANDT	ptr[in, vusb_response_t[SIERRA_CMD_TYPE_OUT, USB_CDC_SEND_ENCAPSULATED_COMMAND, array[int8, 0:4]]]
} [packed]

define SIERRA_CMD_TYPE_IN	(USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)
define SIERRA_CMD_TYPE_OUT	(USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# lan78xx driver specific descriptions.
# While these syz_* variants noticably help with the probe() process, they are not enough.
# This is due to a high number of control requests expected between the driver and the device.

include <drivers/net/usb/smsc95xx.h>

resource fd_usb_lan78xx[fd_usb]

syz_usb_connect$lan78xx(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_lan78xx], conn_descs const[0]) fd_usb_lan78xx (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$lan78xx(fd fd_usb_lan78xx, descs ptr[in, vusb_descriptors_lan78xx], resps ptr[in, vusb_responses_lan78xx]) (timeout[300], remote_cover)

usb_device_descriptor_lan78xx {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0x424, 0x7850, 0, array[usb_config_descriptor_lan78xx, 1]]
} [packed]

usb_config_descriptor_lan78xx {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_lan78xx]
} [packed]

usb_interface_descriptor_lan78xx {
	iface	usb_interface_descriptor_fixed_t[0, 0, 3, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_lan78xx]
} [packed]

usb_endpoint_descriptors_lan78xx {
	bulk_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_IN_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	bulk_out	usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_OUT_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	int_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_INT_IN_ADDR, USB_ENDPOINT_INT_ATTR, 64, 1, void]
} [packed]

vusb_descriptors_lan78xx {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_lan78xx {
	len					len[parent, int32]
	generic					ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE			ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	USB_VENDOR_REQUEST_READ_REGISTER	ptr[in, vusb_response_t[LAN78XX_REG_TYPE_IN, USB_VENDOR_REQUEST_READ_REGISTER, int32]]
	USB_VENDOR_REQUEST_WRITE_REGISTER	ptr[in, vusb_response_t[LAN78XX_REG_TYPE_OUT, USB_VENDOR_REQUEST_WRITE_REGISTER, int32]]
	USB_VENDOR_REQUEST_GET_STATS		ptr[in, vusb_response_t[LAN78XX_REG_TYPE_IN, USB_VENDOR_REQUEST_GET_STATS, array[int8, 47]]]
} [packed]

define LAN78XX_REG_TYPE_IN	(USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
define LAN78XX_REG_TYPE_OUT	(USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
]

191/2 2026/07/30 12:41 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 95817
							output: 50
							thoughts: 142
						

Thoughts:
**Targeting Specific USB Devices**

Okay, so I'm digging into `syz_usb_connect`. It looks like the function wants a `speed`, device length (`dev_len`), device pointer (`dev`), and connection descriptors (`conn_descs`). Interesting. I see that I can use `syz_usb_connect(0, &AUTO, &AUTO, 0)` and syzkaller will automatically cook up a random `usb_device_descriptor` for me. But that's not what I'm after, I want to be more specific. I'm thinking I want to target devices like `si4713`, `au0828`, or `go7007`.

Hmm, wait a second... `si4713`... that's a radio driver, right? Right, it is. Let's see... I'll need to check the source code at `drivers/media/radio/si4713/radio-usb-si4713.c` to see how it's handled. Okay, now we are getting somewhere.



192/2 2026/07/30 12:41 tool read-file
0m Args:
map[File:drivers/media/radio/si4713/radio-usb-si4713.c FirstLine:1 LineCount:100]

Results:
map[Contents:   1:	// SPDX-License-Identifier: GPL-2.0-only
   2:	/*
   3:	 * Copyright 2013 Cisco Systems, Inc. and/or its affiliates.
   4:	 * All rights reserved.
   5:	 */
   6:	
   7:	/* kernel includes */
   8:	#include <linux/kernel.h>
   9:	#include <linux/module.h>
  10:	#include <linux/usb.h>
  11:	#include <linux/init.h>
  12:	#include <linux/slab.h>
  13:	#include <linux/input.h>
  14:	#include <linux/mutex.h>
  15:	#include <linux/i2c.h>
  16:	/* V4l includes */
  17:	#include <linux/videodev2.h>
  18:	#include <media/v4l2-common.h>
  19:	#include <media/v4l2-device.h>
  20:	#include <media/v4l2-ioctl.h>
  21:	#include <media/v4l2-event.h>
  22:	#include <linux/platform_data/media/si4713.h>
  23:	
  24:	#include "si4713.h"
  25:	
  26:	/* driver and module definitions */
  27:	MODULE_AUTHOR("Dinesh Ram <dinesh.ram@cern.ch>");
  28:	MODULE_DESCRIPTION("Si4713 FM Transmitter USB driver");
  29:	MODULE_LICENSE("GPL v2");
  30:	
  31:	/* The Device announces itself as Cygnal Integrated Products, Inc. */
  32:	#define USB_SI4713_VENDOR		0x10c4
  33:	#define USB_SI4713_PRODUCT		0x8244
  34:	
  35:	#define BUFFER_LENGTH			64
  36:	#define USB_TIMEOUT			1000
  37:	#define USB_RESP_TIMEOUT		50000
  38:	
  39:	/* USB Device ID List */
  40:	static const struct usb_device_id usb_si4713_usb_device_table[] = {
  41:		{USB_DEVICE_AND_INTERFACE_INFO(USB_SI4713_VENDOR, USB_SI4713_PRODUCT,
  42:								USB_CLASS_HID, 0, 0) },
  43:		{ }						/* Terminating entry */
  44:	};
  45:	
  46:	MODULE_DEVICE_TABLE(usb, usb_si4713_usb_device_table);
  47:	
  48:	struct si4713_usb_device {
  49:		struct usb_device	*usbdev;
  50:		struct usb_interface	*intf;
  51:		struct video_device	vdev;
  52:		struct v4l2_device	v4l2_dev;
  53:		struct v4l2_subdev	*v4l2_subdev;
  54:		struct mutex		lock;
  55:		struct i2c_adapter	i2c_adapter;
  56:	
  57:		u8			*buffer;
  58:	};
  59:	
  60:	static inline struct si4713_usb_device *to_si4713_dev(struct v4l2_device *v4l2_dev)
  61:	{
  62:		return container_of(v4l2_dev, struct si4713_usb_device, v4l2_dev);
  63:	}
  64:	
  65:	static int vidioc_querycap(struct file *file, void *priv,
  66:						struct v4l2_capability *v)
  67:	{
  68:		struct si4713_usb_device *radio = video_drvdata(file);
  69:	
  70:		strscpy(v->driver, "radio-usb-si4713", sizeof(v->driver));
  71:		strscpy(v->card, "Si4713 FM Transmitter", sizeof(v->card));
  72:		usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
  73:		return 0;
  74:	}
  75:	
  76:	static int vidioc_g_modulator(struct file *file, void *priv,
  77:					struct v4l2_modulator *vm)
  78:	{
  79:		struct si4713_usb_device *radio = video_drvdata(file);
  80:	
  81:		return v4l2_subdev_call(radio->v4l2_subdev, tuner, g_modulator, vm);
  82:	}
  83:	
  84:	static int vidioc_s_modulator(struct file *file, void *priv,
  85:					const struct v4l2_modulator *vm)
  86:	{
  87:		struct si4713_usb_device *radio = video_drvdata(file);
  88:	
  89:		return v4l2_subdev_call(radio->v4l2_subdev, tuner, s_modulator, vm);
  90:	}
  91:	
  92:	static int vidioc_s_frequency(struct file *file, void *priv,
  93:					const struct v4l2_frequency *vf)
  94:	{
  95:		struct si4713_usb_device *radio = video_drvdata(file);
  96:	
  97:		return v4l2_subdev_call(radio->v4l2_subdev, tuner, s_frequency, vf);
  98:	}
  99:	
 100:	static int vidioc_g_frequency(struct file *file, void *priv,
]

193/2 2026/07/30 12:41 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 97860
							output: 594
							thoughts: 1090
						

Thoughts:
**Navigating the USB Device Descriptor Maze**

Okay, so I'm looking at how to trigger this `si4713` device. It looks like the `USB_CLASS_HID` class matches. The `syz_usb_connect$hid` call *should* work if syzkaller is patching the vendor and product IDs. I need to make sure this call does patch the right ones, right?

I see that `syz_usb_connect$hid` uses `usb_device_descriptor_hid` where Go code patches those values. Can't easily check the Go code. But hold on... I could just manually specify the vendor/product IDs in the syzkaller program!

Wait... `syz_usb_connect$hid` takes a pointer to `usb_device_descriptor_hid`. The definition is: a structure with a nested `usb_device_descriptor_t`, where vendor and product are hardcoded to zero! That means they *are* being patched!

If I wanted to provide my own descriptor, I'd need to use the generic `syz_usb_connect` function. However, constructing a custom `usb_device_descriptor` with nested structures looks complicated, with nested `usb_config_descriptor`.

Aha! `&AUTO`! I can let syzkaller generate most of it and override specific fields. For example, I could override just vendor and product: `&AUTO={@inner={0, 0, 0, 0, 0, 0, 0, 0x10c4, 0x8244, 0, 0, 0, 0, 0, []}}`.

But... `usb_device_descriptor_t` is actually an alias for `usb_device_descriptor_verbose_t`. And that's where all the detailed structure is defined: all the individual values, bLength, bDescriptorType, and all the rest. And also nested `usb_config_descriptor_t`.

So, using `syz_usb_connect(0, &AUTO, &AUTO, 0)`, the `dev` argument is going to be `usb_device_descriptor`: a struct with a nested `usb_device_descriptor_t` with even further nested descriptors. Now, I *could* craft something complex like: `&AUTO={@inner={AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, 0x10c4, 0x8244, AUTO, AUTO, AUTO, AUTO, AUTO, [@inner={AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, [@inner={AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, [@inner={AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO}]}]}]}}`, but it looks way too cumbersome.

Wait... back to `syz_usb_connect$hid`, maybe it won't patch the `si4713` IDs because they are not in the patching list. I *could* verify if `si4713` is listed, but if not:

I could use `syz_usb_connect` and just override `idVendor` and `idProduct`. No hex strings, no need for complex nested structs! Use `&AUTO={@inner={AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, 0x10c4, 0x8244}}`. Yes, I'll go with this! Let's try it.



194/2 2026/07/30 12:41 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={@inner={AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, 0x10c4, 0x8244}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

195/2 2026/07/30 12:41 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 100463
							output: 591
							thoughts: 113
						

Thoughts:
**Analyzing the USB Device Descriptor**

Okay, so I'm looking at this `usb_device_descriptor`. The first thing that jumps out at me is that it's *not* a union, but a struct. That's good. Now, I see the structure definition... it's `usb_device_descriptor { inner usb_device_descriptor_t[0, 0, 0, 0, 0, 0, array[usb_config_descriptor, 1]] } [packed]`. With the array syntax. Hmmm, the size and structure are probably important here. Given the overall context, I should construct the AUTO fill for this structure. Therefore, the memory layout should be `&AUTO={{AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, 0x10c4, 0x8244}}`. I think that looks correct given the declaration.



196/2 2026/07/30 12:41 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, 0x10c4, 0x8244}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

197/2 2026/07/30 12:41 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 101386
							output: 598
							thoughts: 477
						

Thoughts:
**Analyzing USB Device Descriptor Structure**

Okay, so I'm trying to figure out how these USB descriptors work, and it's clear that `AUTO` isn't going to cut it for flags. I need to dig deeper. Let's examine this `usb_device_descriptor_verbose_t` structure.

```
type usb_device_descriptor_verbose_t[USB, CLASS, SUBCLASS, PROTOCOL, PACKET, VENDOR, PRODUCT, DEVICE, CFS] {
	bLength			const[USB_DT_DEVICE_SIZE, int8]
	bDescriptorType		const[USB_DT_DEVICE, int8]

	bcdUSB			USB
	bDeviceClass		const[CLASS, int8]
	bDeviceSubClass		const[SUBCLASS, int8]
	bDeviceProtocol		const[PROTOCOL, int8]
	bMaxPacketSize0		PACKET
	idVendor		const[VENDOR, int16]
	idProduct		const[PRODUCT, int16]
	bcdDevice		const[DEVICE, int16]
	iManufacturer		const[1, int8]
	iProduct		const[2, int8]
	iSerialNumber		const[3, int8]
	bNumConfigurations	len[configs, int8]

	configs			CFS
} [packed]
```

Alright, I see the fields. Now, let's look at how `usb_device_descriptor_t` is defined. Aha! I see the relationship now.

`type usb_device_descriptor_t[CLASS, SUBCLASS, PROTOCOL, VENDOR, PRODUCT, DEVICE, CFS] usb_device_descriptor_verbose_t[flags[usb_versions, int16], CLASS, SUBCLASS, PROTOCOL, flags[usb_device_max_packet_sizes, int8], VENDOR, PRODUCT, DEVICE, CFS]`

It looks like the `bcdUSB` field is actually a flag, representing USB version, and the `bMaxPacketSize0` field is another flag, indicating maximum packet size. Knowing this, I think I can safely use `0x200` for `bcdUSB` (for USB 2.0) and `64` for `bMaxPacketSize0`. Hopefully, this will get me a valid descriptor. I'll test it out with:

`&AUTO={{AUTO, AUTO, 0x200, AUTO, AUTO, AUTO, 64, 0x10c4, 0x8244}}`



198/2 2026/07/30 12:41 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{AUTO, AUTO, 0x200, AUTO, AUTO, AUTO, 64, 0x10c4, 0x8244}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

199/2 2026/07/30 12:41 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 103174
							output: 610
							thoughts: 257
						

Thoughts:
**My Current Focus: Defining the Device Descriptor**

Okay, I've got it, I need to define the device descriptor. I almost missed some critical fields in the process, but I've reviewed the list. Let's make sure I hit all the necessary elements. There are 15 fields total and they are: `bLength`, `bDescriptorType`, `bcdUSB`, `bDeviceClass`, `bDeviceSubClass`, `bDeviceProtocol`, `bMaxPacketSize0`, `idVendor`, `idProduct`, `bcdDevice`, `iManufacturer`, `iProduct`, `iSerialNumber`, `bNumConfigurations`, and `configs`. Now, let's assemble this correctly. I can see that some of these have an AUTO value assigned to them and these will be derived by the system. All the other fields will be set to values as described.

So, the complete device descriptor is: `&AUTO={{AUTO, AUTO, 0x200, AUTO, AUTO, AUTO, 64, 0x10c4, 0x8244, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO}}`.



200/2 2026/07/30 12:42 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{AUTO, AUTO, 0x200, AUTO, AUTO, AUTO, 64, 0x10c4, 0x8244, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

201/2 2026/07/30 12:42 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 104309
							output: 610
							thoughts: 104
						

Thoughts:
**Working Through the Configuration Issue**

Okay, so I'm looking at this `configs` variable and it's definitely an array. That immediately tells me I can't just use `AUTO` on its own for this particular case. It expects an array, and `AUTO` just isn't designed for array initialization. Let's see... the type is `array[usb_config_descriptor, 1]`. Right, a single-element array containing a `usb_config_descriptor`. Given that, an empty array `[]` should be perfectly acceptable to serve as a placeholder or to essentially suppress the automatic configuration. So, the correct substitution to get things working is: `&AUTO={{AUTO, AUTO, 0x200, AUTO, AUTO, AUTO, 64, 0x10c4, 0x8244, AUTO, AUTO, AUTO, AUTO, AUTO, []}}` . I am making an array of the proper size, with empty configuration info, thus suppressing the issue.



202/2 2026/07/30 12:42 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{AUTO, AUTO, 0x200, AUTO, AUTO, AUTO, 64, 0x10c4, 0x8244, AUTO, AUTO, AUTO, AUTO, AUTO, []}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

203/2 2026/07/30 12:42 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 105343
							output: 629
							thoughts: 585
						

Thoughts:
**Deconstructing the `usb_config_descriptor`**

Okay, so I'm looking at `array[usb_config_descriptor, 1]`. That means I need exactly one element in the array. My first thought was `[{}]`, but then I remember `usb_config_descriptor` is a struct, and it has an `inner` field. Alright, let's dive into that `usb_config_descriptor` definition.

Looking at the structure, `usb_config_descriptor` contains `inner`, which itself looks like `usb_config_descriptor_ifaces_array_t[int8, array[usb_interface_descriptor, 1:4]]`. Okay, that's interesting. Then I see that `usb_config_descriptor_ifaces_array_t` is actually `usb_config_descriptor_t[NUM, len[interfaces, int8], IFS]`.  And then `usb_config_descriptor_t` expands to  `usb_config_descriptor_verbose_t[NUM, IFSNUM, int8, flags[usb_config_attributes, int8], int8, void, IFS]`. Alright, this gives the underlying structure of the descriptor.

Finally, the breakdown: `usb_config_descriptor_verbose_t`... Right, so we have several fields: `bLength`, `bDescriptorType`, `wTotalLength`, `bNumInterfaces`, `bConfigurationValue`, `iConfiguration`, `bmAttributes`, `bMaxPower`, `extra`, and `interfaces`. The `extra` field is declared as `void`. My brain's screaming, '0 fields!', so I check to confirm the void definition. Yep, `void` takes zero fields. That means we have a total of nine fields.

Now let's see, that structure looks like:
1. `bLength` (AUTO)
2. `bDescriptorType` (AUTO)
3. `wTotalLength` (AUTO)
4. `bNumInterfaces` (AUTO)
5. `bConfigurationValue` (AUTO)
6. `iConfiguration` (AUTO)
7. `bmAttributes` (AUTO)
8. `bMaxPower` (AUTO)
9. `interfaces` (array)

So, based on this, I'll attempt building an instance that looks like `[{inner={AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, []}}]`. Let's see if this works.



204/2 2026/07/30 12:42 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{AUTO, AUTO, 0x200, AUTO, AUTO, AUTO, 64, 0x10c4, 0x8244, AUTO, AUTO, AUTO, AUTO, AUTO, [{{AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, []}}]}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

205/2 2026/07/30 12:42 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 107113
							output: 633
							thoughts: 122
						

Thoughts:
**Decoding the Configuration Attributes**

Okay, so I'm looking at `bmAttributes`. It's clearly a bitfield – a series of flags represented as `flags[usb_config_attributes, int8]`. That means I have to set a value. Diving into the options, `usb_config_attributes` contains the possibilities: `USB_CONFIG_ATT_ONE`, `USB_CONFIG_ATT_SELFPOWER`, `USB_CONFIG_ATT_WAKEUP`, and `USB_CONFIG_ATT_BATTERY`. Based on what I'm seeing here, a good initial approach is to use `0x80`, which corresponds to `USB_CONFIG_ATT_ONE`. This looks right, and here's how the resulting structure is configured: `[{inner={AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, 0x80, AUTO, []}}]`.



206/2 2026/07/30 12:42 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{AUTO, AUTO, 0x200, AUTO, AUTO, AUTO, 64, 0x10c4, 0x8244, AUTO, AUTO, AUTO, AUTO, AUTO, [{{AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, 0x80, AUTO, []}}]}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

207/2 2026/07/30 12:42 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 108080
							output: 648
							thoughts: 671
						

Thoughts:
**Analyzing USB Descriptor Structure with Syzkaller**

Okay, so I'm looking at how Syzkaller should handle USB descriptors, particularly with `AUTO`. Let's break this down. First, I'm checking the types. `bConfigurationValue` is `NUM`, an `int8`. `AUTO` should work fine here. The `usb_config_descriptor`'s structure confirms that `NUM` is indeed an `int8`.

`bNumInterfaces` is `IFSNUM`, also an `int8`, defined as the length of an interface array, so `AUTO` should also be applicable. `iConfiguration` and `bMaxPower` are also `int8`, so `AUTO` should apply here.

Now, let's revisit `usb_device_descriptor_verbose_t`. `bDeviceClass` is `const[CLASS, int8]`. Wait, the `usb_device_descriptor` is composed of an array of `usb_config_descriptor` with fields such as `bDeviceClass` in it. `CLASS` appears to be `0` (as it has to be). The `const` modifier here is what's throwing a wrench in things, right? `const` fields shouldn't take `AUTO`.

Okay, the crucial point is that `const` fields are treated differently. Syzkaller probably fills these with known values anyway; maybe I can provide a precise value or use `AUTO` but it sounds like I can't.

Looking closer, the error "wrong type *prog.IntType for AUTO" is key. It indicates that `AUTO` is being used where an `IntType` is expected but isn't allowed. However, inside a struct, `AUTO` should be perfectly acceptable for `IntType` fields, right? This is where the error stems from.

The error means that when an `IntType` is expected, I am NOT allowed to use `AUTO`.

To be safe, let's provide `0` for all the `AUTO` values which are integers, rather than rely on `AUTO` within structures as Syzkaller currently implements it. That should resolve this issue. In other words, if I'm not sure, I'll provide an explicit value.



208/2 2026/07/30 12:42 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, 0, [{{0, 0, 0, 0, 0, 0, 0x80, 0, []}}]}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

209/2 2026/07/30 12:42 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 110021
							output: 678
							thoughts: 886
						

Thoughts:
**Deconstructing the USB Interface Descriptor**

Okay, so I'm looking at this `interfaces` definition and it's an array of `usb_interface_descriptor` with a minimum of one element. Let's delve into what this `usb_interface_descriptor` actually *is*.

Right, so `usb_interface_descriptor` contains an `inner` field. This `inner` field is of type `usb_interface_descriptor_eps_array_t`. Let's unravel this type.

Following the chain, `usb_interface_descriptor_eps_array_t` is defined in terms of `usb_interface_descriptor_t`, which in turn leads us to `usb_interface_descriptor_verbose_t`. And here it is! This `usb_interface_descriptor_verbose_t` looks like the core of the structure. It has these key fields: `bLength`, `bDescriptorType`, `bInterfaceNumber`, `bAlternateSetting`, `bNumEndpoints`, `bInterfaceClass`, `bInterfaceSubClass`, `bInterfaceProtocol`, `iInterface`, `extra`, and `endpoints`. Wait a minute, did I just count eleven fields? Let me double-check. Yes, that's right, eleven fields.

So, initially, the `inner` field starts with default values, and the `extra` and `endpoints` arrays are empty. Thus my initial understanding is as follows: `[{inner={0, 0, 0, 0, 0, 0, 0, 0, 0, [], []}}]`.

Okay, now let's apply the *si4713* requirement; specifically, `USB_CLASS_HID` (which is `3`). Therefore, I need to modify `bInterfaceClass` to be `3`. Thus the updated result is now: `[{inner={0, 0, 0, 0, 0, 3, 0, 0, 0, [], []}}]`.



210/2 2026/07/30 12:43 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, 0, [{{0, 0, 0, 0, 0, 0, 0x80, 0, [{{0, 0, 0, 0, 0, 3, 0, 0, 0, [], []}}]}}]}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

211/2 2026/07/30 12:43 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 112185
							output: 48
							thoughts: 1077
						

Thoughts:
**Analyzing USB Descriptor Construction for HID Device Interaction**

Okay, let's break this down. My initial thought was about how the `usb_interface_descriptor` is structured. Specifically, the fact that `usb_interface_descriptor_eps_array_t`'s `CLASS` field is a `const[0, int8]` is crucial. This means the `bInterfaceClass` *must* be set to 0. Therefore, any `syz_usb_connect` calls that utilize the basic `usb_device_descriptor` will *always* have a `bInterfaceClass` of 0. That's a constraint I need to keep in mind.

Now, the `syz_usb_connect$hid` call, however, uses `usb_device_descriptor_hid`, which sets the `bInterfaceClass` to `USB_CLASS_HID` (3). This is a potential route. Digging deeper into `usb_device_descriptor_hid` shows that it is comprised of an `inner` field which is `usb_device_descriptor_t` which includes `usb_config_descriptor_hid`. This is promising. The `usb_config_descriptor_hid` contains a `usb_interface_descriptor_hid` structure. The `usb_interface_descriptor_hid` is where the HID-specific data resides. Specifically, the `bInterfaceClass` and its associated values are key.

The ideal scenario would be to modify the `idVendor` and `idProduct` fields within the `usb_device_descriptor_hid` struct to target my desired device. The syntax for this might be something like `&AUTO={@inner={AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, 0x10c4, 0x8244}}`. However, `usb_device_descriptor_hid` is actually a struct containing a *single* `inner` field of `usb_device_descriptor_t`. So, I'd have to specify all 15 fields of the `usb_device_descriptor_t` structure. This sounds like it might get unwieldy and error-prone.

So, let's explore if syzkaller automatically handles some of this for me. Does syzkaller already patch `idVendor` and `idProduct` when I use `syz_usb_connect$hid`, maybe to match a HID driver?

If it does, I can check if it patches to my target device. I wonder if it includes the `si4713`? No, it's very unlikely to hit it by chance, given the number of HID drivers. I remember `si4713` is a radio driver, but it registers as a USB HID device. That is very unusual. Let's look for other cases. How about `au0828`? That's a video driver, and its associated code base will have valuable information. Let's start by looking at `drivers/media/usb/au0828/au0828-core.c`.



212/2 2026/07/30 12:43 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-core.c FirstLine:1 LineCount:100]

Results:
map[Contents:   1:	// SPDX-License-Identifier: GPL-2.0-or-later
   2:	/*
   3:	 *  Driver for the Auvitek USB bridge
   4:	 *
   5:	 *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
   6:	 */
   7:	
   8:	#include "au0828.h"
   9:	#include "au8522.h"
  10:	
  11:	#include <linux/module.h>
  12:	#include <linux/slab.h>
  13:	#include <linux/videodev2.h>
  14:	#include <media/v4l2-common.h>
  15:	#include <linux/mutex.h>
  16:	
  17:	/* Due to enum tuner_pad_index */
  18:	#include <media/tuner.h>
  19:	
  20:	/*
  21:	 * 1 = General debug messages
  22:	 * 2 = USB handling
  23:	 * 4 = I2C related
  24:	 * 8 = Bridge related
  25:	 * 16 = IR related
  26:	 */
  27:	int au0828_debug;
  28:	module_param_named(debug, au0828_debug, int, 0644);
  29:	MODULE_PARM_DESC(debug,
  30:			 "set debug bitmask: 1=general, 2=USB, 4=I2C, 8=bridge, 16=IR");
  31:	
  32:	static unsigned int disable_usb_speed_check;
  33:	module_param(disable_usb_speed_check, int, 0444);
  34:	MODULE_PARM_DESC(disable_usb_speed_check,
  35:			 "override min bandwidth requirement of 480M bps");
  36:	
  37:	#define _AU0828_BULKPIPE 0x03
  38:	#define _BULKPIPESIZE 0xffff
  39:	
  40:	static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
  41:				    u16 index);
  42:	static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
  43:		u16 index, unsigned char *cp, u16 size);
  44:	
  45:	/* USB Direction */
  46:	#define CMD_REQUEST_IN		0x00
  47:	#define CMD_REQUEST_OUT		0x01
  48:	
  49:	u32 au0828_readreg(struct au0828_dev *dev, u16 reg)
  50:	{
  51:		u8 result = 0;
  52:	
  53:		recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, &result, 1);
  54:		dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, result);
  55:	
  56:		return result;
  57:	}
  58:	
  59:	u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val)
  60:	{
  61:		dprintk(8, "%s(0x%04x, 0x%02x)\n", __func__, reg, val);
  62:		return send_control_msg(dev, CMD_REQUEST_OUT, val, reg);
  63:	}
  64:	
  65:	static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
  66:		u16 index)
  67:	{
  68:		int status = -ENODEV;
  69:	
  70:		if (dev->usbdev) {
  71:	
  72:			/* cp must be memory that has been allocated by kmalloc */
  73:			status = usb_control_msg(dev->usbdev,
  74:					usb_sndctrlpipe(dev->usbdev, 0),
  75:					request,
  76:					USB_DIR_OUT | USB_TYPE_VENDOR |
  77:						USB_RECIP_DEVICE,
  78:					value, index, NULL, 0, 1000);
  79:	
  80:			status = min(status, 0);
  81:	
  82:			if (status < 0) {
  83:				pr_err("%s() Failed sending control message, error %d.\n",
  84:					__func__, status);
  85:			}
  86:	
  87:		}
  88:	
  89:		return status;
  90:	}
  91:	
  92:	static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
  93:		u16 index, unsigned char *cp, u16 size)
  94:	{
  95:		int status = -ENODEV;
  96:		mutex_lock(&dev->mutex);
  97:		if (dev->usbdev) {
  98:			status = usb_control_msg(dev->usbdev,
  99:					usb_rcvctrlpipe(dev->usbdev, 0),
 100:					request,
]

213/2 2026/07/30 12:43 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 115480
							output: 50
							thoughts: 48
						

Thoughts:
**Analyzing the `au0828` Video Driver**

Okay, so `au0828` is a video driver. My initial instinct is to dig into the USB identification details to understand the specific hardware it's designed to support. So, my next thought is to head straight to the source code – specifically, `drivers/media/usb/au0828/au0828-cards.c`. That's where I'd expect to find the USB IDs meticulously listed. Understanding those IDs will give me the crucial insight I need to fully grasp the supported devices.



214/2 2026/07/30 12:43 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-cards.c FirstLine:310 LineCount:100]

Results:
map[Contents: 310:	
 311:			/* Into reset */
 312:			au0828_write(dev, REG_001, 0x0);
 313:			au0828_write(dev, REG_000, 0x0);
 314:			msleep(50);
 315:	
 316:			/* Bring power supply out of reset */
 317:			au0828_write(dev, REG_000, 0x80);
 318:			msleep(50);
 319:	
 320:			/* Bring xc5000 and au8522 out of reset (leave the
 321:			   cs5340 in reset until needed) */
 322:			au0828_write(dev, REG_001, 0x02); /* xc5000 */
 323:			au0828_write(dev, REG_000, 0x80 | 0x20); /* PS + au8522 */
 324:	
 325:			msleep(250);
 326:			break;
 327:		case AU0828_BOARD_DVICO_FUSIONHDTV7:
 328:			/* GPIO's
 329:			 * 6 - ?
 330:			 * 8 - AU8522 Demodulator
 331:			 * 9 - XC5000 Tuner
 332:			 */
 333:	
 334:			/* Into reset */
 335:			au0828_write(dev, REG_003, 0x02);
 336:			au0828_write(dev, REG_002, 0xa0);
 337:			au0828_write(dev, REG_001, 0x0);
 338:			au0828_write(dev, REG_000, 0x0);
 339:			msleep(100);
 340:	
 341:			/* Out of reset */
 342:			au0828_write(dev, REG_003, 0x02);
 343:			au0828_write(dev, REG_002, 0xa0);
 344:			au0828_write(dev, REG_001, 0x02);
 345:			au0828_write(dev, REG_000, 0xa0);
 346:			msleep(250);
 347:			break;
 348:		}
 349:	}
 350:	
 351:	/* table of devices that work with this driver */
 352:	struct usb_device_id au0828_usb_id_table[] = {
 353:		{ USB_DEVICE(0x2040, 0x7200),
 354:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 355:		{ USB_DEVICE(0x2040, 0x7240),
 356:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 },
 357:		{ USB_DEVICE(0x0fe9, 0xd620),
 358:			.driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 },
 359:		{ USB_DEVICE(0x2040, 0x7210),
 360:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 361:		{ USB_DEVICE(0x2040, 0x7217),
 362:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 363:		{ USB_DEVICE(0x2040, 0x721b),
 364:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 365:		{ USB_DEVICE(0x2040, 0x721e),
 366:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 367:		{ USB_DEVICE(0x2040, 0x721f),
 368:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 369:		{ USB_DEVICE(0x2040, 0x7280),
 370:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 371:		{ USB_DEVICE(0x0fd9, 0x0008),
 372:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 373:		{ USB_DEVICE(0x2040, 0x7201),
 374:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
 375:		{ USB_DEVICE(0x2040, 0x7211),
 376:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
 377:		{ USB_DEVICE(0x2040, 0x7281),
 378:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
 379:		{ USB_DEVICE(0x05e1, 0x0480),
 380:			.driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY },
 381:		{ USB_DEVICE(0x2040, 0x8200),
 382:			.driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY },
 383:		{ USB_DEVICE(0x2040, 0x7260),
 384:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 385:		{ USB_DEVICE(0x2040, 0x7213),
 386:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 387:		{ USB_DEVICE(0x2040, 0x7270),
 388:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
 389:		{ USB_DEVICE(0x2040, 0x72b0),
 390:			.driver_info = AU0828_BOARD_HAUPPAUGE_IMPACTVCBE },
 391:		{ USB_DEVICE(0x2040, 0x72a0),
 392:			.driver_info = AU0828_BOARD_HAUPPAUGE_HVR1265 },
 393:		{ },
 394:	};
 395:	
 396:	MODULE_DEVICE_TABLE(usb, au0828_usb_id_table);
]

215/2 2026/07/30 12:43 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 117735
							output: 51
							thoughts: 318
						

Thoughts:
**USB Device ID Ponderings**

Okay, so I've got `au0828` with the specific ID `0x2040:0x7200`. My immediate thought is, does syzkaller have a predefined description for this device? Let me quickly scan `dev_video4linux.txt` and `vusb.txt` to see if it's already there. Nope, not in `vusb.txt`.

Alright, I could try using `syz_usb_connect(0, &AUTO, &AUTO, 0)`, and syzkaller *could* generate a random device descriptor. But that's not what I want. I need to nail down those `idVendor` and `idProduct` values. I know building a `usb_device_descriptor` manually is a pain. I could use `syz_usb_connect$hid`, but unfortunately the Go code patches prevent overriding `idVendor` and `idProduct`.

Hmm... what if I use `syz_usb_connect` and just feed it the raw bytes directly? No, that won't work, because `syz_usb_connect` expects a `usb_device_descriptor` struct.

Wait a minute... I could use `syz_usb_connect` with `&AUTO` and let syzkaller mutate it. That's a possibility. The problem is I want this to be deterministic, so random mutation isn't ideal.

Is there *any* other syzkaller primitive that would let me connect a USB device with these specific IDs? What about the `go7007` driver? Let me go look at `drivers/media/usb/go7007/go7007-usb.c` to see if that gives me any ideas.



216/2 2026/07/30 12:43 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:1200 LineCount:100]

Results:
map[Contents:1200:				} else {
1201:					u16 channel;
1202:	
1203:					/* read channel number from GPIO[1:0] */
1204:					if (go7007_read_addr(go, 0x3c81, &channel))
1205:						goto allocfail;
1206:	
1207:					channel &= 0x3;
1208:					go->board_id = GO7007_BOARDID_ADLINK_MPG24;
1209:					usb->board = board = &board_adlink_mpg24;
1210:					go->board_info = &board->main_info;
1211:					go->channel_number = channel;
1212:					snprintf(go->name, sizeof(go->name),
1213:						"Adlink PCI-MPG24, channel #%d",
1214:						channel);
1215:				}
1216:				go7007_update_board(go);
1217:			}
1218:		}
1219:	
1220:		num_i2c_devs = go->board_info->num_i2c_devs;
1221:	
1222:		/* Probe the tuner model on the TV402U */
1223:		if (go->board_id == GO7007_BOARDID_PX_TV402U) {
1224:			/* Board strapping indicates tuner model */
1225:			if (go7007_usb_vendor_request(go, 0x41, 0, 0, go->usb_buf, 3,
1226:						1) < 0) {
1227:				dev_err(go->dev, "GPIO read failed!\n");
1228:				goto allocfail;
1229:			}
1230:			switch (go->usb_buf[0] >> 6) {
1231:			case 1:
1232:				go->tuner_type = TUNER_SONY_BTF_PG472Z;
1233:				go->std = V4L2_STD_PAL;
1234:				strscpy(go->name, "Plextor PX-TV402U-EU",
1235:					sizeof(go->name));
1236:				break;
1237:			case 2:
1238:				go->tuner_type = TUNER_SONY_BTF_PK467Z;
1239:				go->std = V4L2_STD_NTSC_M_JP;
1240:				num_i2c_devs -= 2;
1241:				strscpy(go->name, "Plextor PX-TV402U-JP",
1242:					sizeof(go->name));
1243:				break;
1244:			case 3:
1245:				go->tuner_type = TUNER_SONY_BTF_PB463Z;
1246:				num_i2c_devs -= 2;
1247:				strscpy(go->name, "Plextor PX-TV402U-NA",
1248:					sizeof(go->name));
1249:				break;
1250:			default:
1251:				pr_debug("unable to detect tuner type!\n");
1252:				break;
1253:			}
1254:			/* Configure tuner mode selection inputs connected
1255:			 * to the EZ-USB GPIO output pins */
1256:			if (go7007_usb_vendor_request(go, 0x40, 0x7f02, 0,
1257:						NULL, 0, 0) < 0) {
1258:				dev_err(go->dev, "GPIO write failed!\n");
1259:				goto allocfail;
1260:			}
1261:		}
1262:	
1263:		/* Print a nasty message if the user attempts to use a USB2.0 device in
1264:		 * a USB1.1 port.  There will be silent corruption of the stream. */
1265:		if ((board->flags & GO7007_USB_EZUSB) &&
1266:				usbdev->speed != USB_SPEED_HIGH)
1267:			dev_err(go->dev, "*** WARNING ***  This device must be connected to a USB 2.0 port! Attempting to capture video through a USB 1.1 port will result in stream corruption, even at low bitrates!\n");
1268:	
1269:		/* Allocate the URBs and buffers for receiving the video stream */
1270:		if (board->flags & GO7007_USB_EZUSB) {
1271:			if (!usb->usbdev->ep_in[6])
1272:				goto allocfail;
1273:			v_urb_len = 1024;
1274:			video_pipe = usb_rcvbulkpipe(usb->usbdev, 6);
1275:		} else {
1276:			if (!usb->usbdev->ep_in[1])
1277:				goto allocfail;
1278:			v_urb_len = 512;
1279:			video_pipe = usb_rcvbulkpipe(usb->usbdev, 1);
1280:		}
1281:		for (i = 0; i < 8; ++i) {
1282:			usb->video_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
1283:			if (usb->video_urbs[i] == NULL)
1284:				goto allocfail;
1285:			usb->video_urbs[i]->transfer_buffer =
1286:							kmalloc(v_urb_len, GFP_KERNEL);
1287:			if (usb->video_urbs[i]->transfer_buffer == NULL)
1288:				goto allocfail;
1289:			usb_fill_bulk_urb(usb->video_urbs[i], usb->usbdev, video_pipe,
1290:					usb->video_urbs[i]->transfer_buffer, v_urb_len,
1291:					go7007_usb_read_video_pipe_complete, go);
1292:		}
1293:	
1294:		/* Allocate the URBs and buffers for receiving the audio stream */
1295:		if ((board->flags & GO7007_USB_EZUSB) &&
1296:		    (board->main_info.flags & GO7007_BOARD_HAS_AUDIO)) {
1297:			if (!usb->usbdev->ep_in[8])
1298:				goto allocfail;
1299:			for (i = 0; i < 8; ++i) {
]

217/2 2026/07/30 12:43 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 120336
							output: 683
							thoughts: 913
						

Thoughts:
**Debugging a USB Connection with Syzkaller**

Okay, so I'm diving into this `go7007` issue and it looks like it's connected to `0x0eb1:0x7007`. The goal is to figure out how to use `syz_usb_connect` with custom `idVendor` and `idProduct` values. I already know that I can pass a `usb_device_descriptor` struct to achieve this.

The immediate problem is an error: `"wrong array arg *prog.BufferType"`. It seems I'm passing a buffer when an array is required. Let me check the definition of `usb_interface_descriptor` for clues.

```
usb_interface_descriptor {
	inner	usb_interface_descriptor_eps_array_t[int8, int8, const[0, int8], const[0, int8], const[0, int8], array[usb_interface_extra_descriptor, 0:2], array[usb_endpoint_descriptor, 0:16]]
} [packed]
```

Alright, the `inner` field uses `usb_interface_descriptor_eps_array_t`, which in turn contains a struct with 11 fields. Now, `extra` is an `array[usb_interface_extra_descriptor, 0:2]` and `endpoints` is `array[usb_endpoint_descriptor, 0:16]`. My initial instinct was that passing empty arrays `[]` for both `extra` and `endpoints` would satisfy the requirement.

But the error persists. Let me examine the problematic line of code within the `syz_usb_connect` call. The problematic segment seems to be the `interfaces` array. Now, the key is this - `interfaces` is `array[usb_interface_descriptor, 1:4]`. The error traces back to where I'm passing `[{{0, 0, 0, 0, 0, 3, 0, 0, 0, [], []}}]`.

Aha! `usb_interface_descriptor` is a struct, but with only one member called `inner`! So, the corrected format to pass should be `[{inner={0, 0, 0, 0, 0, 0, 0, 0, 0, [], []}}]`. Let's give that a shot and see if this solves the `wrong array arg` error.



218/2 2026/07/30 12:43 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={@inner={0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, 0, [@inner={0, 0, 0, 0, 0, 0, 0x80, 0, [@inner={0, 0, 0, 0, 0, 0, 0, 0, 0, [], []}]}]}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

219/2 2026/07/30 12:43 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 122708
							output: 678
							thoughts: 203
						

Thoughts:
**Debugging USB Device Descriptor Initialization**

Okay, so I was looking at this `usb_device_descriptor` and I jumped to a conclusion based on potentially incomplete information. I see it's *not* a union, but rather a struct. That's a fundamental misunderstanding on my part – this will impact how I should be looking at the structure. This changes how I interpret the memory layout and field access.

Therefore, the correct initialization should not be based on an assumption of a union structure. I need to make sure I am using the struct-specific initialization pattern and have the array type initialization correct. I am getting something of a default initialization of sorts: `&AUTO={{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, 0, [{{0, 0, 0, 0, 0, 0, 0x80, 0, [{{0, 0, 0, 0, 0, 0, 0, 0, 0, [], []}}]}}]}}`. This is now my baseline to assess.



220/2 2026/07/30 12:43 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, 0, [{{0, 0, 0, 0, 0, 0, 0x80, 0, [{{0, 0, 0, 0, 0, 0, 0, 0, 0, [], []}}]}}]}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

221/2 2026/07/30 12:43 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 124031
							output: 679
							thoughts: 1870
						

Thoughts:
**Debugging a Syzkaller USB Descriptor**

Okay, let's break this down. I'm looking at the definition of `usb_config_descriptor` and I see it contains `usb_config_descriptor_ifaces_array_t`, which in turn contains `usb_config_descriptor_t`. Further down, I see `usb_config_descriptor_t` which is defined using `usb_config_descriptor_verbose_t`.  Tracing it through, this ultimately means the Syzkaller description I have should be aligned with the fields within `usb_config_descriptor_verbose_t`.

I've got a struct literal, and I have to make sure the field count is accurate. Looking at `usb_config_descriptor_verbose_t`, I've identified the fields: `bLength`, `bDescriptorType`, `wTotalLength`, `bNumInterfaces`, `bConfigurationValue`, `iConfiguration`, `bmAttributes`, `bMaxPower`, `extra` and `interfaces`. However, I need to take into account that `extra` is `void`, which is omitted in the struct literal. So that means the `interfaces` field is the 9th, and *last* field, not the 8th. I see I've provided 9 fields in my input, but the format is throwing me off, specifically, `{{0, 0, 0, 0, 0, 0, 0x80, 0, [{{0, 0, 0, 0, 0, 0, 0, 0, 0, [], []}}]}}`.

I'm getting a "wrong array arg *prog.BufferType" error, so I need to go deeper.  Let's look at `usb_interface_descriptor_verbose_t`. It also has `extra` and `endpoints` which are arrays.  This gives me a hint, so I can try to understand `usb_interface_descriptor`.  Now I am looking at `usb_interface_descriptor` itself. The definition tells me that is composed of a single field `inner` of type `usb_interface_descriptor_eps_array_t`.

`usb_interface_descriptor_eps_array_t` then expands to `usb_interface_descriptor_t`, ultimately linking back to `usb_interface_descriptor_verbose_t` which defines the fields within the `usb_interface_descriptor`. Looking closer, the fields are: `bLength`, `bDescriptorType`, `bInterfaceNumber`, `bAlternateSetting`, `bNumEndpoints`, `bInterfaceClass`, `bInterfaceSubClass`, `bInterfaceProtocol`, `iInterface`, `extra`, and `endpoints`. So, that struct also has 11 fields. Now, I see the light, `usb_config_descriptor` has an array of `usb_interface_descriptor`.

So, the problem is with the way I'm defining the `interfaces` array within the `usb_config_descriptor`. Because `usb_interface_descriptor` contains an inner struct, and that has 11 fields, my literal should be an array of structs where each item is also a nested struct. The error message is correct, the compiler expects a struct, or rather the nested structure within, as the `interfaces` contains the `usb_interface_descriptor` data. The literal needs to be structured properly to reflect this nesting.

I'm going to correct the array of `usb_interface_descriptor` entries, so that each item is structured as a nested struct:  `[{{{0, 0, 0, 0, 0, 0, 0, 0, 0, [], []}}}]`.



222/2 2026/07/30 12:44 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, 0, [{{0, 0, 0, 0, 0, 0, 0x80, 0, [{{{0, 0, 0, 0, 0, 0, 0, 0, 0, [], []}}}]}}]}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

223/2 2026/07/30 12:44 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 127548
							output: 680
							thoughts: 623
						

Thoughts:
**Debugging a USB Configuration Descriptor**

Okay, let's break this down. It looks like I'm wrestling with how `usb_config_descriptor` is being represented and initialized. I'm seeing that `usb_config_descriptor` is a struct, and I'm pretty sure it's got a single field called `inner`, which itself seems to be a struct containing 9 fields. My initial thought was that a complete initialization would look something like `{{0, 0, 0, 0, 0, 0, 0x80, 0, [...]}}`.

I'm using `configs` as an array of `usb_config_descriptor`, and `interfaces` as an array of `usb_interface_descriptor`, so I was expecting this nested structure, with `interfaces` having a specific format: `[{{{0, 0, 0, 0, 0, 0, 0, 0, 0, [], []}}}]`. But I'm getting an error, and the error points to the `interfaces` array.

Now I'm looking closely at the descriptor structure. There's a `usb_config_descriptor_t` and it has a field called `EXTRA` that is defined as `void`. I know `void` means a type with static size zero, and usually it's used within templates or varlen unions. But I'm unsure if it plays a part in the struct literal. Does a struct in syzkaller include a `void` field? Will it appear as `{}` or simply be omitted?

The critical part is the ordering. If `void` is omitted, the `interfaces` field is the ninth field. If `void` is *not* omitted, it takes up the ninth position, and the `interfaces` array is the tenth.

So, I'm going to test the hypothesis that providing `{}` for `extra` will solve the problem. Let's see if this revised literal, `[{{0, 0, 0, 0, 0, 0, 0x80, 0, {}, [{{{0, 0, 0, 0, 0, 0, 0, 0, 0, [], []}}}]}}]`, does the trick.



224/2 2026/07/30 12:44 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, 0, [{{0, 0, 0, 0, 0, 0, 0x80, 0, {}, [{{{0, 0, 0, 0, 0, 0, 0, 0, 0, [], []}}}]}}]}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

225/2 2026/07/30 12:44 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 129518
							output: 666
							thoughts: 1817
						

Thoughts:
**Debugging Syzkaller Struct Literals for USB Descriptors**

Okay, so I'm seeing this "wrong struct arg for void" error, and it's throwing me for a loop. Clearly, `void` doesn't take `{}`. The question then becomes, what does `void` actually *do*? I suspect it's omitted entirely. But if that's the case, then fields in my struct are going to be misaligned. In this instance, the `interfaces` field is coming in as field nine. I tried to provide an argument for the field, but it was incorrect. The problem has to do with understanding how `len` and `const` fields work in syzkaller.

Let me break this down using the `usb_config_descriptor` and the other associated structs. Looking at `usb_config_descriptor`, there is a nested structure `usb_config_descriptor_verbose_t`.  Inside that structure, `bNumInterfaces` is defined as `IFSNUM`, which is `len[interfaces, int8]`. It now makes sense! `bNumInterfaces` is a `len` field, so it is automatically computed and omitted from the struct literal, which means I should not provide an argument for it. Similarly, `wTotalLength` is another `len` field, and it also is omitted. Now I understand!

I need to figure out which fields in the structure take values and which are omitted. I know that `const` fields *do* take values.

Looking at `usb_config_descriptor_verbose_t`, the fields that take a value are: `bLength`, `bDescriptorType`, `bConfigurationValue`, `iConfiguration`, `bmAttributes`, `bMaxPower`, and `interfaces`. That's seven fields. Now let's look at `usb_device_descriptor_verbose_t`: this one has `bNumConfigurations`, which is `len`, so it is omitted. This structure has fourteen fields. Finally, I will look at `usb_interface_descriptor_verbose_t`: Here, `bNumEndpoints` is also a `len` field that will be omitted. The fields that take a value are: `bLength`, `bDescriptorType`, `bInterfaceNumber`, `bAlternateSetting`, `bInterfaceClass`, `bInterfaceSubClass`, `bInterfaceProtocol`, `iInterface`, `extra`, and `endpoints`. So, 10 fields!

With a better understanding of what fields are included and omitted, let me construct the struct literals!
*   `usb_device_descriptor`: I'm thinking this one will be `{{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, [CONFIG]}}` which gives me 14 fields.
*   `CONFIG`: `{{0, 0, 0, 0, 0x80, 0, [INTERFACE]}}` - a total of 7 fields.
*   `INTERFACE`: I should have this as `{{0, 0, 0, 0, 3, 0, 0, 0, [], []}}` which will yield 10 fields.

Okay, let's give it a try and see if I've finally cracked this!



226/2 2026/07/30 12:45 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, [{{0, 0, 0, 0, 0x80, 0, [{{0, 0, 0, 0, 3, 0, 0, 0, [], []}}]}}]}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

227/2 2026/07/30 12:45 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 132894
							output: 674
							thoughts: 1193
						

Thoughts:
**Debugging a Syzkaller Descriptor**

Okay, first things first, that "wrong array arg" error is throwing me off. Ah, right, `bNumConfigurations` is a `len` field, determined by the size of the `configs` array. Now, I have to remember, Syzkaller *doesn't* omit `len` fields in its syntax, they're represented as `AUTO`!

Right, I've used `AUTO` before, but got a "wrong type" error. This means `AUTO` isn't compatible with `IntType`. But, if `len` fields are of `LenType`, maybe `AUTO` works for *that*! Let's check my previous attempt: the problem was definitely with `AUTO`, so I'll try to understand where it was going wrong.

The error message pointed out that I used `AUTO` with `IntType`. So, which field was an `IntType`? `bLength`, `bDescriptorType`, `bDeviceClass`, `bDeviceSubClass`, `bDeviceProtocol`, `bcdDevice`, `iManufacturer`, `iProduct`, and `iSerialNumber` are all `const` fields and, therefore, of `ConstType`.

So, does `AUTO` work for `ConstType`? Wait, I think I tried `0` for `ConstType` before, and that worked!

Okay, let's break down the structure of `usb_device_descriptor_verbose_t`. I'll go through the fields one by one:

1.  `bLength` (ConstType) - `0`
2.  `bDescriptorType` (ConstType) - `0`
3.  `bcdUSB` (FlagsType) - `0x200`
4.  `bDeviceClass` (ConstType) - `0`
5.  `bDeviceSubClass` (ConstType) - `0`
6.  `bDeviceProtocol` (ConstType) - `0`
7.  `bMaxPacketSize0` (FlagsType) - `64`
8.  `idVendor` (ConstType) - `0x10c4`
9.  `idProduct` (ConstType) - `0x8244`
10. `bcdDevice` (ConstType) - `0`
11. `iManufacturer` (ConstType) - `0`
12. `iProduct` (ConstType) - `0`
13. `iSerialNumber` (ConstType) - `0`
14. `bNumConfigurations` (LenType) - `AUTO`
15. `configs` (ArrayType) - `[CONFIG]`

Now, each `CONFIG` is:

1.  `bLength` (ConstType) - `0`
2.  `bDescriptorType` (ConstType) - `0`
3.  `wTotalLength` (LenType) - `AUTO`
4.  `bNumInterfaces` (LenType) - `AUTO`
5.  `bConfigurationValue` (IntType) - `0`
6.  `iConfiguration` (IntType) - `0`
7.  `bmAttributes` (FlagsType) - `0x80`
8.  `bMaxPower` (IntType) - `0`
9.  `extra` (VoidType) - Omitted!
10. `interfaces` (ArrayType) - `[INTERFACE]`

So, `extra` is `void`, that's what makes it omitted. I'll remember this, so that's nine fields for the `CONFIG` struct.

Finally, `INTERFACE` looks like:

1.  `bLength` (ConstType) - `0`
2.  `bDescriptorType` (ConstType) - `0`
3.  `bInterfaceNumber` (IntType) - `0`
4.  `bAlternateSetting` (IntType) - `0`
5.  `bNumEndpoints` (LenType) - `AUTO`
6.  `bInterfaceClass` (ConstType) - `3`
7.  `bInterfaceSubClass` (ConstType) - `0`
8.  `bInterfaceProtocol` (ConstType) - `0`
9.  `iInterface` (IntType) - `0`
10. `extra` (ArrayType) - `[]`
11. `endpoints` (ArrayType) - `[]`

Alright, let's give this a shot!



228/2 2026/07/30 12:45 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, AUTO, [{{0, 0, AUTO, AUTO, 0, 0, 0x80, 0, [{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}]}}]}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

229/2 2026/07/30 12:45 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 135937
							output: 675
							thoughts: 115
						

Thoughts:
**Decoding this USB Descriptor Structure**

Okay, so I'm looking at this `interfaces` field, and it's defined as an `array[usb_interface_descriptor, 1:4]`. Right, so it's an array of USB interface descriptors, up to four of them. Now, the crucial part is that `usb_interface_descriptor` itself is defined as a struct, but with only *one* field, which is `inner`. Therefore, when I try to parse this data, it should look something like this: `[{inner={0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}]`. My immediate thought is, let me try and apply this nested structure explicitly. So, given that `inner` is the sole member of `usb_interface_descriptor`, I believe the correct form to try is `[{{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}}]`. That should give me the correct interpretation.



230/2 2026/07/30 12:45 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, AUTO, [{{0, 0, AUTO, AUTO, 0, 0, 0x80, 0, [{{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}}]}}]}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

231/2 2026/07/30 12:45 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 137129
							output: 674
							thoughts: 1214
						

Thoughts:
**Deconstructing the USB Configuration Descriptor**

Okay, let's break this down systematically. I'm focusing on constructing the `usb_config_descriptor` structure.  First, the definition: `usb_config_descriptor` has one field, `inner`.  Therefore, when I'm looking at the `CONFIG` part, it should translate to something like `{{...}}`.  Specifically, `CONFIG` represents `{inner={...}}`.

Now, digging into the `usb_config_descriptor_ifaces_array_t` type, it seems to be built on top of `usb_config_descriptor_t`, which in turn depends on `usb_config_descriptor_verbose_t`.  Looking at `usb_config_descriptor_verbose_t`, I see that it includes an `extra` field, which can be `void`, meaning it's potentially omitted. This is the key.  If `extra` is omitted, then the `interfaces` field *becomes* the 9th field in the structure, not the 10th.  This is critical.

So, `usb_config_descriptor_verbose_t` has 10 fields (or 9 if `extra` is omitted), so the ninth element will be the `interfaces` array.

Now let's consider the device descriptor, and the `configs` field.  `usb_device_descriptor_verbose_t` has a `configs` field, and `configs` is an array of `usb_config_descriptor`. Since a `usb_config_descriptor` is `{inner}`, the `configs` should be `[{inner}]`.  This means `configs` will be an array of `usb_config_descriptor`. Thus, `configs` should be `[{{...}}]`.

The `inner` of `usb_config_descriptor` contains all the elements: `bLength, bDescriptorType, wTotalLength, bNumInterfaces, bConfigurationValue, iConfiguration, bmAttributes, bMaxPower, interfaces`.  So `configs` should be something like `[{{bLength, ...}}]`.

The `interfaces` is an array of `usb_interface_descriptor`s. And each `usb_interface_descriptor` contains an `inner` field.  Therefore, this means `interfaces` becomes `[{inner}]`. Where `inner` represents `bLength, bDescriptorType, bInterfaceNumber, bAlternateSetting, bNumEndpoints, bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol, iInterface, extra, endpoints`.  So `interfaces` is `[{{bLength, ...}}]`.

Let's double-check the brace counts and structure again: `configs = [{{0, 0, AUTO, AUTO, 0, 0, 0x80, 0, [{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}]}}]`.  Now that I've reviewed the structural components and the relationship between each element of this configuration, I'm ready to write that structure exactly.



232/2 2026/07/30 12:45 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, AUTO, [{{0, 0, AUTO, AUTO, 0, 0, 0x80, 0, [{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}]}}]}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

233/2 2026/07/30 12:45 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 139844
							output: 666
							thoughts: 1656
						

Thoughts:
**Debugging USB Descriptor Structures**

Okay, here's the breakdown of my thought process. I'm hitting a "wrong array arg" error when dealing with USB descriptors, specifically related to the `interfaces` field. The error suggests it's expecting a byte array (`BufferType`), but I'm giving it an array of structs. That's the core issue.

First, I need to understand what `interfaces` *actually* is within the structure. I know `usb_config_descriptor_verbose_t` uses `IFS` for `interfaces`, so let's trace that. Looking at the definition, `IFS` resolves to `array[usb_interface_descriptor, 1:4]`, which is, indeed, an array of `usb_interface_descriptor` structs. So, the original error is misleading.

The problem likely lies elsewhere.  Let's consider that the `extra` field, which I thought was omitted, might not be. If not omitted it is parsed as `extra` or parsed as `void`. The struct definition in `usb_config_descriptor` has an `extra` field that's `void`. If not omitted, `extra` doesn't take up any fields, so there's really no effect.

I need to confirm the field order and what's omitted by syzkaller. I need to count the fields in `usb_config_descriptor_verbose_t`. Counting each field, taking into account which ones are `len` fields (omitted in syzkaller), shows that there are only 7 fields that should be populated: `bLength`, `bDescriptorType`, `bConfigurationValue`, `iConfiguration`, `bmAttributes`, `bMaxPower`, and `interfaces`.

Looking back at my code, I was providing 9 fields when the length field was being omitted, because I used `AUTO` to define the `len` fields. I have to remove the `AUTO` entries for those omitted length fields, and my values should be: `{{0, 0, 0, 0, 0x80, 0, [{{...}}]}}`.

Now, let's make sure I didn't make the same mistake elsewhere. I need to make sure `usb_device_descriptor_verbose_t` also doesn't contain the mistake I just caught in `usb_config_descriptor_verbose_t`. Counting all the fields and omitting the fields that are of `len` type confirms I only need to supply 14 fields, and I had 15, because I set `AUTO` on the length field, so that needs to be removed.

Finally, I need to check `usb_interface_descriptor_verbose_t` to be sure I am correct, which contains 10 fields and I have 11 fields because of another `AUTO` length field, so I should be at `{{0, 0, 0, 0, 3, 0, 0, 0, [], []}}`.

With the corrected number of fields in each descriptor, the structs should now be defined as follows: `INTERFACE` is `{{0, 0, 0, 0, 3, 0, 0, 0, [], []}}`, `CONFIG` is `{{0, 0, 0, 0, 0x80, 0, [INTERFACE]}}`, and `DEVICE` is `{{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, [CONFIG]}}`. Let's give this a try and see if it works.



234/2 2026/07/30 12:46 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, [{{0, 0, 0, 0, 0x80, 0, [{{0, 0, 0, 0, 3, 0, 0, 0, [], []}}]}}]}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

235/2 2026/07/30 12:46 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 143129
							output: 674
							thoughts: 983
						

Thoughts:
**Debugging USB Descriptor Generation**

Okay, hold on. That initial error, `wrong array arg *prog.LenType`, immediately points to a problem with field 14 – which is actually a `LenType`. Aha! This means `bNumConfigurations` isn't omitted! I was wrong to assume that. If it's *not* omitted, I *must* provide `AUTO` for it. But wait... when I *did* provide `AUTO` earlier, the error was "wrong type *prog.IntType for AUTO"! I need to re-examine that specific error message.

Okay, let's look at the failing line: `r0 = syz_usb_connect(3, 0, &AUTO={{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, 0, [{{0, 0, 0, 0, 0, 0, 0x80, 0, [<<<!!ERROR!!>>>]}}]}}, 0)`. The error isn't at the `AUTO` *itself* but in the array. It's actually: `wrong type *prog.IntType for AUTO` at the nested array part of `bConfigurationValue`! I was accidentally inputting the wrong type for *that* field and the debugger was complaining about it!

Let me check again: the error is at `&AUTO={{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, AUTO, [{{0, 0, AUTO, AUTO, 0, 0, 0x80, 0, [{{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}}]}}]}}`. Now I see it. The error is `wrong array arg *prog.BufferType` within the innermost structure: `{{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}}`.

I need to map this back to the correct fields. If the `len` fields are *not* omitted, then the `usb_device_descriptor_verbose_t` has 15 fields. `usb_config_descriptor_verbose_t` has 10 fields (assuming `extra` is omitted), and `usb_interface_descriptor_verbose_t` has 11 fields. Now, I have a clear plan. I'll provide `AUTO` for all `len` fields, and `0` for all `const` and `int` fields:

For the `DEVICE` descriptor:
*   `bLength = 0`
*   `bDescriptorType = 0`
*   `bcdUSB = 0x200`
*   `bDeviceClass = 0`
*   `bDeviceSubClass = 0`
*   `bDeviceProtocol = 0`
*   `bMaxPacketSize0 = 64`
*   `idVendor = 0x10c4`
*   `idProduct = 0x8244`
*   `bcdDevice = 0`
*   `iManufacturer = 0`
*   `iProduct = 0`
*   `iSerialNumber = 0`
*   `bNumConfigurations = AUTO`
*   `configs = [CONFIG]`

For the `CONFIG` descriptor:
*   `bLength = 0`
*   `bDescriptorType = 0`
*   `wTotalLength = AUTO`
*   `bNumInterfaces = AUTO`
*   `bConfigurationValue = 0`
*   `iConfiguration = 0`
*   `bmAttributes = 0x80`
*   `bMaxPower = 0`
*   `interfaces = [INTERFACE]` (with the assumption `extra` is omitted)

For the `INTERFACE` descriptor:
*   `bLength = 0`
*   `bDescriptorType = 0`
*   `bInterfaceNumber = 0`
*   `bAlternateSetting = 0`
*   `bNumEndpoints = AUTO`
*   `bInterfaceClass = 3`
*   `bInterfaceSubClass = 0`
*   `bInterfaceProtocol = 0`
*   `iInterface = 0


236/2 2026/07/30 12:46 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, AUTO, [{{0, 0, AUTO, AUTO, 0, 0, 0x80, 0, [{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}]}}]}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

237/2 2026/07/30 12:46 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 145981
							output: 675
							thoughts: 578
						

Thoughts:
**Debugging a `BufferType` Mismatch**

Okay, so I'm getting a "wrong array arg" error related to `prog.BufferType` at this specific array: `[{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}]`. My initial thought is that the code expects a `BufferType` for the `interfaces` argument. But wait, `interfaces` is actually of type `IFS`, not a direct `BufferType`. What *is* `IFS`? Let's trace this.

`usb_config_descriptor_t` uses `usb_config_descriptor_verbose_t`, which in turn involves `IFS`. Okay. Then `usb_config_descriptor` itself employs `usb_config_descriptor_ifaces_array_t`. That holds an array of `usb_interface_descriptor` instances, with size 1 to 4. Therefore, `IFS` *is* this array of `usb_interface_descriptor`s. And looking at the definition of `usb_interface_descriptor`, it's a struct with only one field, called `inner`.

So, `INTERFACE` should be `{inner={...}}`. And based on the provided array, `[INTERFACE]` should indeed look like `[{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}]`. Hang on a second... I *did* provide that! That's the array I'm passing!

Aha! Now I see. The problem is that the given array `{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}` actually contains 11 fields, but the `usb_interface_descriptor` structure has only a single field named `inner`. The provided array, as a whole, is a representation of the *inner* field, of the `usb_interface_descriptor` structure. Therefore, the format I've provided is incorrect. It should be a single structure, with a single member that looks like the given array: `{{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}}`. It's a structure with a structure containing the 11-field array.

Let me try that and see if it fixes the problem.



238/2 2026/07/30 12:46 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, AUTO, [{{0, 0, AUTO, AUTO, 0, 0, 0x80, 0, [{{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}}]}}]}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

239/2 2026/07/30 12:46 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 147927
							output: 667
							thoughts: 1072
						

Thoughts:
**Debugging USB Descriptor Structures**

Okay, here's what's running through my mind as I troubleshoot this descriptor parsing issue. I've encountered this error again using `[{{{...}}}]` -- darn! I need to dig deeper. I need to understand why my descriptor structures aren't being interpreted correctly.

First, let me re-examine `usb_config_descriptor_verbose_t`. I'm going through the field definitions:

```c
type usb_config_descriptor_verbose_t[NUM, IFSNUM, ICONFIG, ATTRS, POWER, EXTRA, IFS] {
	bLength			const[USB_DT_CONFIG_SIZE, int8]
	bDescriptorType		const[USB_DT_CONFIG, int8]

	wTotalLength		len[parent, int16]
	bNumInterfaces		IFSNUM
	bConfigurationValue	NUM
	iConfiguration		ICONFIG
	bmAttributes		ATTRS
	bMaxPower		POWER

	extra			EXTRA
	interfaces		IFS
} [packed]
```

Alright, `EXTRA` being `void` means it is omitted, so the key takeaway is that the `interfaces` field is the 9th field. However, `wTotalLength` is a `len` field, so it is omitted from the input structure. Similarly, `bNumInterfaces` is also a `len` field and is omitted.

This means the actual fields are:
1.  `bLength`
2.  `bDescriptorType`
3.  `bConfigurationValue`
4.  `iConfiguration`
5.  `bmAttributes`
6.  `bMaxPower`
7.  `interfaces`

I had counted 7 fields! But I provided 9 fields: `0, 0, AUTO, AUTO, 0, 0, 0x80, 0, [INTERFACE]`. The `AUTO` fields are the problem. They correspond to the omitted `wTotalLength` and `bNumInterfaces`. I need to remove those `AUTO` values! So the correct format for the CONFIG descriptor should be `{{0, 0, 0, 0, 0x80, 0, [INTERFACE]}}`.

Now, let's double-check the `usb_device_descriptor_verbose_t` structure. Looking at the fields:
1.  `bLength`
2.  `bDescriptorType`
3.  `bcdUSB`
4.  `bDeviceClass`
5.  `bDeviceSubClass`
6.  `bDeviceProtocol`
7.  `bMaxPacketSize0`
8.  `idVendor`
9.  `idProduct`
10. `bcdDevice`
11. `iManufacturer`
12. `iProduct`
13. `iSerialNumber`
14. `configs`

Ah, `bNumConfigurations` is again a `len` field and omitted. So there are indeed 14 fields. I provided 15 fields, with `AUTO` for `bNumConfigurations`, so I need to remove that `AUTO` field.

Finally, `usb_interface_descriptor_verbose_t`:
1.  `bLength`
2.  `bDescriptorType`
3.  `bInterfaceNumber`
4.  `bAlternateSetting`
5.  `bInterfaceClass`
6.  `bInterfaceSubClass`
7.  `bInterfaceProtocol`
8.  `iInterface`
9.  `extra`
10. `endpoints`

This has 10 fields and I incorrectly provided 11 fields. `bNumEndpoints` is a `len` field and is omitted as well. So, I must remove the `AUTO` value for it too.

Okay, let's assemble the correct descriptor strings based on this.

*   `DEVICE`: `{{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, [CONFIG]}}` (14 fields)
*   `CONFIG`: `{{0, 0, 0, 0, 0x80, 0, [INTERFACE]}}` (7 fields)
*   `INTERFACE`: `{{{0, 0, 0, 0, 3, 0, 0, 0, [], []}}}` (10 fields inside `inner`)

I'm confident this is correct. I will try this!



240/2 2026/07/30 12:47 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, [{{0, 0, 0, 0, 0x80, 0, [{{{0, 0, 0, 0, 3, 0, 0, 0, [], []}}}]}}]}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

241/2 2026/07/30 12:47 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 150844
							output: 674
							thoughts: 1565
						

Thoughts:
**Debugging USB Configuration Descriptor Handling**

Okay, first things first, I see this "wrong array arg *prog.LenType" error. That means the `LenType` field is definitely present. So, the `len` fields are *not* omitted, which means I *must* supply a value for them. But when I tried `AUTO`, it complained about the wrong type. 

Let's revisit the error when I used `AUTO` for `bNumConfigurations`. The error specifically pinpoints the issue here: `[{{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}}]`. Interestingly, `AUTO` for `bNumConfigurations` *did* work. The error is located within this nested structure. The key is that `AUTO` seems fine for the configuration count itself.

Why is it complaining about `*prog.BufferType`? Because `interfaces` is the 9th field, after `extra`. Now, if `extra` is `void`, does it even take a field? If it does not, `interfaces` *is* the 9th field. I provided a value for `interfaces` in my initial input. My input looked like this: `[{{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}}]`. But, the error persists!

Could it be that the `void` for `extra` means the field is omitted, and that the `interfaces` field is, in fact, not a `BufferType`? But, if `EXTRA` is `void`, it might mean `BufferType` is expected. No, void is static size 0.

Let's look at `usb_config_descriptor_verbose_t` again. If `extra` is `void`, then the type is omitted. So `IFS` is `array[usb_interface_descriptor, 1:4]`. The problem is that the tool reports a *BufferType* mismatch for the array. Okay, let's step back and look at the types again: the `usb_config_descriptor` has `inner	usb_config_descriptor_ifaces_array_t`. `usb_config_descriptor_ifaces_array_t` then contains `usb_interface_descriptor`.

Now I need to understand what `usb_interface_descriptor` actually *is*. Aha! It's a structure with a single field called `inner`. Okay, so `usb_interface_descriptor` is `{inner}`. This means the array is `[{inner}]`. Since `inner` is a struct, its members include `bLength`. Therefore, the array is `[{{bLength, ...}}]`.

Let's count again. It seems I provided `[{{{bLength, ...}}}]`. That's one set of extra braces! In syzkaller, array of structs is declared like this: `[{field1, field2}, {field1, field2}]`. So my array should have been `[{{inner}}]`. The inner has members such as `bLength`. Therefore `interfaces` should be `[{{bLength, ...}}]`. I mistakenly added one set of extra braces! Let's try removing them!



242/2 2026/07/30 12:47 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, AUTO, [{{0, 0, AUTO, AUTO, 0, 0, 0x80, 0, [{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}]}}]}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

243/2 2026/07/30 12:47 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 153917
							output: 675
							thoughts: 784
						

Thoughts:
**Debugging a Structure Parsing Error**

Okay, so I got this `wrong array arg *prog.BufferType` error, and my initial thought was that the issue was with how I was handling the `interfaces` array, which I'm defining as `[{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}]`. But I need to think this through a bit more methodically. If that array is causing a `BufferType` error, then clearly `interfaces` isn't a simple array of structs like I initially assumed.

I need to reconsider the role of `extra` here. If `extra` isn't omitted, then it occupies the 9th field, and `interfaces` is the 10th. And `extra` is defined as `void`. But a `void` doesn't take a value, so what's going on here? If I feed in the array where I expect the `void` to be, it's attempting to parse that array as the `void` field, and it's choking on it since `void` is a type with a static size of 0.

Let's look more closely at the struct definitions. Ah, `usb_config_descriptor_verbose_t` has `interfaces` defined as `IFS`, and let's go with the assumption that `IFS` is `BufferType`. What is `usb_config_descriptor_ifaces_array_t`? 

```
usb_config_descriptor_ifaces_array_t[NUM, IFS] usb_config_descriptor_t[NUM, len[interfaces, int8], IFS]
```

and `usb_config_descriptor` is:

```
inner	usb_config_descriptor_ifaces_array_t[int8, array[usb_interface_descriptor, 1:4]]
```

So it looks like `IFS` is `array[usb_interface_descriptor, 1:4]`. Okay, so `interfaces` is an array of `usb_interface_descriptor`. But that shouldn't cause this error. 

Now, wait a minute! Could this `wrong array arg *prog.BufferType` *not* be about `interfaces` at all? Is it about `configs` in `usb_device_descriptor_verbose_t`? No, the error clearly points to the problematic `interfaces` data. Okay, back on track, then.

Perhaps if `extra` is `void` and it IS somehow parsed as `BufferType`. No, `void` is `void`. That doesn't make any sense.

Let me go back and re-check `usb_config_descriptor_t`:

```
usb_config_descriptor_t[NUM, IFSNUM, IFS] usb_config_descriptor_verbose_t[NUM, IFSNUM, int8, flags[usb_config_attributes, int8], int8, void, IFS]
```

Yes, `EXTRA` is indeed `void`. So, if `void` might be represented as `""` (empty string). Let's try `"", [{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}]`! That might just work.



244/2 2026/07/30 12:47 tool reproduce-crash
2m Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, AUTO, [{{0, 0, AUTO, AUTO, 0, 0, 0x80, 0, "", [{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}]}}]}}, 0)
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID:repro/67137852399770c652e691f9d4806cf4f88259e0 ReproducedBugTitle: ReproducedCrashReport:]

245/2 2026/07/30 12:49 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 156165
							output: 61
							thoughts: 34
						

Thoughts:
**A Moment of Triumph and Quick Assessment**

Yes! Finally, that worked! I knew `""` was the correct string representation for `void` in this context. It's satisfying to see it click after all the testing.

Hmm, but wait... it didn't crash, which is good, but it's not the primary goal. I suppose that's a positive, but I'm more interested in seeing a clear indication that it's doing the right thing.

Right, time to check the coverage and verify that the test case is firing as I'd expect. Make sure the logic is getting exercised properly by this fix. A successful outcome will need to be verified.



246/2 2026/07/30 12:50 tool get-coverage-files
0m Args:
map[ExecutionCachedID:repro/67137852399770c652e691f9d4806cf4f88259e0]

Results:
map[Files:[arch/x86/entry/vsyscall/vsyscall_64.c arch/x86/include/asm/atomic64_64.h arch/x86/include/asm/bitops.h arch/x86/include/asm/compat.h arch/x86/include/asm/cpufeature.h arch/x86/include/asm/irqflags.h arch/x86/include/asm/jump_label.h arch/x86/include/asm/mmu_context.h arch/x86/include/asm/page.h arch/x86/include/asm/pgtable.h arch/x86/include/asm/pkru.h arch/x86/include/asm/preempt.h arch/x86/include/asm/trace/fpu.h arch/x86/kernel/cpu/aperfmperf.c arch/x86/kernel/fpu/context.h arch/x86/kernel/fpu/core.c arch/x86/kernel/fpu/internal.h arch/x86/kernel/fpu/xstate.c arch/x86/kernel/tsc.c arch/x86/mm/fault.c arch/x86/mm/maccess.c arch/x86/mm/pgtable.c arch/x86/pci/common.c arch/x86/pci/direct.c block/blk-cgroup.c drivers/acpi/acpica/nsaccess.c drivers/acpi/acpica/nsdump.c drivers/acpi/acpica/nssearch.c drivers/acpi/acpica/nsutils.c drivers/acpi/acpica/nsxfname.c drivers/acpi/acpica/utascii.c drivers/acpi/acpica/utdebug.c drivers/acpi/acpica/utmutex.c drivers/acpi/acpica/utstring.c drivers/acpi/device_pm.c drivers/acpi/osl.c drivers/acpi/property.c drivers/acpi/utils.c drivers/base/core.c drivers/base/map.c drivers/base/power/qos.c drivers/base/power/runtime.c drivers/base/power/wakeirq.c drivers/char/misc.c drivers/i2c/busses/i2c-i801.c drivers/i2c/i2c-core-base.c drivers/i2c/i2c-core-smbus.c drivers/i2c/i2c-core.h drivers/i2c/i2c-dev.c drivers/media/common/videobuf2/videobuf2-core.c drivers/media/common/videobuf2/videobuf2-v4l2.c drivers/media/mc/mc-request.c drivers/media/test-drivers/vicodec/codec-v4l2-fwht.c drivers/media/test-drivers/vicodec/vicodec-core.c drivers/media/v4l2-core/v4l2-ctrls-core.c drivers/media/v4l2-core/v4l2-ctrls-defs.c drivers/media/v4l2-core/v4l2-ctrls-request.c drivers/media/v4l2-core/v4l2-dev.c drivers/media/v4l2-core/v4l2-fh.c drivers/media/v4l2-core/v4l2-mem2mem.c drivers/pci/access.c drivers/pci/ats.c drivers/pci/host-bridge.c drivers/pci/iov.c drivers/pci/msi/api.c drivers/pci/msi/msi.c drivers/pci/pci-acpi.c drivers/pci/pci-driver.c drivers/pci/pci.c drivers/pci/pcie/aer.c drivers/pci/pcie/aspm.c drivers/pci/quirks.c drivers/pci/rebar.c drivers/pci/vc.c drivers/usb/gadget/legacy/raw_gadget.c fs/char_dev.c fs/d_path.c fs/dcache.c fs/file.c fs/file_table.c fs/ioctl.c fs/libfs.c fs/mnt_idmapping.c fs/namei.c fs/namespace.c fs/notify/fsnotify.c fs/open.c include/acpi/acpi_bus.h include/asm-generic/bitops/instrumented-non-atomic.h include/asm-generic/pgalloc.h include/linux/atomic/atomic-arch-fallback.h include/linux/atomic/atomic-instrumented.h include/linux/atomic/atomic-long.h include/linux/audit.h include/linux/bit_spinlock.h include/linux/cgroup.h include/linux/clockchips.h include/linux/cpumask.h include/linux/cred.h include/linux/dcache.h include/linux/delayed_call.h include/linux/device.h include/linux/device_cgroup.h include/linux/err.h include/linux/file.h include/linux/file_ref.h include/linux/filelock.h include/linux/find.h include/linux/folio_batch.h include/linux/fortify-string.h include/linux/fs.h include/linux/fs/super.h include/linux/fsnotify.h include/linux/fsnotify_backend.h include/linux/hrtimer.h include/linux/instrumented.h include/linux/jiffies.h include/linux/jump_label.h include/linux/kernel.h include/linux/kref.h include/linux/list.h include/linux/list_bl.h include/linux/llist.h include/linux/log2.h include/linux/lsm_hook_defs.h include/linux/maple_tree.h include/linux/memcontrol.h include/linux/mempolicy.h include/linux/mm.h include/linux/mmzone.h include/linux/mount.h include/linux/nodemask.h include/linux/page-flags.h include/linux/page_ext.h include/linux/page_ref.h include/linux/pagemap.h include/linux/perf_event.h include/linux/pgtable.h include/linux/pid.h include/linux/pm_qos.h include/linux/preempt.h include/linux/rbtree.h include/linux/rbtree_latch.h include/linux/rculist_bl.h include/linux/rcupdate.h include/linux/refcount.h include/linux/rmap.h include/linux/rtmutex.h include/linux/sched.h include/linux/sched/isolation.h include/linux/seqlock.h include/linux/spinlock_rt.h include/linux/srcu.h include/linux/swap.h include/linux/thread_info.h include/linux/uaccess.h include/linux/ucopysize.h include/linux/userfaultfd_k.h include/linux/vmstat.h include/linux/workqueue.h include/linux/xarray.h include/trace/events/exceptions.h include/trace/events/filemap.h include/trace/events/kmem.h include/trace/events/rpm.h include/trace/events/smbus.h include/trace/events/timer.h kernel/bpf/core.c kernel/cgroup/rstat.c kernel/kthread.c kernel/pid.c kernel/printk/printk_safe.c kernel/time/clockevents.c kernel/time/hrtimer.c kernel/time/posix-timers.c kernel/time/tick-oneshot.c kernel/time/tick-sched.c kernel/time/time.c kernel/time/timekeeping.c lib/errseq.c lib/idr.c lib/iomap.c lib/kobject.c lib/lockref.c lib/maple_tree.c lib/percpu_counter.c lib/plist.c lib/radix-tree.c lib/strncpy_from_user.c lib/timerqueue.c lib/usercopy.c lib/vsprintf.c lib/xarray.c mm/backing-dev.c mm/fail_page_alloc.c mm/filemap.c mm/internal.h mm/list_lru.c mm/maccess.c mm/memory.c mm/mempolicy.c mm/mmap_lock.c mm/page_counter.c mm/page_ext.c mm/page_owner.c mm/page_table_check.c mm/pgtable-generic.c mm/readahead.c mm/rmap.c mm/swap.c mm/swapfile.c security/device_cgroup.c security/integrity/ima/ima_main.c security/landlock/cred.h security/landlock/fs.c security/landlock/ruleset.c security/security.c security/smack/smack_access.c security/smack/smack_lsm.c security/tomoyo/audit.c security/tomoyo/common.c security/tomoyo/common.h security/tomoyo/domain.c security/tomoyo/file.c security/tomoyo/realpath.c security/tomoyo/tomoyo.c security/tomoyo/util.c usercopy_64.c]]

247/2 2026/07/30 12:50 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 159324
							output: 52
							thoughts: 220
						

Thoughts:
**Debugging a USB Gadget Driver Issue**

Okay, so I'm looking at the USB gadget code, specifically `drivers/usb/gadget/legacy/raw_gadget.c`, but something's off. I'm not seeing any trace of the `si4713` radio driver in the coverage. Why not? Well, it hits me – the `si4713` driver is, after all, a radio driver, and there's no guarantee it will even be loaded, or that it'll correctly bind to `0x10c4:0x8244` unless the device descriptor matches up perfectly. It's a classic bind issue.

Then I remember something important: the `si4713` driver expects the interface class to be `USB_CLASS_HID`, which is class 3. I did, in fact, provide `bInterfaceClass = 3`. Good. But wait… what about the `bDeviceClass`? Ah, I set it to `0`. And `bNumEndpoints`, I also set that to `0`. That might be a problem.

That's when it hits me: the `si4713` driver has an interrupt endpoint! If `bNumEndpoints` is set to `0`, the driver is probably rejecting it outright. That makes sense; it likely expects at least one endpoint to be defined. I'd better confirm this, let's go check the probe function in `drivers/media/radio/si4713/radio-usb-si4713.c`.



248/2 2026/07/30 12:50 tool read-file
0m Args:
map[File:drivers/media/radio/si4713/radio-usb-si4713.c FirstLine:100 LineCount:100]

Results:
map[Contents: 100:	static int vidioc_g_frequency(struct file *file, void *priv,
 101:					struct v4l2_frequency *vf)
 102:	{
 103:		struct si4713_usb_device *radio = video_drvdata(file);
 104:	
 105:		return v4l2_subdev_call(radio->v4l2_subdev, tuner, g_frequency, vf);
 106:	}
 107:	
 108:	static const struct v4l2_ioctl_ops usb_si4713_ioctl_ops = {
 109:		.vidioc_querycap	  = vidioc_querycap,
 110:		.vidioc_g_modulator	  = vidioc_g_modulator,
 111:		.vidioc_s_modulator	  = vidioc_s_modulator,
 112:		.vidioc_g_frequency	  = vidioc_g_frequency,
 113:		.vidioc_s_frequency	  = vidioc_s_frequency,
 114:		.vidioc_log_status	  = v4l2_ctrl_log_status,
 115:		.vidioc_subscribe_event   = v4l2_ctrl_subscribe_event,
 116:		.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 117:	};
 118:	
 119:	/* File system interface */
 120:	static const struct v4l2_file_operations usb_si4713_fops = {
 121:		.owner		= THIS_MODULE,
 122:		.open           = v4l2_fh_open,
 123:		.release        = v4l2_fh_release,
 124:		.poll           = v4l2_ctrl_poll,
 125:		.unlocked_ioctl	= video_ioctl2,
 126:	};
 127:	
 128:	static void usb_si4713_video_device_release(struct v4l2_device *v4l2_dev)
 129:	{
 130:		struct si4713_usb_device *radio = to_si4713_dev(v4l2_dev);
 131:		struct i2c_adapter *adapter = &radio->i2c_adapter;
 132:	
 133:		i2c_del_adapter(adapter);
 134:		v4l2_device_unregister(&radio->v4l2_dev);
 135:		kfree(radio->buffer);
 136:		kfree(radio);
 137:	}
 138:	
 139:	/*
 140:	 * This command sequence emulates the behaviour of the Windows driver.
 141:	 * The structure of these commands was determined by sniffing the
 142:	 * usb traffic of the device during startup.
 143:	 * Most likely, these commands make some queries to the device.
 144:	 * Commands are sent to enquire parameters like the bus mode,
 145:	 * component revision, boot mode, the device serial number etc.
 146:	 *
 147:	 * These commands are necessary to be sent in this order during startup.
 148:	 * The device fails to powerup if these commands are not sent.
 149:	 *
 150:	 * The complete list of startup commands is given in the start_seq table below.
 151:	 */
 152:	static int si4713_send_startup_command(struct si4713_usb_device *radio)
 153:	{
 154:		unsigned long until_jiffies = jiffies + usecs_to_jiffies(USB_RESP_TIMEOUT) + 1;
 155:		u8 *buffer = radio->buffer;
 156:		int retval;
 157:	
 158:		/* send the command */
 159:		retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
 160:						0x09, 0x21, 0x033f, 0, radio->buffer,
 161:						BUFFER_LENGTH, USB_TIMEOUT);
 162:		if (retval < 0)
 163:			return retval;
 164:	
 165:		for (;;) {
 166:			/* receive the response */
 167:			retval = usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
 168:					0x01, 0xa1, 0x033f, 0, radio->buffer,
 169:					BUFFER_LENGTH, USB_TIMEOUT);
 170:			if (retval < 0)
 171:				return retval;
 172:			if (!radio->buffer[1]) {
 173:				/* USB traffic sniffing showed that some commands require
 174:				 * additional checks. */
 175:				switch (buffer[1]) {
 176:				case 0x32:
 177:					if (radio->buffer[2] == 0)
 178:						return 0;
 179:					break;
 180:				case 0x14:
 181:				case 0x12:
 182:					if (radio->buffer[2] & SI4713_CTS)
 183:						return 0;
 184:					break;
 185:				case 0x06:
 186:					if ((radio->buffer[2] & SI4713_CTS) && radio->buffer[9] == 0x08)
 187:						return 0;
 188:					break;
 189:				default:
 190:					return 0;
 191:				}
 192:			}
 193:			if (time_is_before_jiffies(until_jiffies))
 194:				return -EIO;
 195:			msleep(3);
 196:		}
 197:	
 198:		return retval;
 199:	}
]

249/2 2026/07/30 12:50 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 161639
							output: 52
							thoughts: 60
						

Thoughts:
**Analyzing the `si4713` Probe Sequence**

Okay, hold on a second. I'm recalling something important about the `si4713` device during its startup sequence. It actually transmits control messages, right? I'm thinking about `si4713_send_startup_command` specifically. And if those commands don't receive the anticipated responses, that could lead to a probe failure. This is something I've seen before with similar devices.

So, where does that leave us? Right, the next logical step is to delve into the `usb_si4713_probe` function. I need to refresh my memory on the interactions there to see if we can identify where the communication is going awry. I'll need to look at the exact timing and sequencing of messages in that probe function to see if they line up with what I'm expecting. This will likely give us the key to debugging this probing issue.



250/2 2026/07/30 12:50 tool read-file
0m Args:
map[File:drivers/media/radio/si4713/radio-usb-si4713.c FirstLine:200 LineCount:100]

Results:
map[Contents: 200:	
 201:	struct si4713_start_seq_table {
 202:		int len;
 203:		u8 payload[8];
 204:	};
 205:	
 206:	/*
 207:	 * Some of the startup commands that could be recognized are :
 208:	 * (0x03): Get serial number of the board (Response : CB000-00-00)
 209:	 * (0x06, 0x03, 0x03, 0x08, 0x01, 0x0f) : Get Component revision
 210:	 */
 211:	static const struct si4713_start_seq_table start_seq[] = {
 212:	
 213:		{ 1, { 0x03 } },
 214:		{ 2, { 0x32, 0x7f } },
 215:		{ 6, { 0x06, 0x03, 0x03, 0x08, 0x01, 0x0f } },
 216:		{ 2, { 0x14, 0x02 } },
 217:		{ 2, { 0x09, 0x90 } },
 218:		{ 3, { 0x08, 0x90, 0xfa } },
 219:		{ 2, { 0x36, 0x01 } },
 220:		{ 2, { 0x05, 0x03 } },
 221:		{ 7, { 0x06, 0x00, 0x06, 0x0e, 0x01, 0x0f, 0x05 } },
 222:		{ 1, { 0x12 } },
 223:		/* Commands that are sent after pressing the 'Initialize'
 224:			button in the windows application */
 225:		{ 1, { 0x03 } },
 226:		{ 1, { 0x01 } },
 227:		{ 2, { 0x09, 0x90 } },
 228:		{ 3, { 0x08, 0x90, 0xfa } },
 229:		{ 1, { 0x34 } },
 230:		{ 2, { 0x35, 0x01 } },
 231:		{ 2, { 0x36, 0x01 } },
 232:		{ 2, { 0x30, 0x09 } },
 233:		{ 4, { 0x30, 0x06, 0x00, 0xe2 } },
 234:		{ 3, { 0x31, 0x01, 0x30 } },
 235:		{ 3, { 0x31, 0x04, 0x09 } },
 236:		{ 2, { 0x05, 0x02 } },
 237:		{ 6, { 0x06, 0x03, 0x03, 0x08, 0x01, 0x0f } },
 238:	};
 239:	
 240:	static int si4713_start_seq(struct si4713_usb_device *radio)
 241:	{
 242:		int retval = 0;
 243:		int i;
 244:	
 245:		radio->buffer[0] = 0x3f;
 246:	
 247:		for (i = 0; i < ARRAY_SIZE(start_seq); i++) {
 248:			int len = start_seq[i].len;
 249:			const u8 *payload = start_seq[i].payload;
 250:	
 251:			memcpy(radio->buffer + 1, payload, len);
 252:			memset(radio->buffer + len + 1, 0, BUFFER_LENGTH - 1 - len);
 253:			retval = si4713_send_startup_command(radio);
 254:		}
 255:	
 256:		return retval;
 257:	}
 258:	
 259:	static struct i2c_board_info si4713_board_info = {
 260:		I2C_BOARD_INFO("si4713", SI4713_I2C_ADDR_BUSEN_HIGH),
 261:	};
 262:	
 263:	struct si4713_command_table {
 264:		int command_id;
 265:		u8 payload[8];
 266:	};
 267:	
 268:	/*
 269:	 * Structure of a command :
 270:	 *	Byte 1 : 0x3f (always)
 271:	 *	Byte 2 : 0x06 (send a command)
 272:	 *	Byte 3 : Unknown
 273:	 *	Byte 4 : Number of arguments + 1 (for the command byte)
 274:	 *	Byte 5 : Number of response bytes
 275:	 */
 276:	static struct si4713_command_table command_table[] = {
 277:	
 278:		{ SI4713_CMD_POWER_UP,		{ 0x00, SI4713_PWUP_NARGS + 1, SI4713_PWUP_NRESP} },
 279:		{ SI4713_CMD_GET_REV,		{ 0x03, 0x01, SI4713_GETREV_NRESP } },
 280:		{ SI4713_CMD_POWER_DOWN,	{ 0x00, 0x01, SI4713_PWDN_NRESP} },
 281:		{ SI4713_CMD_SET_PROPERTY,	{ 0x00, SI4713_SET_PROP_NARGS + 1, SI4713_SET_PROP_NRESP } },
 282:		{ SI4713_CMD_GET_PROPERTY,	{ 0x00, SI4713_GET_PROP_NARGS + 1, SI4713_GET_PROP_NRESP } },
 283:		{ SI4713_CMD_TX_TUNE_FREQ,	{ 0x03, SI4713_TXFREQ_NARGS + 1, SI4713_TXFREQ_NRESP } },
 284:		{ SI4713_CMD_TX_TUNE_POWER,	{ 0x03, SI4713_TXPWR_NARGS + 1, SI4713_TXPWR_NRESP } },
 285:		{ SI4713_CMD_TX_TUNE_MEASURE,	{ 0x03, SI4713_TXMEA_NARGS + 1, SI4713_TXMEA_NRESP } },
 286:		{ SI4713_CMD_TX_TUNE_STATUS,	{ 0x00, SI4713_TXSTATUS_NARGS + 1, SI4713_TXSTATUS_NRESP } },
 287:		{ SI4713_CMD_TX_ASQ_STATUS,	{ 0x03, SI4713_ASQSTATUS_NARGS + 1, SI4713_ASQSTATUS_NRESP } },
 288:		{ SI4713_CMD_GET_INT_STATUS,	{ 0x03, 0x01, SI4713_GET_STATUS_NRESP } },
 289:		{ SI4713_CMD_TX_RDS_BUFF,	{ 0x03, SI4713_RDSBUFF_NARGS + 1, SI4713_RDSBUFF_NRESP } },
 290:		{ SI4713_CMD_TX_RDS_PS,		{ 0x00, SI4713_RDSPS_NARGS + 1, SI4713_RDSPS_NRESP } },
 291:	};
 292:	
 293:	static int send_command(struct si4713_usb_device *radio, u8 *payload, char *data, int len)
 294:	{
 295:		int retval;
 296:	
 297:		radio->buffer[0] = 0x3f;
 298:		radio->buffer[1] = 0x06;
 299:	
]

251/2 2026/07/30 12:50 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 164322
							output: 738
							thoughts: 1674
						

Thoughts:
**USB Device Communication Analysis and Strategy**

Okay, so `si4713_send_startup_command` is the key function here. It sends control messages and expects specific responses, which is crucial for probing. The problem is that `syz_usb_connect` doesn't provide the control message responses. `syz_usb_control_io`, on the other hand, *does* handle those responses. But `syz_usb_connect` handles the initial connection, so I can't completely bypass it. If `syz_usb_connect` is used, then the tool will automatically handle the standard requests, but not the vendor-specific ones.

`si4713_send_startup_command` sends a `SET_REPORT` (0x09, 0x21, 0x033f, 0) and then receives a `GET_REPORT` (0x01, 0xa1, 0x033f, 0). If the syzkaller doesn't respond to `GET_REPORT`, the probe will fail.

Good, `syz_usb_connect$hid` *does* respond to `HID_REQ_GET_REPORT`! I need to ensure it provides the right response. Looking at `vusb_responses_hid`, I see that `HID_REQ_GET_REPORT` is covered, which is what I want.

The next thing is that `si4713_send_startup_command` checks `radio->buffer`. Specifically, it checks `if (!radio->buffer[1])`, and then it checks the `switch (buffer[1])`. This is the important part! The first comparison is comparing if byte 1 of buffer is 0. But if byte 1 is 0, the switch statement will never match!

Wait! I re-examined the code. I realized that if `radio->buffer[1]` is 0, it *succeeds* because the `default` case returns 0! Therefore, if `syz_usb_control_io$hid` returns a buffer of zeros for `HID_REQ_GET_REPORT`, `si4713_send_startup_command` will succeed because of the `default: return 0;` branch.

The next is about setting the `idVendor` and `idProduct`. Ideally, I'd want to set it to `0x10c4:0x8244`. `syz_usb_connect$hid` automatically patches those values, so I can't force it. The `syz_usb_connect` returns `fd_usb`, which isn't the same type as `syz_usb_control_io$hid`, which takes `fd_usb_hid`. But I can use `syz_usb_control_io` instead of the HID version! I can use `vusb_responses`.

I'll build the `vusb_responses` structure. I can provide a generic response for `USB_TYPE_CLASS` and `GET_REPORT` which is `0x01`. `USB_TYPE_CLASS` is `0x20`, so `type = 0x20` and `req = 0x01`. Now, let's try configuring the `vusb_responses` and supplying zero bytes of data to that `GET_REPORT` request, and see if it works!



252/2 2026/07/30 12:50 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{0, 0, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, AUTO, [{{0, 0, AUTO, AUTO, 0, 0, 0x80, 0, "", [{{{0, 0, 0, 0, AUTO, 3, 0, 0, 0, [], []}}}]}}]}}, 0)
syz_usb_control_io(r0, 0, &AUTO={AUTO, @generic={0x20, 0x01, AUTO, [0, 0, 0, 0, 0, 0, 0, 0]}})
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

253/2 2026/07/30 12:50 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 167648
							output: 739
							thoughts: 531
						

Thoughts:
**Debugging USB Descriptor Initialization**

Okay, hold on a second. I'm getting a "wrong struct arg for 'const'" error at index 0 for `bLength` in `usb_interface_descriptor_verbose_t`. Right, I remember now! `bLength` is defined as `const[USB_DT_INTERFACE_SIZE, int8]`.  And `USB_DT_INTERFACE_SIZE` is, in this case, 9. So it's expecting `9`, not `0` for that field. Makes sense. I need to ensure I'm providing the correct constant values for the fields defined as `const`. I should probably double-check all the `const` fields in the other descriptors, just to be sure. Let's do a quick run-through.

First, the `usb_device_descriptor_verbose_t`:
1.  `bLength` should be `USB_DT_DEVICE_SIZE`, which is 18.
2.  `bDescriptorType` is `USB_DT_DEVICE`, which is 1.
3.  `bcdUSB` will be 0x200.
4.  `bDeviceClass` is 0,
5.  `bDeviceSubClass` is 0,
6.  `bDeviceProtocol` is 0,
7.  `bMaxPacketSize0` is 64.
8.  `idVendor` is 0x10c4.
9.  `idProduct` is 0x8244.
10. `bcdDevice` is 0.
11. `iManufacturer` is 0.
12. `iProduct` is 0.
13. `iSerialNumber` is 0.

Now, the `usb_config_descriptor_verbose_t`:
1.  `bLength` is `USB_DT_CONFIG_SIZE`, which is 9.
2.  `bDescriptorType` is `USB_DT_CONFIG`, which is 2.
3.  `wTotalLength` I'll have the system calculate.
4.  `bNumInterfaces` should also be determined by the system.
5.  `bConfigurationValue` is 1.
6.  `iConfiguration` is 0.
7.  `bmAttributes` is 0x80.
8.  `bMaxPower` is 0.

Finally, back to the `usb_interface_descriptor_verbose_t`:
1.  `bLength` is `USB_DT_INTERFACE_SIZE`, which, again, is 9.
2.  `bDescriptorType` is `USB_DT_INTERFACE`, which is 4.
3.  `bInterfaceNumber` is 0.
4.  `bAlternateSetting` is 0.
5.  `bNumEndpoints` this will need to be decided by the system.
6.  `bInterfaceClass` is 3.
7.  `bInterfaceSubClass` is 0.
8.  `bInterfaceProtocol` is 0.
9.  `iInterface` is 0.

Alright, I think I've got all the correct values assigned. Time to try this now. Hopefully, that will fix the issue.



254/2 2026/07/30 12:51 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{18, 1, 0x200, 0, 0, 0, 64, 0x10c4, 0x8244, 0, 0, 0, 0, AUTO, [{{9, 2, AUTO, AUTO, 1, 0, 0x80, 0, "", [{{{9, 4, 0, 0, AUTO, 3, 0, 0, 0, [], []}}}]}}]}}, 0)
syz_usb_control_io(r0, 0, &AUTO={AUTO, @generic={0x20, 0x01, AUTO, [0, 0, 0, 0, 0, 0, 0, 0]}})
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

255/2 2026/07/30 12:51 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 169814
							output: 50
							thoughts: 1727
						

Thoughts:
**Analyzing USB Device Descriptor Issues**

Okay, so I'm digging into this code and I've hit a snag with the `usb_interface_descriptor_verbose_t` struct, specifically at `bLength` when dealing with the `const` argument. It looks like `usb_interface_descriptor` has a nested structure, with `usb_interface_descriptor_eps_array_t` and further down the line, `usb_interface_descriptor_t`, where `CLASS` is defined as `const[0, int8]`. This means `bInterfaceClass` *must* be `0`! But I'm providing `3`, which is clearly wrong.

I need to understand what's being passed:
1.  `bLength = 9`
2.  `bDescriptorType = 4`
3.  `bInterfaceNumber = 0`
4.  `bAlternateSetting = 0`
5.  `bNumEndpoints = AUTO`
6.  `bInterfaceClass = 0 (MUST BE 0!)`
7.  `bInterfaceSubClass = 0`
8.  `bInterfaceProtocol = 0`
9.  `iInterface = 0`
10. `extra = []`
11. `endpoints = []`

If `bInterfaceClass` is forced to `0`, I can't just pass `3` for a HID device class (`USB_CLASS_HID`) like `si4713` expects. I was hoping to use `syz_usb_connect$hid`, but that also hardcodes vendor and product IDs. Maybe I can use `syz_usb_connect$hid` and *somehow* have it patch the IDs to match `si4713`? No, Syzkaller patches it to specific IDs. I need to make sure I am providing the right IDs! Let me check `drivers/media/radio/si4713/radio-usb-si4713.c` again. Yes, it uses `USB_DEVICE_AND_INTERFACE_INFO(USB_SI4713_VENDOR, USB_SI4713_PRODUCT, USB_CLASS_HID, 0, 0)`.

What are my options? I could use `syz_usb_connect` with a `usb_device_descriptor`, but it's hardcoded to `0` for the interface class. Okay, I was trying to send an array of bytes, but I know it'll cause an error. I can use the `ANY` type in syzkaller.

I can't directly use `ANY` like that. I can use `syz_usb_connect$hid`! But that takes `usb_device_descriptor_hid`. The inner `usb_device_descriptor_t` in `usb_device_descriptor_hid` has `VENDOR` and `PRODUCT` at `0, 0`. Okay, syzkaller will patch them. This sounds promising! But will it work and is my target still `si4713`?

I need to re-evaluate my options: if I use `syz_usb_connect$hid`, syzkaller *will* patch `idVendor` and `idProduct`. If I *also* open `/dev/radio0`, will that trigger the bug? The bug is in `i2c_adapter_depth`, which calls `i2c_adapter_lock_bus`. I need to trigger a UAF on `adapter->dev.parent->type`. I know this happens when an I2C adapter is unregistered, but its parent (`usb_device`) is already freed.

So, the key is the I2C adapter and the driver.  `si4713` *is* one such driver. Wait! I remember I found it in `au0828`. Let's check `au0828`. It's a video driver, and it *does* register an I2C adapter, and it has the same UAF issue! I've been here before. Now, what USB IDs does `au0828` use? Ah, `0x2040:0x7200`. Can I use `syz_usb_connect` here?

`au0828` expects either `0` or `255` for `bDeviceClass`. Let's check its USB device table. It uses `USB_DEVICE(0x2040, 0x7200)`, which matches *any* class! Perfect! So, if I use `syz_usb_connect` with `idVendor=0x2040` and `idProduct


256/2 2026/07/30 12:51 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-core.c FirstLine:200 LineCount:100]

Results:
map[Contents: 200:	
 201:		mdev = media_device_usb_allocate(udev, KBUILD_MODNAME, THIS_MODULE);
 202:		if (IS_ERR(mdev))
 203:			return PTR_ERR(mdev);
 204:	
 205:		dev->media_dev = mdev;
 206:	#endif
 207:		return 0;
 208:	}
 209:	
 210:	#ifdef CONFIG_MEDIA_CONTROLLER
 211:	static void au0828_media_graph_notify(struct media_entity *new,
 212:					      void *notify_data)
 213:	{
 214:		struct au0828_dev *dev = notify_data;
 215:		int ret;
 216:		struct media_entity *entity, *mixer = NULL, *decoder = NULL;
 217:	
 218:		if (!new) {
 219:			/*
 220:			 * Called during au0828 probe time to connect
 221:			 * entities that were created prior to registering
 222:			 * the notify handler. Find mixer and decoder.
 223:			*/
 224:			media_device_for_each_entity(entity, dev->media_dev) {
 225:				if (entity->function == MEDIA_ENT_F_AUDIO_MIXER)
 226:					mixer = entity;
 227:				else if (entity->function == MEDIA_ENT_F_ATV_DECODER)
 228:					decoder = entity;
 229:			}
 230:			goto create_link;
 231:		}
 232:	
 233:		switch (new->function) {
 234:		case MEDIA_ENT_F_AUDIO_MIXER:
 235:			mixer = new;
 236:			if (dev->decoder)
 237:				decoder = dev->decoder;
 238:			break;
 239:		case MEDIA_ENT_F_ATV_DECODER:
 240:			/* In case, Mixer is added first, find mixer and create link */
 241:			media_device_for_each_entity(entity, dev->media_dev) {
 242:				if (entity->function == MEDIA_ENT_F_AUDIO_MIXER)
 243:					mixer = entity;
 244:			}
 245:			decoder = new;
 246:			break;
 247:		default:
 248:			break;
 249:		}
 250:	
 251:	create_link:
 252:		if (decoder && mixer) {
 253:			ret = media_get_pad_index(decoder, MEDIA_PAD_FL_SOURCE,
 254:						  PAD_SIGNAL_AUDIO);
 255:			if (ret >= 0)
 256:				ret = media_create_pad_link(decoder, ret,
 257:							    mixer, 0,
 258:							    MEDIA_LNK_FL_ENABLED);
 259:			if (ret < 0)
 260:				dev_err(&dev->usbdev->dev,
 261:					"Mixer Pad Link Create Error: %d\n", ret);
 262:		}
 263:	}
 264:	
 265:	static bool au0828_is_link_shareable(struct media_entity *owner,
 266:					     struct media_entity *entity)
 267:	{
 268:		bool shareable = false;
 269:	
 270:		/* Tuner link can be shared by audio, video, and VBI */
 271:		switch (owner->function) {
 272:		case MEDIA_ENT_F_IO_V4L:
 273:		case MEDIA_ENT_F_AUDIO_CAPTURE:
 274:		case MEDIA_ENT_F_IO_VBI:
 275:			if (entity->function == MEDIA_ENT_F_IO_V4L ||
 276:			    entity->function == MEDIA_ENT_F_AUDIO_CAPTURE ||
 277:			    entity->function == MEDIA_ENT_F_IO_VBI)
 278:				shareable = true;
 279:			break;
 280:		case MEDIA_ENT_F_DTV_DEMOD:
 281:		default:
 282:			break;
 283:		}
 284:		return shareable;
 285:	}
 286:	
 287:	/* Callers should hold graph_mutex */
 288:	static int au0828_enable_source(struct media_entity *entity,
 289:					struct media_pipeline *pipe)
 290:	{
 291:		struct media_entity  *source, *find_source;
 292:		struct media_entity *sink;
 293:		struct media_link *link, *found_link = NULL;
 294:		int ret = 0;
 295:		struct media_device *mdev = entity->graph_obj.mdev;
 296:		struct au0828_dev *dev;
 297:	
 298:		if (!mdev)
 299:			return -ENODEV;
]

257/2 2026/07/30 12:51 llm crash-repro-finder-compressor
10m Model:
gemini-3.5-flash

Reply:
### 1. Approaches Tried and Results

*   **Device Path Opening**:
    *   Attempted to open `/dev/video0` and `/dev/i2c-0` directly using `syz_open_dev$video` and `syz_open_dev$I2C` with explicit paths.
    *   *Result*: Failed with `bad string value "/dev/video0\x00", expect ["/dev/video#\x00"]`.
    *   *Correction*: Syzkaller requires the exact template string `"/dev/video#\x00"` or `"/dev/i2c-#\x00"`, replacing `#` with the `id` argument.
*   **Generic HID Emulation**:
    *   Used `syz_usb_connect$hid` to connect a generic HID device.
    *   *Result*: No crash. Coverage analysis showed `raw_gadget.c` was covered, but target drivers (`si4713`, `au0828`, `go7007`) were not. This is because `syz_usb_connect$hid` patches vendor/product IDs to match generic HID drivers, not our target drivers.
*   **Custom USB Descriptor Construction**:
    *   Attempted to construct a custom `usb_device_descriptor` for `syz_usb_connect` to emulate `si4713` (Vendor `0x10c4`, Product `0x8244`, Class `USB_CLASS_HID`).
    *   *Dead-ends & Syntax Errors*:
        *   `AUTO` cannot be used for `FlagsType` (e.g., `bcdUSB`, `bMaxPacketSize0`, `bmAttributes`). They must be explicit values (e.g., `0x200`, `64`, `0x80`).
        *   `AUTO` cannot be used for `ArrayType` (e.g., `configs`, `interfaces`). They must be explicit arrays (e.g., `[...]`).
        *   `void` fields (like `extra` in `usb_config_descriptor_verbose_t`) are omitted and do not accept `{}`.
        *   `len` fields (like `bNumConfigurations`, `wTotalLength`, `bNumInterfaces`, `bNumEndpoints`) are of `LenType` and must be explicitly provided as `AUTO` in the struct literal (they are NOT omitted).
        *   `usb_interface_descriptor` is a struct with a single field `inner`, requiring nested braces `{{{...}}}` for its array elements.
        *   Currently blocked on a persistent `wrong array arg *prog.BufferType` or `wrong array arg *prog.LenType` error when trying to correctly nest the `interfaces` array inside the `configs` array of the `usb_device_descriptor`.

### 2. Current Hypotheses & Active Lines of Investigation

*   **Deferred Cleanup Race via `si4713`**:
    *   Emulate a USB device matching `si4713` (Vendor `0x10c4`, Product `0x8244`, Class `USB_CLASS_HID`).
    *   Open the corresponding radio device `/dev/radio#` to hold a reference to the driver context.
    *   Open the corresponding I2C device `/dev/i2c-#`.
    *   Disconnect the USB device. The driver's `disconnect` callback runs but defers the unregistration of the I2C adapter because the radio device is still open.
    *   The USB core frees the `struct usb_device`.
    *   Perform an I2C transaction (e.g., `ioctl$I2C_SMBUS`) on the open I2C file descriptor. This triggers `i2c_adapter_depth` which dereferences `adapter->dev.parent->type` (offset 264 of the freed `usb_device`), causing the UAF.

### 3. Critical Code and Configuration Values

*   **Target USB IDs**:
    *   `si4713`: Vendor `0x10c4`, Product `0x8244`, Class `3` (`USB_CLASS_HID`).
    *   `au0828`: Vendor `0x2040`, Product `0x7200`.
    *   `go7007`: Vendor `0x0eb1`, Product `0x7007`.
*   **Syzkaller Struct Definitions (from `vusb.txt`)**:
    ```
    usb_device_descriptor {
        inner	usb_device_descriptor_t[0, 0, 0, 0, 0, 0, array[usb_config_descriptor, 1]]
    } [packed]

    usb_config_descriptor {
        inner	usb_config_descriptor_ifaces_array_t[int8, array[usb_interface_descriptor, 1:4]]
    } [packed]

    usb_interface_descriptor {
        inner	usb_interface_descriptor_eps_array_t[int8, int8, const[0, int8], const[0, int8], const[0, int8], array[usb_interface_extra_descriptor, 0:2], array[usb_endpoint_descriptor, 0:16]]
    } [packed]
    ```
*   **Field Counts for Struct Literals**:
    *   `usb_device_descriptor_verbose_t` (15 fields):
        `bLength` (const), `bDescriptorType` (const), `bcdUSB` (flags), `bDeviceClass` (const), `bDeviceSubClass` (const), `bDeviceProtocol` (const), `bMaxPacketSize0` (flags), `idVendor` (const), `idProduct` (const), `bcdDevice` (const), `iManufacturer` (const), `iProduct` (const), `iSerialNumber` (const), `bNumConfigurations` (len), `configs` (array).
    *   `usb_config_descriptor_verbose_t` (10 fields, `extra` is `void` and omitted -> 9 fields):
        `bLength` (const), `bDescriptorType` (const), `wTotalLength` (len), `bNumInterfaces` (len), `bConfigurationValue` (int), `iConfiguration` (int), `bmAttributes` (flags), `bMaxPower` (int), `interfaces` (array).
    *   `usb_interface_descriptor_verbose_t` (11 fields):
        `bLength` (const), `bDescriptorType` (const), `bInterfaceNumber` (int), `bAlternateSetting` (int), `bNumEndpoints` (len), `bInterfaceClass` (const), `bInterfaceSubClass` (const), `bInterfaceProtocol` (const), `iInterface` (int), `extra` (array), `endpoints` (array).

### 4. Potential Reasoning Loops / Repetitive Tool Calls

*   **Brace Nesting Loop**: Avoid repeatedly guessing the brace nesting of `configs` and `interfaces` arrays in `usb_device_descriptor` without matching the exact field types.
*   **Omitted vs. Non-Omitted Fields**: Remember that `len` fields (of `LenType`) are NOT omitted in syzkaller program syntax; they must be explicitly provided as `AUTO`. Only `void` fields are omitted. All `const`, `int`, and `flags` fields must have explicit values (or `0` if they are not important).

Tokens:
							input: 160864
							output: 1690
							thoughts: 3189
						

258/2 2026/07/30 13:01 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 43759
							output: 50
							thoughts: 18
						

Thoughts:
Okay, let's see. My mind's jumping around a bit, but the most pressing thing right now is that `au0828_usb_probe`. I need to get back to that. It's calling to me, you know? It's the key to something I'm working on, and I've got to revisit the code for it immediately. I need to dive back in and understand what's happening.



259/2 2026/07/30 13:02 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-core.c FirstLine:580 LineCount:100]

Results:
map[Contents: 580:			}
 581:		} else {
 582:			/*
 583:			 * Call au0828_media_graph_notify() to connect
 584:			 * audio graph to our graph. In this case, audio
 585:			 * driver registered the device and there is no
 586:			 * entity_notify to be called when new entities
 587:			 * are added. Invoke it now.
 588:			*/
 589:			au0828_media_graph_notify(NULL, (void *) dev);
 590:		}
 591:	
 592:		/*
 593:		 * Find tuner, decoder and demod.
 594:		 *
 595:		 * The tuner and decoder should be cached, as they'll be used by
 596:		 *	au0828_enable_source.
 597:		 *
 598:		 * It also needs to disable the link between tuner and
 599:		 * decoder/demod, to avoid disable step when tuner is requested
 600:		 * by video or audio. Note that this step can't be done until dvb
 601:		 * graph is created during dvb register.
 602:		*/
 603:		media_device_for_each_entity(entity, dev->media_dev) {
 604:			switch (entity->function) {
 605:			case MEDIA_ENT_F_TUNER:
 606:				dev->tuner = entity;
 607:				break;
 608:			case MEDIA_ENT_F_ATV_DECODER:
 609:				dev->decoder = entity;
 610:				break;
 611:			case MEDIA_ENT_F_DTV_DEMOD:
 612:				demod = entity;
 613:				break;
 614:			}
 615:		}
 616:	
 617:		/* Disable link between tuner->demod and/or tuner->decoder */
 618:		if (dev->tuner) {
 619:			list_for_each_entry(link, &dev->tuner->links, list) {
 620:				if (demod && link->sink->entity == demod)
 621:					media_entity_setup_link(link, 0);
 622:				if (dev->decoder && link->sink->entity == dev->decoder)
 623:					media_entity_setup_link(link, 0);
 624:			}
 625:		}
 626:	
 627:		/* register entity_notify callback */
 628:		dev->entity_notify.notify_data = (void *) dev;
 629:		dev->entity_notify.notify = (void *) au0828_media_graph_notify;
 630:		media_device_register_entity_notify(dev->media_dev,
 631:							  &dev->entity_notify);
 632:	
 633:		/* set enable_source */
 634:		mutex_lock(&dev->media_dev->graph_mutex);
 635:		dev->media_dev->source_priv = (void *) dev;
 636:		dev->media_dev->enable_source = au0828_enable_source;
 637:		dev->media_dev->disable_source = au0828_disable_source;
 638:		mutex_unlock(&dev->media_dev->graph_mutex);
 639:	#endif
 640:		return 0;
 641:	}
 642:	
 643:	static int au0828_usb_probe(struct usb_interface *interface,
 644:		const struct usb_device_id *id)
 645:	{
 646:		int ifnum;
 647:		int retval = 0;
 648:	
 649:		struct au0828_dev *dev;
 650:		struct usb_device *usbdev = interface_to_usbdev(interface);
 651:	
 652:		ifnum = interface->altsetting->desc.bInterfaceNumber;
 653:	
 654:		if (ifnum != 0)
 655:			return -ENODEV;
 656:	
 657:		dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__,
 658:			le16_to_cpu(usbdev->descriptor.idVendor),
 659:			le16_to_cpu(usbdev->descriptor.idProduct),
 660:			ifnum);
 661:	
 662:		/*
 663:		 * Make sure we have 480 Mbps of bandwidth, otherwise things like
 664:		 * video stream wouldn't likely work, since 12 Mbps is generally
 665:		 * not enough even for most Digital TV streams.
 666:		 */
 667:		if (usbdev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) {
 668:			pr_err("au0828: Device initialization failed.\n");
 669:			pr_err("au0828: Device must be connected to a high-speed USB 2.0 port.\n");
 670:			return -ENODEV;
 671:		}
 672:	
 673:		dev = kzalloc_obj(*dev);
 674:		if (dev == NULL) {
 675:			pr_err("%s() Unable to allocate memory\n", __func__);
 676:			return -ENOMEM;
 677:		}
 678:	
 679:		mutex_init(&dev->lock);
]

260/2 2026/07/30 13:02 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 45492
							output: 50
							thoughts: 104
						

Thoughts:
**Debugging the `au0828` USB Driver Connection**

Okay, let's see... the error log points to `au0828` needing a `USB_SPEED_HIGH` connection, specifically `usbdev->speed == USB_SPEED_HIGH`. I remember `syz_usb_connect` takes a `speed` argument using the `flags[usb_device_speed]` enum. Let me check... Ah, right, `USB_SPEED_HIGH` is defined as `3`. I'm pretty sure I provided `3` in the test case. And the interface number, `ifnum`, must be `0`, which I explicitly set to `bInterfaceNumber = 0`. So far, so good, I think the speed and interface number are correct.

Wait a second... it can't be that simple. What about the endpoints? I wonder if `au0828` has specific checks related to the endpoint configurations during the connection process. It's time to dig deeper into the driver code related to endpoint handling to understand why this connection is failing.



261/2 2026/07/30 13:02 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-core.c FirstLine:680 LineCount:100]

Results:
map[Contents: 680:		mutex_lock(&dev->lock);
 681:		mutex_init(&dev->mutex);
 682:		mutex_init(&dev->dvb.lock);
 683:		dev->usbdev = usbdev;
 684:		dev->boardnr = id->driver_info;
 685:		dev->board = au0828_boards[dev->boardnr];
 686:	
 687:		/* Initialize the media controller */
 688:		retval = au0828_media_device_init(dev, usbdev);
 689:		if (retval) {
 690:			pr_err("%s() au0828_media_device_init failed\n",
 691:			       __func__);
 692:			mutex_unlock(&dev->lock);
 693:			kfree(dev);
 694:			return retval;
 695:		}
 696:	
 697:		retval = au0828_v4l2_device_register(interface, dev);
 698:		if (retval) {
 699:			au0828_usb_v4l2_media_release(dev);
 700:			mutex_unlock(&dev->lock);
 701:			kfree(dev);
 702:			return retval;
 703:		}
 704:	
 705:		/* Power Up the bridge */
 706:		au0828_write(dev, REG_600, 1 << 4);
 707:	
 708:		/* Bring up the GPIO's and supporting devices */
 709:		au0828_gpio_setup(dev);
 710:	
 711:		/* I2C */
 712:		au0828_i2c_register(dev);
 713:	
 714:		/* Setup */
 715:		au0828_card_setup(dev);
 716:	
 717:		/*
 718:		 * Store the pointer to the au0828_dev so it can be accessed in
 719:		 * au0828_usb_disconnect
 720:		 */
 721:		usb_set_intfdata(interface, dev);
 722:	
 723:		/* Analog TV */
 724:		retval = au0828_analog_register(dev, interface);
 725:		if (retval) {
 726:			pr_err("%s() au0828_analog_register failed to register on V4L2\n",
 727:				__func__);
 728:			mutex_unlock(&dev->lock);
 729:			goto done;
 730:		}
 731:	
 732:		/* Digital TV */
 733:		retval = au0828_dvb_register(dev);
 734:		if (retval)
 735:			pr_err("%s() au0828_dvb_register failed\n",
 736:			       __func__);
 737:	
 738:		/* Remote controller */
 739:		au0828_rc_register(dev);
 740:	
 741:		pr_info("Registered device AU0828 [%s]\n",
 742:			dev->board.name == NULL ? "Unset" : dev->board.name);
 743:	
 744:		mutex_unlock(&dev->lock);
 745:	
 746:		retval = au0828_media_device_register(dev, usbdev);
 747:	
 748:	done:
 749:		if (retval < 0)
 750:			au0828_usb_disconnect(interface);
 751:	
 752:		return retval;
 753:	}
 754:	
 755:	static int au0828_suspend(struct usb_interface *interface,
 756:					pm_message_t message)
 757:	{
 758:		struct au0828_dev *dev = usb_get_intfdata(interface);
 759:	
 760:		if (!dev)
 761:			return 0;
 762:	
 763:		pr_info("Suspend\n");
 764:	
 765:		au0828_rc_suspend(dev);
 766:		au0828_v4l2_suspend(dev);
 767:		au0828_dvb_suspend(dev);
 768:	
 769:		/* FIXME: should suspend also ATV/DTV */
 770:	
 771:		return 0;
 772:	}
 773:	
 774:	static int au0828_resume(struct usb_interface *interface)
 775:	{
 776:		struct au0828_dev *dev = usb_get_intfdata(interface);
 777:		if (!dev)
 778:			return 0;
 779:	
]

262/2 2026/07/30 13:02 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 47297
							output: 52
							thoughts: 47
						

Thoughts:
**Analyzing the Code's I2C Registration**

Okay, so looking at this code snippet, the first thing that jumps out at me is that it appears to bypass the usual endpoint checks. It doesn't seem to be performing any validation before attempting to register with the I2C bus. Instead, it jumps straight to `au0828_i2c_register(dev)`. That's a bit unusual. My immediate thought is, "Why the shortcut?" Is this intended behaviour, or is something being assumed?

I need to dive deeper. My next step will be to meticulously examine the `au0828_i2c_register` function itself. I need to understand what it's doing internally. Does it handle any error checking or validation *within* that function? Does it assume the `dev` structure is valid at this point? Does it perform the equivalent of what was skipped above, or does it do something else entirely? A thorough investigation of `au0828_i2c_register` will provide crucial context and hopefully illuminate why this initial code doesn't seem to be performing endpoint checks before the I2C registration.



263/2 2026/07/30 13:02 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-i2c.c FirstLine:350 LineCount:100]

Results:
map[Contents: 350:		}
 351:	}
 352:	
 353:	/* init + register i2c adapter */
 354:	int au0828_i2c_register(struct au0828_dev *dev)
 355:	{
 356:		dprintk(1, "%s()\n", __func__);
 357:	
 358:		dev->i2c_adap = au0828_i2c_adap_template;
 359:		dev->i2c_algo = au0828_i2c_algo_template;
 360:		dev->i2c_client = au0828_i2c_client_template;
 361:	
 362:		dev->i2c_adap.dev.parent = &dev->usbdev->dev;
 363:	
 364:		strscpy(dev->i2c_adap.name, KBUILD_MODNAME,
 365:			sizeof(dev->i2c_adap.name));
 366:	
 367:		dev->i2c_adap.algo = &dev->i2c_algo;
 368:		dev->i2c_adap.algo_data = dev;
 369:	#ifdef CONFIG_VIDEO_AU0828_V4L2
 370:		i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
 371:	#else
 372:		i2c_set_adapdata(&dev->i2c_adap, dev);
 373:	#endif
 374:		i2c_add_adapter(&dev->i2c_adap);
 375:	
 376:		dev->i2c_client.adapter = &dev->i2c_adap;
 377:	
 378:		if (0 == dev->i2c_rc) {
 379:			pr_info("i2c bus registered\n");
 380:			if (i2c_scan)
 381:				do_i2c_scan(KBUILD_MODNAME, &dev->i2c_client);
 382:		} else
 383:			pr_info("i2c bus register FAILED\n");
 384:	
 385:		return dev->i2c_rc;
 386:	}
 387:	
 388:	int au0828_i2c_unregister(struct au0828_dev *dev)
 389:	{
 390:		i2c_del_adapter(&dev->i2c_adap);
 391:		return 0;
 392:	}
 393:	
]

264/2 2026/07/30 13:02 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 48392
							output: 50
							thoughts: 42
						

Thoughts:
Okay, here's my interpretation of those thoughts, framed from my perspective as an expert:

**Debugging the I2C Adapter**

Alright, that's a good start - the system *is* recognizing the I2C adapter. The core hardware link appears to be established. Now, the gears are turning... I need to be careful not to make assumptions. Is this a *specific* issue with this particular adapter, or is there a more general flaw in the I2C driver implementation?

That `au0828` driver... could it be exhibiting the same disconnection bug I've seen before? I remember there was a problem with handling USB disconnect events, and this is a prime suspect. Let's dig into that `au0828_usb_disconnect` function. Understanding how that function handles the disconnection of the USB device is crucial. Checking that function should help provide further insight into whether this is a general I2C driver issue or something specific to this implementation. Time to look closely at that code and trace the disconnect sequence.



265/2 2026/07/30 13:02 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-core.c FirstLine:290 LineCount:100]

Results:
map[Contents: 290:	{
 291:		struct media_entity  *source, *find_source;
 292:		struct media_entity *sink;
 293:		struct media_link *link, *found_link = NULL;
 294:		int ret = 0;
 295:		struct media_device *mdev = entity->graph_obj.mdev;
 296:		struct au0828_dev *dev;
 297:	
 298:		if (!mdev)
 299:			return -ENODEV;
 300:	
 301:		dev = mdev->source_priv;
 302:	
 303:		/*
 304:		 * For Audio and V4L2 entity, find the link to which decoder
 305:		 * is the sink. Look for an active link between decoder and
 306:		 * source (tuner/s-video/Composite), if one exists, nothing
 307:		 * to do. If not, look for any  active links between source
 308:		 * and any other entity. If one exists, source is busy. If
 309:		 * source is free, setup link and start pipeline from source.
 310:		 * For DVB FE entity, the source for the link is the tuner.
 311:		 * Check if tuner is available and setup link and start
 312:		 * pipeline.
 313:		*/
 314:		if (entity->function == MEDIA_ENT_F_DTV_DEMOD) {
 315:			sink = entity;
 316:			find_source = dev->tuner;
 317:		} else {
 318:			/* Analog isn't configured or register failed */
 319:			if (!dev->decoder) {
 320:				ret = -ENODEV;
 321:				goto end;
 322:			}
 323:	
 324:			sink = dev->decoder;
 325:	
 326:			/*
 327:			 * Default input is tuner and default input_type
 328:			 * is AU0828_VMUX_TELEVISION.
 329:			 *
 330:			 * There is a problem when s_input is called to
 331:			 * change the default input. s_input will try to
 332:			 * enable_source before attempting to change the
 333:			 * input on the device, and will end up enabling
 334:			 * default source which is tuner.
 335:			 *
 336:			 * Additional logic is necessary in au0828 to detect
 337:			 * that the input has changed and enable the right
 338:			 * source. au0828 handles this case in its s_input.
 339:			 * It will disable the old source and enable the new
 340:			 * source.
 341:			 *
 342:			*/
 343:			if (dev->input_type == AU0828_VMUX_TELEVISION)
 344:				find_source = dev->tuner;
 345:			else if (dev->input_type == AU0828_VMUX_SVIDEO ||
 346:				 dev->input_type == AU0828_VMUX_COMPOSITE)
 347:				find_source = &dev->input_ent[dev->input_type];
 348:			else {
 349:				/* unknown input - let user select input */
 350:				ret = 0;
 351:				goto end;
 352:			}
 353:		}
 354:	
 355:		/* Is there an active link between sink and source */
 356:		if (dev->active_link) {
 357:			if (dev->active_link_owner == entity) {
 358:				/* This check is necessary to handle multiple
 359:				 * enable_source calls from v4l_ioctls during
 360:				 * the course of video/vbi application run-time.
 361:				*/
 362:				pr_debug("%s already owns the tuner\n", entity->name);
 363:				ret = 0;
 364:				goto end;
 365:			} else if (au0828_is_link_shareable(dev->active_link_owner,
 366:				   entity)) {
 367:				/* Either ALSA or Video own tuner. Sink is the same
 368:				 * for both. Allow sharing the active link between
 369:				 * their common source (tuner) and sink (decoder).
 370:				 * Starting pipeline between sharing entity and sink
 371:				 * will fail with pipe mismatch, while owner has an
 372:				 * active pipeline. Switch pipeline ownership from
 373:				 * user to owner when owner disables the source.
 374:				 */
 375:				dev->active_link_shared = true;
 376:				/* save the user info to use from disable */
 377:				dev->active_link_user = entity;
 378:				dev->active_link_user_pipe = pipe;
 379:				pr_debug("%s owns the tuner %s can share!\n",
 380:					 dev->active_link_owner->name,
 381:					 entity->name);
 382:				ret = 0;
 383:				goto end;
 384:			} else {
 385:				ret = -EBUSY;
 386:				goto end;
 387:			}
 388:		}
 389:	
]

266/2 2026/07/30 13:02 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 50227
							output: 50
							thoughts: 17
						

Thoughts:
Okay, here's my interpretation of that thought process, tailored for an expert audience, and written in the first person:

**Navigating the USB Landscape**

Alright, hold on a second. I'm deep into this analysis, and I've hit a point where I need to take a step back and specifically examine something. The flow I'm tracing... something feels a little off. I need to zero in on a particular event to get a clearer picture of what's happening. The specific artifact I require right now is `au0828_usb_disconnect`. That's where I need to focus my attention. It's that critical point where the USB connection is severed, and I need to see *precisely* what the system is doing, or not doing, at that juncture. I suspect that's the key to understanding this current, elusive issue. Time to drill down.



267/2 2026/07/30 13:02 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-core.c FirstLine:400 LineCount:100]

Results:
map[Contents: 400:			ret = -ENODEV;
 401:			goto end;
 402:		}
 403:	
 404:		/* activate link between source and sink and start pipeline */
 405:		source = found_link->source->entity;
 406:		ret = __media_entity_setup_link(found_link, MEDIA_LNK_FL_ENABLED);
 407:		if (ret) {
 408:			pr_err("Activate link from %s->%s. Error %d\n",
 409:				source->name, sink->name, ret);
 410:			goto end;
 411:		}
 412:	
 413:		ret = __media_pipeline_start(entity->pads, pipe);
 414:		if (ret) {
 415:			pr_err("Start Pipeline: %s->%s Error %d\n",
 416:				source->name, entity->name, ret);
 417:			ret = __media_entity_setup_link(found_link, 0);
 418:			if (ret)
 419:				pr_err("Deactivate link Error %d\n", ret);
 420:			goto end;
 421:		}
 422:	
 423:		/* save link state to allow audio and video share the link
 424:		 * and not disable the link while the other is using it.
 425:		 * active_link_owner is used to deactivate the link.
 426:		*/
 427:		dev->active_link = found_link;
 428:		dev->active_link_owner = entity;
 429:		dev->active_source = source;
 430:		dev->active_sink = sink;
 431:	
 432:		pr_info("Enabled Source: %s->%s->%s Ret %d\n",
 433:			 dev->active_source->name, dev->active_sink->name,
 434:			 dev->active_link_owner->name, ret);
 435:	end:
 436:		pr_debug("%s end: ent:%s fnc:%d ret %d\n",
 437:			 __func__, entity->name, entity->function, ret);
 438:		return ret;
 439:	}
 440:	
 441:	/* Callers should hold graph_mutex */
 442:	static void au0828_disable_source(struct media_entity *entity)
 443:	{
 444:		int ret = 0;
 445:		struct media_device *mdev = entity->graph_obj.mdev;
 446:		struct au0828_dev *dev;
 447:	
 448:		if (!mdev)
 449:			return;
 450:	
 451:		dev = mdev->source_priv;
 452:	
 453:		if (!dev->active_link)
 454:			return;
 455:	
 456:		/* link is active - stop pipeline from source
 457:		 * (tuner/s-video/Composite) to the entity
 458:		 * When DVB/s-video/Composite owns tuner, it won't be in
 459:		 * shared state.
 460:		 */
 461:		if (dev->active_link->sink->entity == dev->active_sink &&
 462:		    dev->active_link->source->entity == dev->active_source) {
 463:			/*
 464:			 * Prevent video from deactivating link when audio
 465:			 * has active pipeline and vice versa. In addition
 466:			 * handle the case when more than one video/vbi
 467:			 * application is sharing the link.
 468:			*/
 469:			bool owner_is_audio = false;
 470:	
 471:			if (dev->active_link_owner->function ==
 472:			    MEDIA_ENT_F_AUDIO_CAPTURE)
 473:				owner_is_audio = true;
 474:	
 475:			if (dev->active_link_shared) {
 476:				pr_debug("Shared link owner %s user %s %d\n",
 477:					 dev->active_link_owner->name,
 478:					 entity->name, dev->users);
 479:	
 480:				/* Handle video device users > 1
 481:				 * When audio owns the shared link with
 482:				 * more than one video users, avoid
 483:				 * disabling the source and/or switching
 484:				 * the owner until the last disable_source
 485:				 * call from video _close(). Use dev->users to
 486:				 * determine when to switch/disable.
 487:				 */
 488:				if (dev->active_link_owner != entity) {
 489:					/* video device has users > 1 */
 490:					if (owner_is_audio && dev->users > 1)
 491:						return;
 492:	
 493:					dev->active_link_user = NULL;
 494:					dev->active_link_user_pipe = NULL;
 495:					dev->active_link_shared = false;
 496:					return;
 497:				}
 498:	
 499:				/* video owns the link and has users > 1 */
]

268/2 2026/07/30 13:02 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 51988
							output: 23
							thoughts: 18
						

Thoughts:
Here's my thought process, summarized as you requested:

**Navigating the Digital Landscape: The Quest for `au0828_usb_disconnect`**

Okay, hold on a second. Before I get too deep into this, I need to take a step back and make sure I have all the pieces I need. My immediate priority is to locate information regarding `au0828_usb_disconnect`. This function, or code snippet, is crucial for understanding a specific aspect of this project, I'm sure of it. I need to find context, definitions, and any relevant documentation. My experience tells me that this search will probably be the key to unlocking the right answers. Let's see what I can uncover, and what that tells me.



269/2 2026/07/30 13:02 tool grepper
0m Args:
map[Expression:au0828_usb_disconnect]

Results:
map[Output:drivers/media/usb/au0828/au0828-core.c=153=void au0828_usb_release(struct au0828_dev *dev)
--
drivers/media/usb/au0828/au0828-core.c-162-
drivers/media/usb/au0828/au0828-core.c:163:static void au0828_usb_disconnect(struct usb_interface *interface)
drivers/media/usb/au0828/au0828-core.c-164-{
--
drivers/media/usb/au0828/au0828-core.c=643=static int au0828_usb_probe(struct usb_interface *interface,
--
drivers/media/usb/au0828/au0828-core.c-718-	 * Store the pointer to the au0828_dev so it can be accessed in
drivers/media/usb/au0828/au0828-core.c:719:	 * au0828_usb_disconnect
drivers/media/usb/au0828/au0828-core.c-720-	 */
--
drivers/media/usb/au0828/au0828-core.c-749-	if (retval < 0)
drivers/media/usb/au0828/au0828-core.c:750:		au0828_usb_disconnect(interface);
drivers/media/usb/au0828/au0828-core.c-751-
--
drivers/media/usb/au0828/au0828-core.c=797=static struct usb_driver au0828_usb_driver = {
--
drivers/media/usb/au0828/au0828-core.c-799-	.probe		= au0828_usb_probe,
drivers/media/usb/au0828/au0828-core.c:800:	.disconnect	= au0828_usb_disconnect,
drivers/media/usb/au0828/au0828-core.c-801-	.id_table	= au0828_usb_id_table,
]

270/2 2026/07/30 13:02 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 52797
							output: 49
							thoughts: 15
						

Thoughts:
Okay, here we go...

**Diving into au0828_usb_disconnect**

Alright, let's get down to brass tacks. The prompt says "Let's read `au0828_usb_disconnect`". So, my immediate thought is, "Okay, another delve into a USB disconnect function. Given my experience, I'm expecting this is going to be a crucial piece of the driver, the linchpin that gracefully handles the removal of a USB device associated with the au0828, which I know is a popular USB device often used for video capture. I'm already anticipating the nuances of resource management that I'll need to dissect – deallocating buffers, resetting hardware, and ensuring that no race conditions arise in the driver with other threads. "

"I need to understand this disconnect procedure completely. Was this written to handle hot-plug removal? How robust is this code? Is it a bare-bones implementation, or does it incorporate sophisticated error handling and state management? I need to look for typical USB disconnection steps: issuing an `usb_kill_urb`, cancelling pending transfers, releasing any claimed USB interfaces, and potentially resetting hardware components related to the au0828. I also want to make sure the right cleanup happens, like properly shutting down the video stream and releasing all the resources so the system isn't left in a bad state."

"I hope this code doesn't leave any dangling pointers, unreleased mutexes, or orphaned memory allocations. My goal is to ensure this disconnect routine is bulletproof and doesn't introduce any instability into the system. It would also be good to think about the situation where the user unplugs the USB cable while the device is in the middle of operation. I need to keep that kind of situation in mind."



271/2 2026/07/30 13:02 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-core.c FirstLine:160 LineCount:50]

Results:
map[Contents: 160:		kfree(dev);
 161:	}
 162:	
 163:	static void au0828_usb_disconnect(struct usb_interface *interface)
 164:	{
 165:		struct au0828_dev *dev = usb_get_intfdata(interface);
 166:	
 167:		dprintk(1, "%s()\n", __func__);
 168:	
 169:		/* there is a small window after disconnect, before
 170:		   dev->usbdev is NULL, for poll (e.g: IR) try to access
 171:		   the device and fill the dmesg with error messages.
 172:		   Set the status so poll routines can check and avoid
 173:		   access after disconnect.
 174:		*/
 175:		set_bit(DEV_DISCONNECTED, &dev->dev_state);
 176:	
 177:		au0828_rc_unregister(dev);
 178:		/* Digital TV */
 179:		au0828_dvb_unregister(dev);
 180:	
 181:		usb_set_intfdata(interface, NULL);
 182:		mutex_lock(&dev->mutex);
 183:		dev->usbdev = NULL;
 184:		mutex_unlock(&dev->mutex);
 185:		if (au0828_analog_unregister(dev)) {
 186:			/*
 187:			 * No need to call au0828_usb_release() if V4L2 is enabled,
 188:			 * as this is already called via au0828_usb_v4l2_release()
 189:			 */
 190:			return;
 191:		}
 192:		au0828_usb_release(dev);
 193:	}
 194:	
 195:	static int au0828_media_device_init(struct au0828_dev *dev,
 196:					    struct usb_device *udev)
 197:	{
 198:	#ifdef CONFIG_MEDIA_CONTROLLER
 199:		struct media_device *mdev;
 200:	
 201:		mdev = media_device_usb_allocate(udev, KBUILD_MODNAME, THIS_MODULE);
 202:		if (IS_ERR(mdev))
 203:			return PTR_ERR(mdev);
 204:	
 205:		dev->media_dev = mdev;
 206:	#endif
 207:		return 0;
 208:	}
 209:	
]

272/2 2026/07/30 13:02 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 53986
							output: 50
							thoughts: 54
						

Thoughts:
**Analyzing the USB Disconnect Flow**

Okay, so I'm looking at this `au0828_usb_disconnect` function. Something immediately jumps out at me: it calls `au0828_analog_unregister(dev)`. And *crucially*, it returns early if that function returns true. This is important to catch. I need to understand what situations lead to `au0828_analog_unregister` returning true, because that's where the control flow diverges. I need to understand if this could cause issues. Alright, so I need to dig into the `au0828_analog_unregister` function to figure out what's going on. Let's see what that does...



273/2 2026/07/30 13:02 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-video.c FirstLine:1890 LineCount:50]

Results:
map[Contents:1890:			switch (AUVI_INPUT(i).type) {
1891:			case AU0828_VMUX_COMPOSITE:
1892:				ent->function = MEDIA_ENT_F_CONN_COMPOSITE;
1893:				break;
1894:			case AU0828_VMUX_SVIDEO:
1895:				ent->function = MEDIA_ENT_F_CONN_SVIDEO;
1896:				break;
1897:			case AU0828_VMUX_CABLE:
1898:			case AU0828_VMUX_TELEVISION:
1899:			case AU0828_VMUX_DVB:
1900:			default: /* Just to shut up a warning */
1901:				ent->function = MEDIA_ENT_F_CONN_RF;
1902:				break;
1903:			}
1904:	
1905:			ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]);
1906:			if (ret < 0)
1907:				pr_err("failed to initialize input pad[%d]!\n", i);
1908:	
1909:			ret = media_device_register_entity(dev->media_dev, ent);
1910:			if (ret < 0)
1911:				pr_err("failed to register input entity %d!\n", i);
1912:		}
1913:	#endif
1914:	}
1915:	
1916:	/**************************************************************************/
1917:	
1918:	int au0828_analog_register(struct au0828_dev *dev,
1919:				   struct usb_interface *interface)
1920:	{
1921:		int retval = -ENOMEM;
1922:		struct usb_host_interface *iface_desc;
1923:		struct usb_endpoint_descriptor *endpoint;
1924:		int i, ret;
1925:	
1926:		dprintk(1, "au0828_analog_register called for intf#%d!\n",
1927:			interface->cur_altsetting->desc.bInterfaceNumber);
1928:	
1929:		/* No analog TV */
1930:		if (AUVI_INPUT(0).type == AU0828_VMUX_UNDEFINED)
1931:			return 0;
1932:	
1933:		/* set au0828 usb interface0 to as5 */
1934:		retval = usb_set_interface(dev->usbdev,
1935:				interface->cur_altsetting->desc.bInterfaceNumber, 5);
1936:		if (retval != 0) {
1937:			pr_info("Failure setting usb interface0 to as5\n");
1938:			return retval;
1939:		}
]

274/2 2026/07/30 13:02 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 55053
							output: 23
							thoughts: 17
						

Thoughts:
Okay, here's my thought process on that:

**Hunting Down `au0828_analog_unregister`**

Right, so I need to find the definition or usage of `au0828_analog_unregister`. It’s a pretty specific function name, so I'm guessing it’s related to the `au0828` driver, which from the name alone I suspect it has something to do with audio or analog video, probably in the context of a particular embedded or system-level implementation. My initial approach will be to locate the source code. I'll probably start with a `grep` or `find` across the relevant kernel source directories if I have access to it, or if it's a closed source, I will need to search the documentation and API references. I will be looking for header files, C files, or makefiles that reference this function. Once I pinpoint the file, I can then use a code editor or IDE with cross-referencing capabilities to find its declaration, implementation, and most importantly, where and how it's used within the driver or related subsystems. The context of its use will give me clues about its purpose - is it part of device uninitialization, resource cleanup, or maybe some kind of analog signal deactivation? My goal is to understand how the system interacts with the device. If it's a kernel function, I'll need to understand the surrounding code to determine how it is implemented and its dependencies. If it's a user-space function, I'll need to check the build process to understand its location and dependencies.



275/2 2026/07/30 13:02 tool grepper
0m Args:
map[Expression:au0828_analog_unregister]

Results:
map[Output:drivers/media/usb/au0828/au0828-core.c=163=static void au0828_usb_disconnect(struct usb_interface *interface)
--
drivers/media/usb/au0828/au0828-core.c-184-	mutex_unlock(&dev->mutex);
drivers/media/usb/au0828/au0828-core.c:185:	if (au0828_analog_unregister(dev)) {
drivers/media/usb/au0828/au0828-core.c-186-		/*
--
drivers/media/usb/au0828/au0828-video.c=911=static const struct vb2_ops au0828_video_qops = {
--
drivers/media/usb/au0828/au0828-video.c-923-/*
drivers/media/usb/au0828/au0828-video.c:924: * au0828_analog_unregister
drivers/media/usb/au0828/au0828-video.c-925- * unregister v4l2 devices
drivers/media/usb/au0828/au0828-video.c-926- */
drivers/media/usb/au0828/au0828-video.c:927:int au0828_analog_unregister(struct au0828_dev *dev)
drivers/media/usb/au0828/au0828-video.c-928-{
drivers/media/usb/au0828/au0828-video.c:929:	dprintk(1, "au0828_analog_unregister called\n");
drivers/media/usb/au0828/au0828-video.c-930-
--
drivers/media/usb/au0828/au0828.h=327=extern int au0828_analog_register(struct au0828_dev *dev,
drivers/media/usb/au0828/au0828.h-328-			   struct usb_interface *interface);
drivers/media/usb/au0828/au0828.h:329:extern int au0828_analog_unregister(struct au0828_dev *dev);
drivers/media/usb/au0828/au0828.h-330-extern void au0828_usb_v4l2_media_release(struct au0828_dev *dev);
--
drivers/media/usb/au0828/au0828.h=337=static inline int au0828_analog_register(struct au0828_dev *dev,
--
drivers/media/usb/au0828/au0828.h-339-{ return 0; };
drivers/media/usb/au0828/au0828.h:340:static inline int au0828_analog_unregister(struct au0828_dev *dev)
drivers/media/usb/au0828/au0828.h-341-{ return 0; };
]

276/2 2026/07/30 13:02 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 56275
							output: 49
							thoughts: 15
						

Thoughts:
Okay, here's my take on those thoughts, tailored for an expert audience:

**Analyzing the `au0828_analog_unregister` Function**

Alright, let's dive into the `au0828_analog_unregister` function. My initial thought is to understand its role within the broader context of the `au0828` driver. It's safe to assume, given the naming, that this function is responsible for cleanly detaching and releasing resources associated with the analog component of the `au0828` device. This is crucial for proper device lifecycle management – preventing memory leaks, dangling pointers, and potential conflicts with other drivers or system components.

I'll be looking for key aspects:

*   **Resource Deallocation:** What specific analog resources are being freed? Is it I/O memory mappings, interrupt handlers, DMA channels, or potentially power management contexts? I need to ascertain the level of granularity in its clean up.
*   **Driver Unregistration:** How is the analog component unregistered from the larger `au0828` driver structure? Is there a cascading effect, unregistering sub-components as well?
*   **Error Handling:** What kind of error checking is implemented? Does it handle situations where resources are already deallocated or where the unregistration fails midway? Are there any return codes or error messages that need attention?
*   **Synchronization:** How does it handle potential concurrent access or interrupts during the unregistration process? Are there mutexes, spinlocks, or other synchronization primitives in place to prevent race conditions? I expect there to be a careful locking strategy.
*   **Power Management:** Is there any interaction with power management interfaces to put the analog component into a low-power state or shut it down completely? This is critical for battery-powered systems or scenarios where the device can be inactive.
*   **Contextual Considerations:** What about the context that this unregistration happens within? Is it always from a user thread, a kernel thread, or an interrupt handler? The context will influence what strategies are possible.

I'll be paying close attention to any dependencies on other functions or data structures within the `au0828` driver. Understanding these relationships is vital to ensure that the unregistration process is complete and doesn't leave the system in an inconsistent state. My aim is to achieve a deep and holistic understanding of its purpose, the risks of using it and the potential failures.



277/2 2026/07/30 13:03 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-video.c FirstLine:920 LineCount:50]

Results:
map[Contents: 920:	/* ------------------------------------------------------------------
 921:	   V4L2 interface
 922:	   ------------------------------------------------------------------*/
 923:	/*
 924:	 * au0828_analog_unregister
 925:	 * unregister v4l2 devices
 926:	 */
 927:	int au0828_analog_unregister(struct au0828_dev *dev)
 928:	{
 929:		dprintk(1, "au0828_analog_unregister called\n");
 930:	
 931:		/* No analog TV */
 932:		if (AUVI_INPUT(0).type == AU0828_VMUX_UNDEFINED)
 933:			return 0;
 934:	
 935:		mutex_lock(&au0828_sysfs_lock);
 936:		vb2_video_unregister_device(&dev->vdev);
 937:		vb2_video_unregister_device(&dev->vbi_dev);
 938:		mutex_unlock(&au0828_sysfs_lock);
 939:	
 940:		v4l2_device_disconnect(&dev->v4l2_dev);
 941:		v4l2_device_put(&dev->v4l2_dev);
 942:	
 943:		return 1;
 944:	}
 945:	
 946:	/* This function ensures that video frames continue to be delivered even if
 947:	   the ITU-656 input isn't receiving any data (thereby preventing applications
 948:	   such as tvtime from hanging) */
 949:	static void au0828_vid_buffer_timeout(struct timer_list *t)
 950:	{
 951:		struct au0828_dev *dev = timer_container_of(dev, t, vid_timeout);
 952:		struct au0828_dmaqueue *dma_q = &dev->vidq;
 953:		struct au0828_buffer *buf;
 954:		unsigned char *vid_data;
 955:		unsigned long flags = 0;
 956:	
 957:		spin_lock_irqsave(&dev->slock, flags);
 958:	
 959:		buf = dev->isoc_ctl.buf;
 960:		if (buf != NULL) {
 961:			vid_data = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
 962:			memset(vid_data, 0x00, buf->length); /* Blank green frame */
 963:			buffer_filled(dev, dma_q, buf);
 964:		}
 965:		get_next_buf(dma_q, &buf);
 966:	
 967:		if (dev->vid_timeout_running == 1)
 968:			mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
 969:	
]

278/2 2026/07/30 13:03 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 57704
							output: 49
							thoughts: 249
						

Thoughts:
**Analyzing the Analog Unregistration and USB Release Logic**

Okay, so I'm looking at this `au0828_usb_disconnect` function and something's bugging me. Specifically, I'm focusing on the interaction between `au0828_analog_unregister` and `au0828_usb_release`. It looks like `au0828_analog_unregister` returns `1` when `AUVI_INPUT(0).type` is *not* `AU0828_VMUX_UNDEFINED`. Now, if that function returns `1`, the entire `au0828_usb_disconnect` function simply returns early. That means the subsequent call to `au0828_usb_release(dev)` is *skipped*. Hmm.

But...wait a minute. I know `au0828_usb_release(dev)` *is* called elsewhere, specifically within `au0828_usb_v4l2_release()` when the last V4L2 device is closed. So, if `au0828_analog_unregister` fails (returns 1) and we return early, we *shouldn't* have an issue. Because the cleanup is handled by V4L2.

I need to confirm this assumption. The key is in understanding how `au0828_usb_v4l2_release` is interacting. I need to make sure my understanding of this control flow is correct. Time to dig into `au0828_usb_v4l2_release`!



279/2 2026/07/30 13:03 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-core.c FirstLine:140 LineCount:50]

Results:
map[Contents: 140:	
 141:		/* clear enable_source, disable_source */
 142:		mutex_lock(&mdev->graph_mutex);
 143:		dev->media_dev->source_priv = NULL;
 144:		dev->media_dev->enable_source = NULL;
 145:		dev->media_dev->disable_source = NULL;
 146:		mutex_unlock(&mdev->graph_mutex);
 147:	
 148:		media_device_delete(dev->media_dev, KBUILD_MODNAME, THIS_MODULE);
 149:		dev->media_dev = NULL;
 150:	#endif
 151:	}
 152:	
 153:	void au0828_usb_release(struct au0828_dev *dev)
 154:	{
 155:		au0828_unregister_media_device(dev);
 156:	
 157:		/* I2C */
 158:		au0828_i2c_unregister(dev);
 159:	
 160:		kfree(dev);
 161:	}
 162:	
 163:	static void au0828_usb_disconnect(struct usb_interface *interface)
 164:	{
 165:		struct au0828_dev *dev = usb_get_intfdata(interface);
 166:	
 167:		dprintk(1, "%s()\n", __func__);
 168:	
 169:		/* there is a small window after disconnect, before
 170:		   dev->usbdev is NULL, for poll (e.g: IR) try to access
 171:		   the device and fill the dmesg with error messages.
 172:		   Set the status so poll routines can check and avoid
 173:		   access after disconnect.
 174:		*/
 175:		set_bit(DEV_DISCONNECTED, &dev->dev_state);
 176:	
 177:		au0828_rc_unregister(dev);
 178:		/* Digital TV */
 179:		au0828_dvb_unregister(dev);
 180:	
 181:		usb_set_intfdata(interface, NULL);
 182:		mutex_lock(&dev->mutex);
 183:		dev->usbdev = NULL;
 184:		mutex_unlock(&dev->mutex);
 185:		if (au0828_analog_unregister(dev)) {
 186:			/*
 187:			 * No need to call au0828_usb_release() if V4L2 is enabled,
 188:			 * as this is already called via au0828_usb_v4l2_release()
 189:			 */
]

280/2 2026/07/30 13:03 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 59127
							output: 48
							thoughts: 421
						

Thoughts:
**The Eureka Moment!**

Yes! The `au0828_usb_release` function *does* call `au0828_i2c_unregister(dev)`! This is key. And, crucially, `au0828_usb_release` is called when the V4L2 device associated with the USB device is closed. So, if I open the V4L2 device, disconnect the USB device, the I2C adapter *isn't* unregistered! The USB core then goes ahead and frees the USB device. And then, here's the kicker: I can perform an I2C transaction on the I2C adapter, which will attempt to dereference `adapter->dev.parent->type` which is actually `usbdev->type`! Boom! This is *exactly* the bug! The classic use-after-free!

Perfect. This makes the `au0828` driver an ideal target. I need to construct a solid reproducer for this.

Let's see. I need to use `syz_usb_connect`, and the Vendor ID (`idVendor`) must be `0x2040`, and the Product ID (`idProduct`) is `0x7200`. Wait, I need to make sure the `bInterfaceNumber` of the device to be probed is `0`, because `au0828_usb_probe` checks `ifnum != 0`. Then the USB device speed must be `USB_SPEED_HIGH`, which equates to `3`.

Now, let's double-check `au0828_analog_register`. The code verifies that `AUVI_INPUT(0).type == AU0828_VMUX_UNDEFINED`. `AUVI_INPUT` uses `dev->board`. And `dev->boardnr` is assigned from `id->driver_info`. Looking at `au0828_usb_id_table`, the combination `0x2040:0x7200` maps to `AU0828_BOARD_HAUPPAUGE_HVR950Q`. Now, let's verify what `au0828_boards[AU0828_BOARD_HAUPPAUGE_HVR950Q]` contains... This is coming together nicely!



281/2 2026/07/30 13:03 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-cards.c FirstLine:40 LineCount:50]

Results:
map[Contents:  40:			.has_ir_i2c = 1,
  41:			.has_analog = 1,
  42:			.i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
  43:			.input = {
  44:				{
  45:					.type = AU0828_VMUX_TELEVISION,
  46:					.vmux = AU8522_COMPOSITE_CH4_SIF,
  47:					.amux = AU8522_AUDIO_SIF,
  48:				},
  49:				{
  50:					.type = AU0828_VMUX_COMPOSITE,
  51:					.vmux = AU8522_COMPOSITE_CH1,
  52:					.amux = AU8522_AUDIO_NONE,
  53:					.audio_setup = hvr950q_cs5340_audio,
  54:				},
  55:				{
  56:					.type = AU0828_VMUX_SVIDEO,
  57:					.vmux = AU8522_SVIDEO_CH13,
  58:					.amux = AU8522_AUDIO_NONE,
  59:					.audio_setup = hvr950q_cs5340_audio,
  60:				},
  61:			},
  62:		},
  63:		[AU0828_BOARD_HAUPPAUGE_HVR950Q] = {
  64:			.name	= "Hauppauge HVR950Q",
  65:			.tuner_type = TUNER_XC5000,
  66:			.tuner_addr = 0x61,
  67:			.has_ir_i2c = 1,
  68:			.has_analog = 1,
  69:			.i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
  70:			.input = {
  71:				{
  72:					.type = AU0828_VMUX_TELEVISION,
  73:					.vmux = AU8522_COMPOSITE_CH4_SIF,
  74:					.amux = AU8522_AUDIO_SIF,
  75:				},
  76:				{
  77:					.type = AU0828_VMUX_COMPOSITE,
  78:					.vmux = AU8522_COMPOSITE_CH1,
  79:					.amux = AU8522_AUDIO_NONE,
  80:					.audio_setup = hvr950q_cs5340_audio,
  81:				},
  82:				{
  83:					.type = AU0828_VMUX_SVIDEO,
  84:					.vmux = AU8522_SVIDEO_CH13,
  85:					.amux = AU8522_AUDIO_NONE,
  86:					.audio_setup = hvr950q_cs5340_audio,
  87:				},
  88:			},
  89:		},
]

282/2 2026/07/30 13:03 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 60968
							output: 35
							thoughts: 808
						

Thoughts:
**Analyzing the USB Device Driver Probe**

Okay, so I'm looking at this probe function and the first thing I see is that `input[0].type` is definitely the right kind of television device. Great, so far so good. It looks like the driver then calls `au0828_analog_register`, which is where things get interesting. It's trying to set the USB interface 0 to alternate setting 5. If the USB interface doesn't *have* alternate setting 5, this `usb_set_interface` will fail and the entire `au0828_analog_register` will return an error, which in turn means the probe function, `au0828_usb_probe`, will fail! The failure will jump to a cleanup routine that disconnects the device and returns the error code. The device will *not* be registered.

So, I absolutely MUST ensure that alternate setting 5 exists for interface 0. The key is the `usb_interface_descriptor` and its `bAlternateSetting` field. I need to provide multiple of these descriptors for the same `bInterfaceNumber` (0), covering alternate settings from 0 through 5.

Now, let's see how I can do that using syzkaller. I see the `usb_config_descriptor_verbose_t` struct, and it has an `interfaces` field, which is an array of `usb_interface_descriptor`, but the documentation seems to limit it to 1-4. That's a problem! I need 6 alternate settings, but I only have the ability to supply 4 interface descriptors according to the documentation.

Wait, the `usb_interface_descriptor` actually *represents* an alternate setting! It's not a general interface description. So I can provide 6 `usb_interface_descriptor`s for interface 0, each with a different `bAlternateSetting` value.

However, the syzkaller limitation remains. The struct `usb_config_descriptor_ifaces_array_t` limits the number of interface descriptors. Hmmm, the `ANY` keyword might bypass this array size limit. Wait! I can also just use `syz_usb_connect` with `ANY`.

But then, `syz_usb_connect` takes `dev ptr[in, usb_device_descriptor]`. If I just pass a byte array, it will say "wrong struct arg".

But wait! `syz_usb_connect` has a special video version too, `syz_usb_connect$video`! It takes a `usb_device_descriptor_video` structure. Does that one have a way to specify alternate settings? Let me check the documentation ("vusb.txt") for the `usb_device_descriptor_video`...



283/2 2026/07/30 13:03 tool read-file
0m Error:
log-in to see details

Args:
map[File:sys/linux/vusb.txt FirstLine:1 LineCount:100]

Results:
map[Contents:]

284/2 2026/07/30 13:03 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 62426
							output: 37
							thoughts: 17
						

Thoughts:
Here's my attempt at summarizing the thought process, tailored for an expert audience:

**Analyzing the `sys/linux/dev_vusb.txt` Context**

Okay, here we go. The filename, `sys/linux/dev_vusb.txt`, immediately pegs this as a potentially crucial piece of documentation or configuration related to USB virtual devices within a Linux kernel environment. The "sys" prefix suggests a kernel-level configuration or device information file, so I'm already thinking about device nodes, sysfs entries, or even kernel command-line parameters that influence virtual USB device behavior. The "dev" part is obviously about devices, and "vusb" screams "virtual USB," which implies emulated USB devices, likely used for testing, virtualization, or maybe even advanced embedded systems with USB gadget capabilities. My mind's now running through potential scenarios: Is this about the `g_cdc` driver, a custom virtual USB Ethernet device, or something completely custom? I’m immediately trying to assess the likely age of the information. "vusb" has been around a while; I'm betting on a moderately recent version of the kernel. I’m prepared for a deeper dive and I'm ready to figure out the use case.



285/2 2026/07/30 13:03 tool read-file
0m Error:
log-in to see details

Args:
map[File:sys/linux/dev_vusb.txt FirstLine:1 LineCount:100]

Results:
map[Contents:]

286/2 2026/07/30 13:03 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 62758
							output: 19
							thoughts: 12
						

Thoughts:
Okay, here's my attempt at summarizing the thought process, as if it were my own, assuming I'm an expert in the field:

**Eureka! A Tool for This Task**

Right, let me think this through. I'm dealing with a textual task, a description to be read and understood. There has to be a way to avoid manually analyzing this text. Wait a minute... of course! I can use a tool I developed. This situation calls for the `read-description` tool! That's perfect. This is ideal; It’ll handle this task flawlessly. I can use my specialized tool to simplify this task.



287/2 2026/07/30 13:03 tool read-description
0m Args:
map[File:vusb.txt]

Results:
map[Output:# Copyright 2019 syzkaller project authors. All rights reserved.
# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

include <linux/types.h>
include <linux/byteorder/generic.h>

include <uapi/linux/usb/ch9.h>
include <uapi/linux/usb/ch11.h>

include <uapi/linux/usb/midi.h>
include <uapi/linux/usb/audio.h>
include <linux/usb/audio-v2.h>
include <linux/usb/audio-v3.h>
include <uapi/linux/hid.h>
include <linux/hid.h>
include <uapi/linux/usb/cdc.h>
include <uapi/linux/if_ether.h>
include <linux/interrupt.h>
include <linux/usb/cdc_ncm.h>
include <drivers/net/usb/asix.h>

# This is a special fd for USB fuzzing and should only be used with syz_usb_* pseudo-syscalls.
# We don't inherit it from the fd resource, to discourage syzkaller calling raw ioctls on it.
resource fd_usb[int32]: -1

# These are generic pseudo-syscalls for emulating arbitrary USB devices.
# They are mostly targeted to cover the enumeration process.
syz_usb_connect(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io(fd fd_usb, descs ptr[in, vusb_descriptors], resps ptr[in, vusb_responses]) (timeout[300], remote_cover)
syz_usb_ep_write(fd fd_usb, ep int8, len len[data], data ptr[in, array[int8, 0:256]]) (timeout[300], remote_cover)
syz_usb_ep_read(fd fd_usb, ep int8, len len[data], data buffer[out]) (timeout[300], remote_cover)
syz_usb_disconnect(fd fd_usb) (timeout[300], remote_cover)

usb_device_speed = USB_SPEED_UNKNOWN, USB_SPEED_LOW, USB_SPEED_FULL, USB_SPEED_HIGH, USB_SPEED_WIRELESS, USB_SPEED_SUPER, USB_SPEED_SUPER_PLUS

# TODO: consider patching idVendor and idProduct for all class specific descriptions in Go code to cover more drivers.
# TODO: custom syz_usb_ep_write() descriptions for all class specific descriptions.
# TODO: consider adding custom vusb_connect_descriptors definitions to all class specific descriptions.

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

type usb_device_descriptor_verbose_t[USB, CLASS, SUBCLASS, PROTOCOL, PACKET, VENDOR, PRODUCT, DEVICE, CFS] {
	bLength			const[USB_DT_DEVICE_SIZE, int8]
	bDescriptorType		const[USB_DT_DEVICE, int8]

	bcdUSB			USB
	bDeviceClass		const[CLASS, int8]
	bDeviceSubClass		const[SUBCLASS, int8]
	bDeviceProtocol		const[PROTOCOL, int8]
	bMaxPacketSize0		PACKET
	idVendor		const[VENDOR, int16]
	idProduct		const[PRODUCT, int16]
	bcdDevice		const[DEVICE, int16]
	iManufacturer		const[1, int8]
	iProduct		const[2, int8]
	iSerialNumber		const[3, int8]
	bNumConfigurations	len[configs, int8]

	configs			CFS
} [packed]

type usb_device_descriptor_t[CLASS, SUBCLASS, PROTOCOL, VENDOR, PRODUCT, DEVICE, CFS] usb_device_descriptor_verbose_t[flags[usb_versions, int16], CLASS, SUBCLASS, PROTOCOL, flags[usb_device_max_packet_sizes, int8], VENDOR, PRODUCT, DEVICE, CFS]
type usb_device_descriptor_fixed_t[USB, CLASS, SUBCLASS, PROTOCOL, PACKET, VENDOR, PRODUCT, DEVICE, CFS] usb_device_descriptor_verbose_t[const[USB, int16], CLASS, SUBCLASS, PROTOCOL, const[PACKET, int8], VENDOR, PRODUCT, DEVICE, CFS]

usb_versions = 0x110, 0x200, 0x201, 0x250, 0x300, 0x310

# https://elixir.bootlin.com/linux/v5.1.7/source/drivers/usb/core/hub.c#L4661
usb_device_max_packet_sizes = 8, 16, 32, 64, 255

type usb_config_descriptor_verbose_t[NUM, IFSNUM, ICONFIG, ATTRS, POWER, EXTRA, IFS] {
	bLength			const[USB_DT_CONFIG_SIZE, int8]
	bDescriptorType		const[USB_DT_CONFIG, int8]

	wTotalLength		len[parent, int16]
	bNumInterfaces		IFSNUM
	bConfigurationValue	NUM
	iConfiguration		ICONFIG
	bmAttributes		ATTRS
	bMaxPower		POWER

	extra			EXTRA
	interfaces		IFS
} [packed]

type usb_config_descriptor_t[NUM, IFSNUM, IFS] usb_config_descriptor_verbose_t[NUM, IFSNUM, int8, flags[usb_config_attributes, int8], int8, void, IFS]
type usb_config_descriptor_ifaces_array_t[NUM, IFS] usb_config_descriptor_t[NUM, len[interfaces, int8], IFS]
type usb_config_descriptor_fixed_t[NUM, IFSNUM, ATTRS, POWER, IFS] usb_config_descriptor_verbose_t[const[NUM, int8], const[IFSNUM, int8], const[0, int8], const[ATTRS, int8], const[POWER, int8], void, IFS]
type usb_config_descriptor_extra_t[NUM, IFSNUM, EXTRA, IFS] usb_config_descriptor_verbose_t[NUM, IFSNUM, int8, flags[usb_config_attributes, int8], int8, EXTRA, IFS]

type usb_interface_descriptor_verbose_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, IIF, EXTRA, EPS] {
	bLength			const[USB_DT_INTERFACE_SIZE, int8]
	bDescriptorType		const[USB_DT_INTERFACE, int8]

	bInterfaceNumber	IFNUM
	bAlternateSetting	ALTNUM
	bNumEndpoints		EPSNUM
	bInterfaceClass		CLASS
	bInterfaceSubClass	SUBCLASS
	bInterfaceProtocol	PROTOCOL
	iInterface		IIF

	extra			EXTRA
	endpoints		EPS
} [packed]

type usb_interface_descriptor_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS] usb_interface_descriptor_verbose_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, int8, EXTRA, EPS]
type usb_interface_descriptor_eps_array_t[IFNUM, ALTNUM, CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS] usb_interface_descriptor_t[IFNUM, ALTNUM, len[endpoints, int8], CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS]
type usb_interface_descriptor_fixed_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS] usb_interface_descriptor_verbose_t[const[IFNUM, int8], const[ALTNUM, int8], const[EPSNUM, int8], const[CLASS, int8], const[SUBCLASS, int8], const[PROTOCOL, int8], const[0, int8], EXTRA, EPS]

# TODO: non-audio endpoints have USB_DT_ENDPOINT_SIZE.
type usb_endpoint_descriptor_verbose_t[ADDR, ATTRS, PACKET, INTERVAL, REFRESH, SYNCH, EXTRA] {
	bLength			const[USB_DT_ENDPOINT_AUDIO_SIZE, int8]
	bDescriptorType		const[USB_DT_ENDPOINT, int8]

	bEndpointAddress	ADDR
	bmAttributes		ATTRS
	wMaxPacketSize		PACKET
	bInterval		INTERVAL

	bRefresh		REFRESH
	bSynchAddress		SYNCH

	extra			EXTRA
} [packed]

type usb_endpoint_descriptor_t[ADDR, ATTRS, EXTRA] usb_endpoint_descriptor_verbose_t[ADDR, ATTRS, flags[usb_endpoint_max_packet_sizes, int16], int8, int8, int8, EXTRA]
type usb_endpoint_descriptor_fixed_t[ADDR, ATTRS, PACKET, INTERVAL, EXTRA] usb_endpoint_descriptor_verbose_t[const[ADDR, int8], const[ATTRS, int8], const[PACKET, int16], const[INTERVAL, int8], const[0, int8], const[0, int8], EXTRA]

# TODO: dummy driver has complex requirements for packet sizes, account for those:
# https://elixir.bootlin.com/linux/v5.3.6/source/drivers/usb/gadget/udc/dummy_hcd.c#L497
usb_endpoint_max_packet_sizes = 8, 16, 32, 64, 512, 1023, 1024

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Generic USB device, configuration, interface and endpoint descriptors.

# We only support one configuration per device.
# bDeviceClass, bDeviceSubClass, bDeviceProtocol, idVendor, idProduct
# and bcdDevice are patched by Go code, see sys/linux/init_vusb.go.
usb_device_descriptor {
	inner	usb_device_descriptor_t[0, 0, 0, 0, 0, 0, array[usb_config_descriptor, 1]]
} [packed]

usb_config_descriptor {
	inner	usb_config_descriptor_ifaces_array_t[int8, array[usb_interface_descriptor, 1:4]]
} [packed]

usb_config_attributes = USB_CONFIG_ATT_ONE, USB_CONFIG_ATT_SELFPOWER, USB_CONFIG_ATT_WAKEUP, USB_CONFIG_ATT_BATTERY

# bInterfaceNumber, bInterfaceClass, bInterfaceSubClass and bInterfaceProtocol
# are patched by Go code, see sys/linux/init_vusb.go.
usb_interface_descriptor {
	inner	usb_interface_descriptor_eps_array_t[int8, int8, const[0, int8], const[0, int8], const[0, int8], array[usb_interface_extra_descriptor, 0:2], array[usb_endpoint_descriptor, 0:16]]
} [packed]

usb_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], flags[usb_endpoint_attributes, int8], array[usb_endpoint_extra_descriptor, 0:2]]
} [packed]

usb_endpoint_addresses = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, USB_DIR_OUT, USB_DIR_IN

usb_endpoint_attributes = USB_ENDPOINT_XFER_CONTROL, USB_ENDPOINT_XFER_ISOC, USB_ENDPOINT_XFER_BULK, USB_ENDPOINT_XFER_INT, USB_ENDPOINT_INTR_PERIODIC, USB_ENDPOINT_INTR_NOTIFICATION, USB_ENDPOINT_SYNC_NONE, USB_ENDPOINT_SYNC_ASYNC, USB_ENDPOINT_SYNC_ADAPTIVE, USB_ENDPOINT_SYNC_SYNC, USB_ENDPOINT_USAGE_DATA, USB_ENDPOINT_USAGE_FEEDBACK, USB_ENDPOINT_USAGE_FEEDBACK

vusb_connect_descriptors {
	qual_len	len[qual, int32]
	qual		ptr[in, usb_qualifier_descriptor]
	bos_len		len[bos, int32]
	bos		ptr[in, usb_bos_descriptor]
	strs_len	len[strs, int32]
	strs		array[vusb_connect_string_descriptor]
} [packed]

vusb_connect_string_descriptor {
	len	len[str, int32]
	str	ptr[in, usb_string_descriptor]
} [packed]

vusb_descriptors {
	len	len[parent, int32]
	generic	ptr[in, vusb_descriptor_generic]

	string	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
	bos	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_BOS, usb_bos_descriptor]]

	hub_hs	ptr[in, vusb_descriptor_t[USB_TYPE_CLASS, USB_DT_HUB, usb_hub_descriptor_hs]]
	hub_ss	ptr[in, vusb_descriptor_t[USB_TYPE_CLASS, USB_DT_SS_HUB, usb_hub_descriptor_ss]]
} [packed]

vusb_descriptor_generic {
	req_type	flags[usb_request_types, int8]
	desc_type	flags[usb_descriptor_types, int8]
	len		bytesize[data, int32]
	data		usb_generic_descriptor
} [packed]

usb_request_types = USB_TYPE_STANDARD, USB_TYPE_CLASS, USB_TYPE_VENDOR

type vusb_descriptor_t[CLASS, REQ, DATA] {
	type	const[CLASS, int8]
	req	const[REQ, int8]
	len	bytesize[data, int32]
	data	DATA
} [packed]

# TODO: consider doing lookups based on USB_RECIP values.
vusb_responses {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	get_interface			ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	get_configuration		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

# TODO: move these into custom descriptions for hub class when they are added.
	hub_USB_REQ_GET_STATUS_hub	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_REQ_GET_STATUS, usb_hub_status]]
	hub_USB_REQ_GET_STATUS_port	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_REQ_GET_STATUS, usb_port_status]]

# TODO: move these into custom descriptions for asix driver when they are added.
	asix_AX_CMD_READ_MII_REG	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_MII_REG, int16]]
	asix_AX_CMD_STATMNGSTS_REG	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_STATMNGSTS_REG, int8]]
	asix_AX_CMD_READ_EEPROM		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_EEPROM, array[int8, 2]]]
	asix_AX_CMD_READ_RX_CTL		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_RX_CTL, int16]]
	asix_AX_CMD_READ_NODE_ID	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_NODE_ID, mac_addr]]
	asix_AX88172_CMD_READ_NODE_ID	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX88172_CMD_READ_NODE_ID, mac_addr]]
	asix_AX_CMD_READ_PHY_ID		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_PHY_ID, array[int8, 2]]]
	asix_AX_CMD_READ_MEDIUM_STATUS	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_MEDIUM_STATUS, int16]]
	asix_AX_CMD_READ_MONITOR_MODE	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_MONITOR_MODE, int8]]
	asix_AX_CMD_READ_GPIOS		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_GPIOS, int8]]
	asix_AX_CMD_SW_PHY_STATUS	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_SW_PHY_STATUS, int8]]
} [packed]

vusb_response_generic {
	type	flags[usb_request_types, int8]
	req	flags[usb_requests, int8]
	len	bytesize[data, int32]
	data	array[int8, 0:256]
} [packed]

usb_requests = USB_REQ_GET_STATUS, USB_REQ_CLEAR_FEATURE, USB_REQ_SET_FEATURE, USB_REQ_SET_ADDRESS, USB_REQ_GET_DESCRIPTOR, USB_REQ_SET_DESCRIPTOR, USB_REQ_GET_CONFIGURATION, USB_REQ_SET_CONFIGURATION, USB_REQ_GET_INTERFACE, USB_REQ_SET_INTERFACE, USB_REQ_SYNCH_FRAME, USB_REQ_SET_SEL, USB_REQ_SET_ISOCH_DELAY, USB_REQ_SET_ENCRYPTION, USB_REQ_GET_ENCRYPTION, USB_REQ_RPIPE_ABORT, USB_REQ_SET_HANDSHAKE, USB_REQ_RPIPE_RESET, USB_REQ_GET_HANDSHAKE, USB_REQ_SET_CONNECTION, USB_REQ_SET_SECURITY_DATA, USB_REQ_GET_SECURITY_DATA, USB_REQ_SET_WUSB_DATA, USB_REQ_LOOPBACK_DATA_WRITE, USB_REQ_LOOPBACK_DATA_READ, USB_REQ_SET_INTERFACE_DS, USB_REQ_GET_PARTNER_PDO, USB_REQ_GET_BATTERY_STATUS, USB_REQ_SET_PDO, USB_REQ_GET_VDM, USB_REQ_SEND_VDM

type vusb_response_t[CLASS, REQ, DATA] {
	type	const[CLASS, int8]
	req	const[REQ, int8]
	len	bytesize[data, int32]
	data	DATA
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# USB descriptors requested by the kernel before the SET_CONFIGURATION request.

# TODO: figure out when is the USB_DT_OTG descriptor used.
# TODO: figure out when is the USB_DT_INTERFACE_ASSOCIATION descriptor used.
# TODO: figure out when is the USB_DT_BOS descriptor used.

type usb_string_descriptor_t[DATA] {
	bLength		len[parent, int8]
	bDescriptorType	const[USB_DT_STRING, int8]

	data		DATA
} [packed]

usb_string_descriptor [
	lang_id	usb_string_descriptor_t[flags[usb_lang_ids, int16]]
	string	usb_string_descriptor_t[array[int8, 0:256]]
] [varlen]

usb_lang_ids = 0x436, 0x41c, 0x401, 0x801, 0xc01, 0x1001, 0x1401, 0x1801, 0x1c01, 0x2001, 0x2401, 0x2801, 0x2c01, 0x3001, 0x3401, 0x3801, 0x3c01, 0x4001, 0x42b, 0x44d, 0x42c, 0x82c, 0x42d, 0x423, 0x445, 0x402, 0x455, 0x403, 0x404, 0x804, 0xc04, 0x1004, 0x1404, 0x41a, 0x405, 0x406, 0x413, 0x813, 0x409, 0x809, 0xc09, 0x1009, 0x1409, 0x1809, 0x1c09, 0x2009, 0x2409, 0x2809, 0x2c09, 0x3009, 0x3409, 0x425, 0x438, 0x429, 0x40b, 0x40c, 0x80c, 0xc0c, 0x100c, 0x140c, 0x180c, 0x437, 0x407, 0x807, 0xc07, 0x1007, 0x1407, 0x408, 0x447, 0x40d, 0x439, 0x40e, 0x40f, 0x421, 0x410, 0x810, 0x411, 0x44b, 0x860, 0x43f, 0x457, 0x412, 0x812, 0x426, 0x427, 0x827, 0x42f, 0x43e, 0x83e, 0x44c, 0x458, 0x44e, 0x861, 0x414, 0x814, 0x448, 0x415, 0x416, 0x816, 0x446, 0x418, 0x419, 0x44f, 0xc1a, 0x81a, 0x459, 0x41b, 0x424, 0x40a, 0x80a, 0xc0a, 0x100a, 0x140a, 0x180a, 0x1c0a, 0x200a, 0x240a, 0x280a, 0x2c0a, 0x300a, 0x340a, 0x380a, 0x3c0a, 0x400a, 0x440a, 0x480a, 0x4c0a, 0x500a, 0x430, 0x441, 0x41d, 0x81d, 0x449, 0x444, 0x44a, 0x41e, 0x41f, 0x422, 0x420, 0x820, 0x443, 0x843, 0x42a, 0x4ff, 0xf0ff, 0xf4ff, 0xf8ff, 0xfcff

usb_qualifier_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_QUALIFIER, int8]

	bcdUSB			flags[usb_versions, int16]
	bDeviceClass		int8
	bDeviceSubClass		int8
	bDeviceProtocol		int8
	bMaxPacketSize0		flags[usb_device_max_packet_sizes, int8]
	bNumConfigurations	int8
	bRESERVED		const[0, int8]
} [packed]

usb_bos_descriptor {
	bLength		const[USB_DT_BOS_SIZE, int8]
	bDescriptorType	const[USB_DT_BOS, int8]

	wTotalLength	len[parent, int16]
	bNumDeviceCaps	len[caps, int8]

	caps		array[usb_dev_cap, 0:6]
} [packed]

usb_dev_cap [
	generic		usb_generic_cap_descriptor
	wireless	usb_wireless_cap_descriptor
	ext_cap		usb_ext_cap_descriptor
	ss_cap		usb_ss_cap_descriptor
	ss_container_id	usb_ss_container_id_descriptor
	ssp_cap		usb_ssp_cap_descriptor
	ptm_cap		usb_ptm_cap_descriptor
] [varlen]

usb_generic_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	flags[usb_capability_types, int8]

	data			array[int8, 0:256]
} [packed]

usb_capability_types = USB_CAP_TYPE_WIRELESS_USB, USB_CAP_TYPE_EXT, USB_SS_CAP_TYPE, USB_SSP_CAP_TYPE, CONTAINER_ID_TYPE, USB_PTM_CAP_TYPE

usb_wireless_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_CAP_TYPE_WIRELESS_USB, int8]

	bmAttributes		flags[usb_wireless_cap_attributes, int8]
	wPHYRates		flags[usb_wireless_cap_phyrates, int16]
	bmTFITXPowerInfo	int8
	bmFFITXPowerInfo	int8
	bmBandGroup		int16
	bReserved		int8
} [packed]

usb_wireless_cap_attributes = USB_WIRELESS_P2P_DRD, USB_WIRELESS_BEACON_MASK, USB_WIRELESS_BEACON_SELF, USB_WIRELESS_BEACON_DIRECTED, USB_WIRELESS_BEACON_NONE

usb_wireless_cap_phyrates = USB_WIRELESS_PHY_53, USB_WIRELESS_PHY_80, USB_WIRELESS_PHY_107, USB_WIRELESS_PHY_160, USB_WIRELESS_PHY_200, USB_WIRELESS_PHY_320, USB_WIRELESS_PHY_400, USB_WIRELESS_PHY_480

usb_ext_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_CAP_TYPE_EXT, int8]

	bmAttributes1		flags[usb_ext_cap_attributes, int32:8]
	bmAttributes2		int32:4
	bmAttributes3		int32:4
	bmAttributes4		int32:16
} [packed]

usb_ext_cap_attributes = USB_LPM_SUPPORT, USB_BESL_SUPPORT, USB_BESL_BASELINE_VALID, USB_BESL_DEEP_VALID

usb_ss_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_SS_CAP_TYPE, int8]

	bmAttributes		flags[usb_ss_cap_attributes, int8]
	wSpeedSupported		flags[usb_ss_cap_speed, int16]
	bFunctionalitySupport	int8
	bU1devExitLat		int8
	bU2DevExitLat		int16
} [packed]

usb_ss_cap_attributes = USB_LTM_SUPPORT

usb_ss_cap_speed = USB_LOW_SPEED_OPERATION, USB_FULL_SPEED_OPERATION, USB_HIGH_SPEED_OPERATION, USB_5GBPS_OPERATION

usb_ss_container_id_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[CONTAINER_ID_TYPE, int8]

	bReserved		int8
	ContainerID		array[int8, 16]
} [packed]

usb_ssp_cap_descriptor {
	bLength				len[parent, int8]
	bDescriptorType			const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType		const[USB_SSP_CAP_TYPE, int8]

	bReserved			int8
	bmAttributesSublinkSpeeds	len[bmSublinkSpeedAttr, int32:5]
	bmAttributesSpeedIDs		int32:27
	wFunctionalitySupport		flags[usb_ssp_cap_funcs, int16]
	wReserved			int16
	bmSublinkSpeedAttr		array[flags[usb_ssp_cap_sublink_speeds, int32], 0:6]
} [packed]

usb_ssp_cap_funcs = USB_SSP_MIN_SUBLINK_SPEED_ATTRIBUTE_ID, USB_SSP_MIN_RX_LANE_COUNT, USB_SSP_MIN_TX_LANE_COUNT

usb_ssp_cap_sublink_speeds = USB_SSP_SUBLINK_SPEED_SSID, USB_SSP_SUBLINK_SPEED_LSE, USB_SSP_SUBLINK_SPEED_ST, USB_SSP_SUBLINK_SPEED_RSVD, USB_SSP_SUBLINK_SPEED_LP, USB_SSP_SUBLINK_SPEED_LSM

usb_ptm_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_PTM_CAP_TYPE, int8]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Extra USB descriptors that come after an interface or an endpoint descriptor.

# TODO: consider removing class specific descriptors here for described classes.
usb_interface_extra_descriptor [
	generic		usb_generic_descriptor
	hid_hid		usb_hid_descriptor_hid
	cdc_ecm		usb_cdc_header_ecm
	cdc_ncm		usb_cdc_header_ncm
	uac_control	uac_control_iface_extra_descriptors
	uac_as		uac_as_iface_extra_descriptors
] [varlen]

usb_endpoint_extra_descriptor [
	generic	usb_generic_descriptor
	uac_iso	uac_iso_endpoint_descriptor
] [varlen]

usb_generic_descriptor {
	bLength		len[parent, int8]
	bDescriptorType	flags[usb_descriptor_types, int8]

	data		array[int8, 0:256]
} [packed]

usb_descriptor_types = USB_DT_DEVICE, USB_DT_CONFIG, USB_DT_STRING, USB_DT_INTERFACE, USB_DT_ENDPOINT, USB_DT_DEVICE_QUALIFIER, USB_DT_OTHER_SPEED_CONFIG, USB_DT_INTERFACE_POWER, USB_DT_OTG, USB_DT_DEBUG, USB_DT_INTERFACE_ASSOCIATION, USB_DT_SECURITY, USB_DT_KEY, USB_DT_ENCRYPTION_TYPE, USB_DT_BOS, USB_DT_DEVICE_CAPABILITY, USB_DT_WIRELESS_ENDPOINT_COMP, USB_DT_WIRE_ADAPTER, USB_DT_RPIPE, USB_DT_CS_RADIO_CONTROL, USB_DT_PIPE_USAGE, USB_DT_SS_ENDPOINT_COMP, USB_DT_SSP_ISOC_ENDPOINT_COMP, HID_DT_HID, HID_DT_REPORT, HID_DT_PHYSICAL

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# USB descriptors requested after the SET_CONFIGURATION request.

usb_hub_descriptor_hs {
	bDescLength		len[parent, int8]
	bDescriptorType		const[USB_DT_HUB, int8]

	bNbrPorts		int8
	wHubCharacteristics	flags[usb_hub_characteristics, int16]
	bPwrOn2PwrGood		int8
	bHubContrCurrent	int8

	DeviceRemovable		array[int8, USB_HUB_PORTS_BITS]
	PortPwrCtrlMask		array[int8, USB_HUB_PORTS_BITS]
} [packed]

usb_hub_descriptor_ss {
	bDescLength		len[parent, int8]
	bDescriptorType		const[USB_DT_SS_HUB, int8]

	bNbrPorts		int8
	wHubCharacteristics	flags[usb_hub_characteristics, int16]
	bPwrOn2PwrGood		int8
	bHubContrCurrent	int8

	bHubHdrDecLat		int8
	wHubDelay		int16
	DeviceRemovable		int16
} [packed]

define USB_HUB_PORTS_BITS	((USB_MAXCHILDREN + 1 + 7) / 8)

usb_hub_characteristics = HUB_CHAR_LPSM, HUB_CHAR_COMMON_LPSM, HUB_CHAR_INDV_PORT_LPSM, HUB_CHAR_NO_LPSM, HUB_CHAR_COMPOUND, HUB_CHAR_OCPM, HUB_CHAR_COMMON_OCPM, HUB_CHAR_INDV_PORT_OCPM, HUB_CHAR_NO_OCPM, HUB_CHAR_TTTT, HUB_CHAR_PORTIND

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Replies to USB control requests requested after the SET_CONFIGURATION request.

usb_port_status {
	wPortStatus	flags[usb_port_status_flags, int16]
	wPortChange	flags[usb_port_change_flags, int16]
	dwExtPortStatus	array[flags[usb_ext_port_status_flags, int32], 0:1]
} [packed]

usb_port_status_flags = USB_PORT_STAT_CONNECTION, USB_PORT_STAT_ENABLE, USB_PORT_STAT_SUSPEND, USB_PORT_STAT_OVERCURRENT, USB_PORT_STAT_RESET, USB_PORT_STAT_L1, USB_PORT_STAT_POWER, USB_PORT_STAT_LOW_SPEED, USB_PORT_STAT_HIGH_SPEED, USB_PORT_STAT_TEST, USB_PORT_STAT_INDICATOR, USB_PORT_STAT_LINK_STATE, USB_SS_PORT_STAT_POWER, USB_SS_PORT_STAT_SPEED, USB_PORT_STAT_SPEED_5GBPS, USB_SS_PORT_LS_U0, USB_SS_PORT_LS_U1, USB_SS_PORT_LS_U2, USB_SS_PORT_LS_U3, USB_SS_PORT_LS_SS_DISABLED, USB_SS_PORT_LS_RX_DETECT, USB_SS_PORT_LS_SS_INACTIVE, USB_SS_PORT_LS_POLLING, USB_SS_PORT_LS_RECOVERY, USB_SS_PORT_LS_HOT_RESET, USB_SS_PORT_LS_COMP_MOD, USB_SS_PORT_LS_LOOPBACK

usb_port_change_flags = USB_PORT_STAT_C_CONNECTION, USB_PORT_STAT_C_ENABLE, USB_PORT_STAT_C_SUSPEND, USB_PORT_STAT_C_OVERCURRENT, USB_PORT_STAT_C_RESET, USB_PORT_STAT_C_L1, USB_PORT_STAT_C_BH_RESET, USB_PORT_STAT_C_LINK_STATE, USB_PORT_STAT_C_CONFIG_ERROR

usb_ext_port_status_flags = USB_EXT_PORT_STAT_RX_SPEED_ID, USB_EXT_PORT_STAT_TX_SPEED_ID, USB_EXT_PORT_STAT_RX_LANES, USB_EXT_PORT_STAT_TX_LANES

usb_hub_status {
	wHubStatus	flags[usb_hub_status_flags, int16]
	wHubChange	flags[usb_hub_change_flags, int16]
} [packed]

usb_hub_status_flags = HUB_STATUS_LOCAL_POWER, HUB_STATUS_OVERCURRENT

usb_hub_change_flags = HUB_CHANGE_LOCAL_POWER, HUB_CHANGE_OVERCURRENT

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# HID device class specific descriptions.
# https://www.usb.org/sites/default/files/documents/hid1_11.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/hid/usbhid/hid-core.c
# https://elixir.bootlin.com/linux/latest/source/drivers/hid/hid-core.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/hid.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_hid.c

# Connected HID devices are known to create the following /dev/ files:
# /dev/hidraw#, /dev/usb/hiddev# and /dev/input/event#.

resource fd_usb_hid[fd_usb]

syz_usb_connect$hid(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_hid], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_hid (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$hid(fd fd_usb_hid, descs ptr[in, vusb_descriptors_hid], resps ptr[in, vusb_responses_hid]) (timeout[300], remote_cover)

# idVendor and idProduct are patched by Go code, see sys/linux/init_vusb.go.
usb_device_descriptor_hid {
	inner	usb_device_descriptor_t[0, 0, 0, 0, 0, 64, array[usb_config_descriptor_hid, 1]]
} [packed]

usb_config_descriptor_hid {
	inner	usb_config_descriptor_ifaces_array_t[const[1, int8], array[usb_interface_descriptor_hid, 1]]
} [packed]

usb_interface_descriptor_hid {
	inner	usb_interface_descriptor_t[const[0, int8], int8, int8[1:2], const[USB_CLASS_HID, int8], const[USB_INTERFACE_SUBCLASS_BOOT, int8], flags[usb_hid_protocols, int8], usb_hid_descriptor_hid, usb_endpoint_descriptors_hid]
} [packed]

usb_hid_protocols = USB_INTERFACE_PROTOCOL_KEYBOARD, USB_INTERFACE_PROTOCOL_MOUSE

usb_endpoint_descriptors_hid {
	in	usb_endpoint_descriptor_hid_in
	out	array[usb_endpoint_descriptor_hid_out, 0:1]
} [packed]

usb_endpoint_descriptor_hid_in {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_HID_IN_ADDRESS, int8], const[USB_ENDPOINT_HID_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_hid_out {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_HID_OUT_ADDRESS, int8], const[USB_ENDPOINT_HID_ATTRIBUTES, int8], void]
} [packed]

define USB_ENDPOINT_HID_ATTRIBUTES	(USB_ENDPOINT_XFER_INT)
define USB_ENDPOINT_HID_IN_ADDRESS	(1 | USB_DIR_IN)
define USB_ENDPOINT_HID_OUT_ADDRESS	(2)

vusb_descriptors_hid {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]

# For unknown reasons these are requested as USB_TYPE_STANDARD and not as USB_TYPE_CLASS.
# Linux doesn't request HID_DT_HID, but some hosts might do that.
	HID_DT_REPORT	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, HID_DT_REPORT, hid_descriptor_report]]
	HID_DT_HID	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, HID_DT_HID, usb_hid_descriptor_hid]]
} [packed]

vusb_responses_hid {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	HID_REQ_GET_REPORT		ptr[in, vusb_response_t[USB_TYPE_CLASS, HID_REQ_GET_REPORT, array[int8, 0:256]]]
	HID_REQ_GET_PROTOCOL		ptr[in, vusb_response_t[USB_TYPE_CLASS, HID_REQ_GET_PROTOCOL, int8]]
} [packed]

# USB HID specifications allows for multiple report and physical descriptors
# to be present, but I don't see any support for them in the Linux kernel,
# except for a single report descriptor.
usb_hid_descriptor_hid {
	bLength		len[parent, int8]
	bDescriptorType	const[HID_DT_HID, int8]

	bcdHID		int16
	bCountryCode	int8
	bNumDescriptors	const[1, int8]

	report_desc	usb_hid_class_descriptor_report
} [packed]

usb_hid_class_descriptor_report {
	bDescriptorType		const[HID_DT_REPORT, int8]
	wDescriptorLength	int16[0:HID_MAX_DESCRIPTOR_SIZE]
} [packed]

# TODO: it's hard to describe the REPORT descriptor structure via syzkaller
# descriptions, so consider generating it in Go code.
# TODO: the length of REPORT descriptor must match the value in HID descriptor.
# TODO: there are vendor specific REPORT descriptor formats (Logitech HID++).

# Linux HID stack doesn't support long items.
hid_descriptor_report {
	items	array[hid_report_item_short]
} [packed]

type hid_report_item_short_012_t[TYPE, TAGS] {
	bSize	len[data, int8:2]
	bType	const[TYPE, int8:2]
	bTag	flags[TAGS, int8:4]
	data	array[int8, 0:2]
} [packed]

type hid_report_item_short_4_t[TYPE, TAGS] {
	bSize	const[3, int8:2]
	bType	const[TYPE, int8:2]
	bTag	flags[TAGS, int8:4]
	data	array[int8, 4]
} [packed]

type hid_report_item_short_t[TYPE, TAGS] [
	item_012	hid_report_item_short_012_t[TYPE, TAGS]
	item_4		hid_report_item_short_4_t[TYPE, TAGS]
] [varlen]

hid_report_item_short [
	main	hid_report_item_short_t[HID_ITEM_TYPE_MAIN, hid_report_item_main_tags]
	global	hid_report_item_short_t[HID_ITEM_TYPE_GLOBAL, hid_report_item_global_tags]
	local	hid_report_item_short_t[HID_ITEM_TYPE_LOCAL, hid_report_item_local_tags]
] [varlen]

hid_report_item_main_tags = HID_MAIN_ITEM_TAG_INPUT, HID_MAIN_ITEM_TAG_OUTPUT, HID_MAIN_ITEM_TAG_FEATURE, HID_MAIN_ITEM_TAG_BEGIN_COLLECTION, HID_MAIN_ITEM_TAG_END_COLLECTION
hid_report_item_global_tags = HID_GLOBAL_ITEM_TAG_USAGE_PAGE, HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM, HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM, HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM, HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM, HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT, HID_GLOBAL_ITEM_TAG_UNIT, HID_GLOBAL_ITEM_TAG_REPORT_SIZE, HID_GLOBAL_ITEM_TAG_REPORT_ID, HID_GLOBAL_ITEM_TAG_REPORT_COUNT, HID_GLOBAL_ITEM_TAG_PUSH, HID_GLOBAL_ITEM_TAG_POP
hid_report_item_local_tags = HID_LOCAL_ITEM_TAG_USAGE, HID_LOCAL_ITEM_TAG_USAGE_MINIMUM, HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM, HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX, HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM, HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM, HID_LOCAL_ITEM_TAG_STRING_INDEX, HID_LOCAL_ITEM_TAG_STRING_MINIMUM, HID_LOCAL_ITEM_TAG_STRING_MAXIMUM, HID_LOCAL_ITEM_TAG_DELIMITER

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# PRINTER device class specific descriptions.
# https://www.usb.org/sites/default/files/usbprint11a021811.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/class/usblp.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/printer.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_printer.c

# Connected PRINTER devices are known to create the following /dev/ files:
# /dev/usb/lp#.
# TODO: write descriptions for those.

# drivers/usb/class/usblp.c
define USBLP_REQ_GET_ID	0x00
define USBLP_REQ_GET_STATUS	0x01
define USBLP_REQ_RESET	0x02
define USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST	0x00
define USBLP_FIRST_PROTOCOL	1
define USBLP_LAST_PROTOCOL	3

resource fd_usb_printer[fd_usb]

syz_usb_connect$printer(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_printer], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_printer (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$printer(fd fd_usb_printer, descs ptr[in, vusb_descriptors_printer], resps ptr[in, vusb_responses_printer]) (timeout[300], remote_cover)

usb_device_descriptor_printer {
	inner	usb_device_descriptor_t[0, 0, 0, 0x525, 0xa4a8, 64, array[usb_config_descriptor_printer, 1]]
} [packed]

usb_config_descriptor_printer {
	inner	usb_config_descriptor_ifaces_array_t[const[1, int8], array[usb_interface_descriptor_printer, 1]]
} [packed]

usb_interface_descriptor_printer {
	inner	usb_interface_descriptor_t[const[0, int8], int8, int8[1:2], const[USB_CLASS_PRINTER, int8], const[1, int8], int8[USBLP_FIRST_PROTOCOL:USBLP_LAST_PROTOCOL], void, usb_endpoint_descriptors_printer]
} [packed]

usb_endpoint_descriptors_printer {
	in	usb_endpoint_descriptor_printer_out
	out	array[usb_endpoint_descriptor_printer_in, 0:1]
} [packed]

usb_endpoint_descriptor_printer_out {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_PRINTER_OUT_ADDRESS, int8], const[USB_ENDPOINT_PRINTER_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_printer_in {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_PRINTER_IN_ADDRESS, int8], const[USB_ENDPOINT_PRINTER_ATTRIBUTES, int8], void]
} [packed]

define USB_ENDPOINT_PRINTER_ATTRIBUTES	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_PRINTER_OUT_ADDRESS	(1)
define USB_ENDPOINT_PRINTER_IN_ADDRESS	(2 | USB_DIR_IN)

vusb_descriptors_printer {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_printer {
	len					len[parent, int32]
	generic					ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE			ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	USBLP_REQ_GET_ID			ptr[in, vusb_response_t[USB_TYPE_CLASS, USBLP_REQ_GET_ID, usb_printer_get_id_response]]
	USBLP_REQ_GET_STATUS			ptr[in, vusb_response_t[USB_TYPE_CLASS, USBLP_REQ_GET_STATUS, int8]]
	USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST	ptr[in, vusb_response_t[USB_TYPE_CLASS, USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST, int8]]
} [packed]

usb_printer_get_id_response {
	length	len[id, int16be]
	id	array[int8, 0:256]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# CDC ECM (Ethernet) device class specific descriptions.
# https://www.usb.org/document-library/class-definitions-communication-devices-12
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/cdc_ether.c
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/usbnet.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/ether.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_ecm.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/u_ether.c

# Connected CDC ECM devices are known to create usbN network interfaces.
# TODO: write descriptions for those.

resource fd_usb_cdc_ecm[fd_usb]

syz_usb_connect$cdc_ecm(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_cdc_ecm], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_cdc_ecm (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$cdc_ecm(fd fd_usb_cdc_ecm, descs ptr[in, vusb_descriptors_cdc_ecm], resps ptr[in, vusb_responses_cdc_ecm]) (timeout[300], remote_cover)

usb_device_descriptor_cdc_ecm {
	inner	usb_device_descriptor_t[USB_CLASS_COMM, 0, 0, 0x525, 0xa4a1, 64, array[usb_config_descriptor_cdc_ecm, 1]]
} [packed]

usb_config_descriptor_cdc_ecm {
	inner	usb_config_descriptor_ifaces_array_t[const[1, int8], array[usb_interface_descriptor_cdc_ecm, 1]]
} [packed]

# Per specification CDC ECM devices have two interfaces (control and data),
# but here we're merging them into one for simplicity since Linux supports that.
usb_interface_descriptor_cdc_ecm {
	inner	usb_interface_descriptor_t[const[0, int8], int8, int8[2:3], const[USB_CLASS_COMM, int8], const[USB_CDC_SUBCLASS_ETHERNET, int8], const[USB_CDC_PROTO_NONE, int8], usb_cdc_header_ecm, usb_endpoint_descriptors_cdc_ecm]
} [packed]

usb_endpoint_descriptors_cdc_ecm {
	notify	array[usb_endpoint_descriptor_cdc_ecm_notify, 0:1]
	in	usb_endpoint_descriptor_cdc_ecm_in
	out	usb_endpoint_descriptor_cdc_ecm_out
} [packed]

usb_endpoint_descriptor_cdc_ecm_notify {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_CDC_ECM_NOTIFY_ADDRESS, int8], const[USB_ENDPOINT_CDC_ECM_NOTIFY_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_cdc_ecm_in {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_CDC_ECM_IN_ADDRESS, int8], const[USB_ENDPOINT_CDC_ECM_DATA_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_cdc_ecm_out {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_CDC_ECM_OUT_ADDRESS, int8], const[USB_ENDPOINT_CDC_ECM_DATA_ATTRIBUTES, int8], void]
} [packed]

define USB_ENDPOINT_CDC_ECM_NOTIFY_ATTRIBUTES	(USB_ENDPOINT_XFER_INT)
define USB_ENDPOINT_CDC_ECM_DATA_ATTRIBUTES	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_CDC_ECM_NOTIFY_ADDRESS	(1 | USB_DIR_IN)
define USB_ENDPOINT_CDC_ECM_IN_ADDRESS	(2 | USB_DIR_IN)
define USB_ENDPOINT_CDC_ECM_OUT_ADDRESS	(3)

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/usb/core/message.c#L2137
# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/cdc_ether.c#L155
usb_cdc_header_ecm {
	union	usb_cdc_union_desc_t[0, 0]
	header	usb_cdc_header_desc
	ether	usb_cdc_ether_desc

	other	array[usb_cdc_header_ecm_other, 0:6]
} [packed]

usb_cdc_header_ecm_other [
	call_mgmt		usb_cdc_call_mgmt_descriptor
	acm			usb_cdc_acm_descriptor
	country_functional	usb_cdc_country_functional_desc
	network_terminal	usb_cdc_network_terminal_desc
	dmm			usb_cdc_dmm_desc
	mdlm			usb_cdc_mdlm_desc
	mdlm_detail		usb_cdc_mdlm_detail_desc
	obex			usb_cdc_obex_desc
	ncm			usb_cdc_ncm_desc
	mbim			usb_cdc_mbim_desc
	mbim_extended		usb_cdc_mbim_extended_desc
] [varlen]

usb_cdc_header_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_HEADER_TYPE, int8]

	bcdCDC			int16
} [packed]

usb_cdc_call_mgmt_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_CALL_MANAGEMENT_TYPE, int8]

	bmCapabilities		flags[usb_cdc_call_mgmt_caps, int8]
	bDataInterface		int8
} [packed]

usb_cdc_call_mgmt_caps = USB_CDC_CALL_MGMT_CAP_CALL_MGMT, USB_CDC_CALL_MGMT_CAP_DATA_INTF

usb_cdc_acm_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_ACM_TYPE, int8]

	bmCapabilities		flags[usb_cdc_acm_caps, int8]
} [packed]

usb_cdc_acm_caps = USB_CDC_COMM_FEATURE, USB_CDC_CAP_LINE, USB_CDC_CAP_BRK, USB_CDC_CAP_NOTIFY

type usb_cdc_union_desc_t[MASTER, SLAVE] {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_UNION_TYPE, int8]

	bMasterInterface0	const[MASTER, int8]
	bSlaveInterface0	const[SLAVE, int8]
	slave_interfaces	array[int8, 0:6]
} [packed]

usb_cdc_country_functional_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_COUNTRY_TYPE, int8]

	iCountryCodeRelDate	int8
	wCountyCode0		int16
	country_codes		array[int16, 0:6]
} [packed]

usb_cdc_network_terminal_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_NETWORK_TERMINAL_TYPE, int8]

	bEntityId		int8
	iName			int8
	bChannelIndex		int8
	bPhysicalInterface	int8
} [packed]

usb_cdc_ether_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_ETHERNET_TYPE, int8]

	iMACAddress		const[1, int8]
	bmEthernetStatistics	int32
	wMaxSegmentSize		int16
	wNumberMCFilters	int16
	bNumberPowerFilters	int8
} [packed]

usb_cdc_dmm_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_DMM_TYPE, int8]

	bcdVersion		int16
	wMaxCommand		int16
} [packed]

usb_cdc_mdlm_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_MDLM_TYPE, int8]

	bcdVersion		int16
	bGUID			usb_cdc_ecm_mbm_guid
} [packed]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/cdc_ether.c#L61
usb_cdc_ecm_mbm_guid {
	id0	const[0x14f5e048ba817a3, int64]
	id1	const[0x2a397ecbffc007a6, int64]
} [packed]

usb_cdc_mdlm_detail_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_MDLM_DETAIL_TYPE, int8]

	bGuidDescriptorType	int8
	bDetailData		array[int8, 0:256]
} [packed]

usb_cdc_obex_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_OBEX_TYPE, int8]

	bcdVersion		int16
} [packed]

usb_cdc_ncm_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_NCM_TYPE, int8]

	bcdNcmVersion		int16
	bmNetworkCapabilities	flags[usb_cdc_ncm_ncaps, int8]
} [packed]

usb_cdc_ncm_ncaps = USB_CDC_NCM_NCAP_ETH_FILTER, USB_CDC_NCM_NCAP_NET_ADDRESS, USB_CDC_NCM_NCAP_ENCAP_COMMAND, USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE, USB_CDC_NCM_NCAP_CRC_MODE, USB_CDC_NCM_NCAP_NTB_INPUT_SIZE

usb_cdc_mbim_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_MBIM_TYPE, int8]

	bcdMBIMVersion		int16
	wMaxControlMessage	int16
	bNumberFilters		int8
	bMaxFilterSize		int8
	wMaxSegmentSize		int16
	bmNetworkCapabilities	int8
} [packed]

usb_cdc_mbim_extended_desc {
	bLength				len[parent, int8]
	bDescriptorType			const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType		const[USB_CDC_MBIM_EXTENDED_TYPE, int8]

	bcdMBIMExtendedVersion		int16
	bMaxOutstandingCommandMessages	int8
	wMTU				int16
} [packed]

vusb_descriptors_cdc_ecm {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/usbnet.c#L147
	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor_t[usb_cdc_ecm_mac]]]
} [packed]

usb_cdc_ecm_mac {
# This is a UTF16 encoded string "424242424242".
	data0	const[0x3400320034003200, int64be]
	data1	const[0x3400320034003200, int64be]
	data2	const[0x3400320034003200, int64be]
} [packed]

vusb_responses_cdc_ecm {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# CDC NCM class specific descriptions.
# CDC NCM is based on CDC ECM, so some of the descriptions are reused.
# https://www.usb.org/document-library/network-control-model-devices-specification-v10-and-errata-and-adopters-agreement
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/cdc_ncm.c
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/usbnet.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/ncm.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_ncm.c

resource fd_usb_cdc_ncm[fd_usb]

syz_usb_connect$cdc_ncm(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_cdc_ncm], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_cdc_ncm (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$cdc_ncm(fd fd_usb_cdc_ncm, descs ptr[in, vusb_descriptors_cdc_ncm], resps ptr[in, vusb_responses_cdc_ncm]) (timeout[300], remote_cover)

usb_device_descriptor_cdc_ncm {
	inner	usb_device_descriptor_t[USB_CLASS_COMM, 0, 0, 0x525, 0xa4a1, 64, array[usb_config_descriptor_cdc_ncm, 1]]
} [packed]

usb_config_descriptor_cdc_ncm {
	inner	usb_config_descriptor_t[const[1, int8], const[2, int8], usb_interface_descriptors_cdc_ncm]
} [packed]

usb_interface_descriptors_cdc_ncm {
	control		usb_interface_descriptor_fixed_t[0, CDC_NCM_COMM_ALTSETTING_NCM, 1, USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE, usb_cdc_header_ncm, usb_endpoint_descriptor_cdc_ecm_notify]
	data_nop	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE, void, void]
	data		usb_interface_descriptor_fixed_t[1, CDC_NCM_DATA_ALTSETTING_NCM, 2, USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE, void, usb_endpoint_descriptors_cdc_ncm_data]
} [packed]

usb_endpoint_descriptors_cdc_ncm_data {
	in	usb_endpoint_descriptor_cdc_ecm_in
	out	usb_endpoint_descriptor_cdc_ecm_out
} [packed]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/usb/core/message.c#L2137
# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/cdc_ncm.c#L798
usb_cdc_header_ncm {
	union	usb_cdc_union_desc_t[0, 1]
	header	usb_cdc_header_desc
	ether	usb_cdc_ether_desc
	ncm	usb_cdc_ncm_desc

	other	array[usb_cdc_header_ncm_other, 0:6]
} [packed]

usb_cdc_header_ncm_other [
	call_mgmt		usb_cdc_call_mgmt_descriptor
	acm			usb_cdc_acm_descriptor
	country_functional	usb_cdc_country_functional_desc
	network_terminal	usb_cdc_network_terminal_desc
	dmm			usb_cdc_dmm_desc
	mdlm			usb_cdc_mdlm_desc
	mdlm_detail		usb_cdc_mdlm_detail_desc
	obex			usb_cdc_obex_desc
	mbim			usb_cdc_mbim_desc
	mbim_extended		usb_cdc_mbim_extended_desc
] [varlen]

vusb_descriptors_cdc_ncm {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/usbnet.c#L147
	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor_t[usb_cdc_ecm_mac]]]
} [packed]

vusb_responses_cdc_ncm {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	USB_CDC_GET_NTB_PARAMETERS	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_NTB_PARAMETERS, usb_cdc_ncm_ntb_parameters]]
	USB_CDC_GET_NTB_INPUT_SIZE	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_NTB_INPUT_SIZE, int32]]
	USB_CDC_GET_NTB_FORMAT		ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_NTB_FORMAT, int16[0:1]]]
	USB_CDC_GET_MAX_DATAGRAM_SIZE	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_MAX_DATAGRAM_SIZE, int16]]
	USB_CDC_GET_CRC_MODE		ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_CRC_MODE, int16[0:1]]]
} [packed]

usb_cdc_ncm_ntb_parameters {
	wLength			int16
	bmNtbFormatsSupported	int16
	dwNtbInMaxSize		int32
	wNdpInDivisor		int16
	wNdpInPayloadRemainder	int16
	wNdpInAlignment		int16
	wPadding1		int16
	dwNtbOutMaxSize		int32
	wNdpOutDivisor		int16
	wNdpOutPayloadRemainder	int16
	wNdpOutAlignment	int16
	wNtbOutMaxDatagrams	int16
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC1 device class specific descriptions.
# https://www.usb.org/sites/default/files/audio10.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/audio.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac1.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac1_legacy.c
# https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/usb/audio.h

# TODO: find out which /dev/ files are created by connected UAC1 devices and add descriptions for those.

resource fd_usb_uac1[fd_usb]

syz_usb_connect$uac1(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_uac1], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_uac1 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$uac1(fd fd_usb_uac1, descs ptr[in, vusb_descriptors_uac1], resps ptr[in, vusb_responses_uac1]) (timeout[300], remote_cover)

usb_device_descriptor_uac1 {
	inner	usb_device_descriptor_t[0, 0, 0, 0x1d6b, 0x101, 64, array[usb_config_descriptor_uac1, 1]]
} [packed]

usb_config_descriptor_uac1 {
	inner	usb_config_descriptor_t[const[1, int8], const[3, int8], usb_interface_descriptors_uac1]
} [packed]

# TODO: control interface might have and optional interrupt endpoint.
usb_interface_descriptors_uac1 {
	inner	usb_interface_descriptors_uac1_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_uac1_inner {
	control		usb_interface_descriptor_fixed_t[0, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOCONTROL, 0, uac_control_iface_extra_descriptors, void]
	as_out_alt_0	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, void, void]
	as_out_alt_1	usb_interface_descriptor_fixed_t[1, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, uac_as_iface_extra_descriptors, uac_as_out_endpoint_descriptor]
	as_in_alt_0	usb_interface_descriptor_fixed_t[2, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, void, void]
	as_in_alt_1	usb_interface_descriptor_fixed_t[2, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, uac_as_iface_extra_descriptors, uac_as_in_endpoint_descriptor]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC uses IDs to make it possible for terminals and units to refer to each other.
# We don't have a way to describe this, so just use a limited number of ids.
type uac_id int8[1:6]

uac_control_iface_extra_descriptors {
	header	uac1_ac_header_descriptor
	others	array[uac_control_iface_extra_descriptor, 0:6]
} [packed]

uac1_ac_header_descriptor {
	bLength			const[UAC_DT_AC_HEADER_LENGTH, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_HEADER, int8]

	bcdADC			int16
	wTotalLength		len[uac_control_iface_extra_descriptors, int16]
	bInCollection		const[F_AUDIO_NUM_INTERFACES, int8]

# These must match interfaces numbers.
	baInterfaceNr0		const[1, int8]
	baInterfaceNr1		const[2, int8]
} [packed]

uac_control_iface_extra_descriptor [
	input_terminal	uac_input_terminal_descriptor
	output_terminal	uac1_output_terminal_descriptor
	mixer_unit	uac_mixer_unit_descriptor
	selector_unit	uac_selector_unit_descriptor
	feature_unit	uac_feature_unit_descriptor
	processing_unit	uac_processing_unit_descriptor
	extension_unit	uac_extension_unit_descriptor
] [varlen]

define F_AUDIO_NUM_INTERFACES	2
define UAC_DT_AC_HEADER_LENGTH	UAC_DT_AC_HEADER_SIZE(F_AUDIO_NUM_INTERFACES)

uac_input_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_INPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_input_terminal_types, int16]
	bAssocTerminal		uac_id
	bNrChannels		int8
	wChannelConfig		int16
	iChannelNames		int8
	iTerminal		int8
} [packed]

# The following list contains input terminal types and inout terminal types.
uac_input_terminal_types = UAC_TERMINAL_UNDEFINED, UAC_TERMINAL_STREAMING, UAC_TERMINAL_VENDOR_SPEC, UAC_INPUT_TERMINAL_UNDEFINED, UAC_INPUT_TERMINAL_MICROPHONE, UAC_INPUT_TERMINAL_DESKTOP_MICROPHONE, UAC_INPUT_TERMINAL_PERSONAL_MICROPHONE, UAC_INPUT_TERMINAL_OMNI_DIR_MICROPHONE, UAC_INPUT_TERMINAL_MICROPHONE_ARRAY, UAC_INPUT_TERMINAL_PROC_MICROPHONE_ARRAY, UAC_BIDIR_TERMINAL_UNDEFINED, UAC_BIDIR_TERMINAL_HANDSET, UAC_BIDIR_TERMINAL_HEADSET, UAC_BIDIR_TERMINAL_SPEAKER_PHONE, UAC_BIDIR_TERMINAL_ECHO_SUPPRESSING, UAC_BIDIR_TERMINAL_ECHO_CANCELING
# The following list contains output terminal types and inout terminal types.
uac_output_terminal_types = UAC_TERMINAL_UNDEFINED, UAC_TERMINAL_STREAMING, UAC_TERMINAL_VENDOR_SPEC, UAC_OUTPUT_TERMINAL_UNDEFINED, UAC_OUTPUT_TERMINAL_SPEAKER, UAC_OUTPUT_TERMINAL_HEADPHONES, UAC_OUTPUT_TERMINAL_HEAD_MOUNTED_DISPLAY_AUDIO, UAC_OUTPUT_TERMINAL_DESKTOP_SPEAKER, UAC_OUTPUT_TERMINAL_ROOM_SPEAKER, UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER, UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER, UAC_BIDIR_TERMINAL_UNDEFINED, UAC_BIDIR_TERMINAL_HANDSET, UAC_BIDIR_TERMINAL_HEADSET, UAC_BIDIR_TERMINAL_SPEAKER_PHONE, UAC_BIDIR_TERMINAL_ECHO_SUPPRESSING, UAC_BIDIR_TERMINAL_ECHO_CANCELING

uac1_output_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_OUTPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_output_terminal_types, int16]
	bAssocTerminal		uac_id
	bSourceID		uac_id
	iTerminal		int8
} [packed]

uac_mixer_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIXER_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac_selector_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_SELECTOR_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac_feature_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FEATURE_UNIT, int8]

	bUnitID			uac_id
	bSourceID		uac_id
	bControlSize		len[bmaControls, int8]
	bmaControls		array[flags[uac_feature_unit_controls, int16], 1:6]
	iFeature		int8
} [packed]

uac_feature_unit_controls = UAC_FU_MUTE, UAC_FU_VOLUME, UAC_FU_BASS, UAC_FU_MID, UAC_FU_TREBLE, UAC_FU_GRAPHIC_EQUALIZER, UAC_FU_AUTOMATIC_GAIN, UAC_FU_DELAY, UAC_FU_BASS_BOOST, UAC_FU_LOUDNESS

uac_processing_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC1_PROCESSING_UNIT, int8]

	bUnitID			uac_id
	wProcessType		flags[uac_processing_unit_types, int16]
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac_processing_unit_types = UAC_PROCESS_UNDEFINED, UAC_PROCESS_UP_DOWNMIX, UAC_PROCESS_DOLBY_PROLOGIC, UAC_PROCESS_STEREO_EXTENDER, UAC_PROCESS_REVERB, UAC_PROCESS_CHORUS, UAC_PROCESS_DYN_RANGE_COMP

uac_extension_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC1_EXTENSION_UNIT, int8]

	bUnitID			uac_id
	wProcessType		int16
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac_as_iface_extra_descriptors {
	others	array[uac_as_iface_extra_descriptor, 0:6]
} [packed]

uac_as_iface_extra_descriptor [
	as_header			uac1_as_header_descriptor
	format_type_i_continuous	uac_format_type_i_continuous_descriptor
	format_type_i_discrete		uac_format_type_i_discrete_descriptor
	format_type_ii_discrete		uac_format_type_ii_discrete_descriptor
	format_type_ii_ext		uac_format_type_ii_ext_descriptor
	format_type_i_ext		uac_format_type_i_ext_descriptor
] [varlen]

uac1_as_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_AS_GENERAL, int8]

	bTerminalLink		int8
	bDelay			int8
	wFormatTag		flags[uac_format_tags, int16]
} [packed]

uac_format_tags = UAC_FORMAT_TYPE_I_UNDEFINED, UAC_FORMAT_TYPE_I_PCM, UAC_FORMAT_TYPE_I_PCM8, UAC_FORMAT_TYPE_I_IEEE_FLOAT, UAC_FORMAT_TYPE_I_ALAW, UAC_FORMAT_TYPE_I_MULAW, UAC_FORMAT_TYPE_II_MPEG, UAC_FORMAT_TYPE_II_AC3
uac_usb_format_types_i = UAC_FORMAT_TYPE_I, UAC_FORMAT_TYPE_II, UAC_FORMAT_TYPE_III, UAC_FORMAT_TYPE_UNDEFINED

uac_format_type_i_continuous_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bNrChannels		int8
	bSubframeSize		int8[1:4]
	bBitResolution		int8
	bSamFreqType		int8
	tLowerSamFreq		array[int8, 0:3]
	tUpperSamFreq		array[int8, 0:3]
} [packed]

uac_format_type_i_discrete_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bNrChannels		int8
	bSubframeSize		int8[1:4]
	bBitResolution		int8
	bSamFreqType		int8
	tSamFreq		array[int8, 0:9]
} [packed]

uac_format_type_ii_discrete_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_II, int8]
	wMaxBitRate		int16
	wSamplesPerFrame	int16
	bSamFreqType		int8
	tSamFreq		array[int8, 0:9]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac_as_out_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac_iso_endpoint_descriptor]
} [packed]

uac_as_in_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_IN_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac_iso_endpoint_descriptor]
} [packed]

define USB_ENDPOINT_UAC1_AS_OUT_ADDRESS	(1 | USB_DIR_OUT)
define USB_ENDPOINT_UAC1_AS_IN_ADDRESS	(2 | USB_DIR_IN)
define USB_ENDPOINT_UAC1_AS_ATTRIBUTES	(USB_ENDPOINT_SYNC_ADAPTIVE | USB_ENDPOINT_XFER_ISOC)

uac_iso_ep_attributes = USB_ENDPOINT_SYNCTYPE, USB_ENDPOINT_SYNC_NONE, USB_ENDPOINT_SYNC_ASYNC, USB_ENDPOINT_SYNC_ADAPTIVE, USB_ENDPOINT_SYNC_SYNC

uac_iso_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubType	const[UAC_EP_GENERAL, int8]

	bmAttributes		flags[uac_iso_ep_attributes, int8]
	bLockDelayUnits		int8
	wLockDelay		int16
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

vusb_descriptors_uac1 {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_uac1 {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	audio_UAC_GET_CUR		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_CUR, array[int8, 1:3]]]
	audio_UAC_GET_MIN		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_MIN, array[int8, 1:3]]]
	audio_UAC_GET_MAX		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_MAX, array[int8, 1:3]]]
	audio_UAC_GET_RES		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_RES, array[int8, 1:4]]]
	audio_UAC_GET_MEM		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_MEM, array[int8, 3]]]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC2 device class specific descriptions.
# https://www.usb.org/sites/default/files/audio10.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/audio.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac2.c
# https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/usb/audio.h

resource fd_usb_uac2[fd_usb]

syz_usb_connect$uac2(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_uac2], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_uac2 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$uac2(fd fd_usb_uac2, descs ptr[in, vusb_descriptors_uac1], resps ptr[in, vusb_responses_uac1]) (timeout[300], remote_cover)

usb_device_descriptor_uac2 {
	inner	usb_device_descriptor_t[0, 0, 0, 0x41e, 0x3000, 64, array[usb_config_descriptor_uac2, 1]]
} [packed]

usb_config_descriptor_uac2 {
	inner	usb_config_descriptor_extra_t[const[1, int8], const[3, int8], uac2_interface_assoc_descriptor, usb_interface_descriptors_uac2]
} [packed]

uac2_interface_assoc_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_INTERFACE_ASSOCIATION, int8]

	bFirstInterface		int8[0:2]
	bInterfaceCount		int8[0:2]
	bFunctionClass		const[USB_CLASS_AUDIO, int8]
	bFunctionSubClass	flags[audio_function_category_types, int8]
	bFunctionProtocol	const[UAC_VERSION_2, int8]
	iFunction		int8
} [packed]

audio_function_category_types = UAC2_FUNCTION_SUBCLASS_UNDEFINED, UAC2_FUNCTION_DESKTOP_SPEAKER, UAC2_FUNCTION_HOME_THEATER, UAC2_FUNCTION_MICROPHONE, UAC2_FUNCTION_HEADSET, UAC2_FUNCTION_TELEPHONE, UAC2_FUNCTION_CONVERTER, UAC2_FUNCTION_SOUND_RECORDER, UAC2_FUNCTION_IO_BOX, UAC2_FUNCTION_MUSICAL_INSTRUMENT, UAC2_FUNCTION_PRO_AUDIO, UAC2_FUNCTION_AUDIO_VIDEO, UAC2_FUNCTION_CONTROL_PANEL, UAC2_FUNCTION_OTHER

usb_interface_descriptors_uac2 {
	inner	usb_interface_descriptors_uac2_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_uac2_inner {
	control		usb_interface_descriptor_fixed_t[0, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOCONTROL, UAC_VERSION_2, uac2_control_iface_extra_descriptors, void]
	as_out_alt_0	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, void, void]
	as_out_alt_1	usb_interface_descriptor_fixed_t[1, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, uac2_as_iface_extra_descriptors, uac2_as_out_endpoint_descriptor]
	as_in_alt_0	usb_interface_descriptor_fixed_t[2, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, void, void]
	as_in_alt_1	usb_interface_descriptor_fixed_t[2, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, uac2_as_iface_extra_descriptors, uac2_as_in_endpoint_descriptor]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac2_control_iface_extra_descriptors {
	header	uac2_ac_header_descriptor
	others	array[uac2_control_iface_extra_descriptor, 0:6]
} [packed]

uac2_ac_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MS_HEADER, int8]
	bcdADC			int16
	bCategory		flags[uac2_feature_unit_controls, int8]
	wTotalLength		len[uac2_control_iface_extra_descriptors, int16]
	bmControls		int8
} [packed]

uac2_feature_unit_controls = UAC2_FUNCTION_SUBCLASS_UNDEFINED, UAC2_FUNCTION_DESKTOP_SPEAKER, UAC2_FUNCTION_HOME_THEATER, UAC2_FUNCTION_MICROPHONE, UAC2_FUNCTION_HEADSET, UAC2_FUNCTION_TELEPHONE, UAC2_FUNCTION_CONVERTER, UAC2_FUNCTION_SOUND_RECORDER, UAC2_FUNCTION_IO_BOX, UAC2_FUNCTION_MUSICAL_INSTRUMENT, UAC2_FUNCTION_PRO_AUDIO, UAC2_FUNCTION_AUDIO_VIDEO, UAC2_FUNCTION_CONTROL_PANEL, UAC2_FUNCTION_OTHER, uac_feature_unit_controls

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac2_as_iface_extra_descriptors {
	others	array[uac2_as_iface_extra_descriptor, 0:6]
} [packed]

uac2_as_iface_extra_descriptor [
	as_header			uac2_as_header_descriptor
	format_type_i_descriptor	uac2_format_type_i_descriptor
	format_type_i_continuous	uac_format_type_i_continuous_descriptor
	format_type_i_discrete		uac_format_type_i_discrete_descriptor
	format_type_ii_discrete		uac_format_type_ii_discrete_descriptor
	format_type_i_ext		uac2_format_type_i_ext_descriptor
	format_type_ii_ext		uac_format_type_ii_ext_descriptor
] [varlen]

uac2_as_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_AS_GENERAL, int8]
	bTerminalLink		int8
	bmControls		int8
	bFormatType		flags[uac_usb_format_types_i, int8]
	bmFormats		flags[uac_format_tags, int32]
	bNrChannels		int8
	bmChannelConfig		int32
	iChannelNames		int8
} [packed]

b_sub_slot_sizes = 1, 2, 3, 4

uac2_format_type_i_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]
	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bSubslotSize		flags[b_sub_slot_sizes, int8]
	bBitResolution		int8
} [packed]

uac2_format_type_i_ext_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bSubslotSize		int8
	bBitResolution		int8
	bHeaderLength		int8
	bControlSize		int8
	bSideBandProtocol	int8
} [packed]

uac_format_type_ii_ext_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]
	bFormatType		const[UAC_FORMAT_TYPE_II, int8]
	wMaxBitRate		int16
	wSamplesPerFrame	int16
	bHeaderLength		int8
	bSideBandProtocol	int8
} [packed]

uac_format_type_i_ext_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]
	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bSubslotSize		int8
	bBitResolution		int8
	bHeaderLength		int8
	bControlSize		int8
	bSideBandProtocol	int8
} [packed]

uac2_as_out_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac2_iso_endpoint_descriptor]
} [packed]

uac2_as_in_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_IN_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac2_iso_endpoint_descriptor]
} [packed]

uac2_iso_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubtype	const[UAC_EP_GENERAL, int8]

	bmAttributes		flags[csep_bm_attributes, int8]
	bmControls		flags[csep_bm_controls, int8]
	bLockDelayUnits		int8
	wLockDelay		int16
} [packed]

csep_bm_attributes = UAC_EP_CS_ATTR_SAMPLE_RATE, UAC_EP_CS_ATTR_PITCH_CONTROL, UAC_EP_CS_ATTR_FILL_MAX
csep_bm_controls = UAC2_CONTROL_PITCH, UAC2_CONTROL_DATA_OVERRUN, UAC2_CONTROL_DATA_UNDERRUN

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac2_control_iface_extra_descriptor [
	input_terminal	uac2_input_terminal_descriptor
	output_terminal	uac2_output_terminal_descriptor
	mixer_unit	uac2_mixer_unit_descriptor
	selector_unit	uac2_clock_selector_descriptor

	feature_unit	uac2_feature_unit_descriptor
	processing_unit	uac2_processing_unit_descriptor
	extension_unit	uac2_extension_unit_descriptor

	effect_unit	uac2_effect_unit_descriptor
	sample_rate	uac2_sample_rate_descriptor
	source_unit	uac2_clock_source_descriptor
	multiply_unit	uac2_clock_multiplier_descriptor
] [varlen]

uac2_input_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_INPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_input_terminal_types, int16]
	bAssocTerminal		uac_id
	bCSourceID		int8
	bNrChannels		int8
	bmChannelConfig		int32
	iChannelNames		int8
	bmControls		int8
	iTerminal		int8
} [packed]

uac2_output_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_OUTPUT_TERMINAL, int8]
	bTerminalID		uac_id
	wTerminalType		flags[uac_output_terminal_types, int16]
	bAssocTerminal		int8
	bSourceID		uac_id
	bCSourceID		int8
	bmControls		int16
	iTerminal		int8
} [packed]

uac2_mixer_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIXER_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

# TODO: Figure out if bmControls and iClockSelector should be a part of this structure.
uac2_clock_selector_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_CLOCK_SELECTOR, int8]
	bClockID		int8
	bNrInPins		len[baCSourceID, int8]
	baCSourceID		array[int8, 0:8]
} [packed]

# TODO: Verify coverage.
uac2_processing_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC2_PROCESSING_UNIT_V2, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac2_processing_unit_types, int16], 1:6]
} [packed]

uac2_processing_unit_types = UAC2_PROCESS_UNDEFINED, UAC2_PROCESS_UP_DOWNMIX, UAC2_PROCESS_DOLBY_PROLOCIC, UAC2_PROCESS_STEREO_EXTENDER

uac2_extension_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_EXTENSION_UNIT_V2, int8]

	bUnitID			uac_id
	wProcessType		int16
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

# TODO: Verify coverage.
uac2_effect_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC2_EFFECT_UNIT, int8]
	bUnitID			uac_id
	wEffectType		flags[uac2_effect_unit_types, int16]
	bSourceID		uac_id
	bmaControls		array[flags[uac2_processing_unit_types, int16], 1:6]
} [packed]

uac2_effect_unit_types = UAC2_EFFECT_UNDEFINED, UAC2_EFFECT_PARAM_EQ, UAC2_EFFECT_REVERB, UAC2_EFFECT_MOD_DELAY, UAC2_EFFECT_DYN_RANGE_COMP

uac2_sample_rate_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC2_SAMPLE_RATE_CONVERTER, int8]
	bUnitID			uac_id
	wProcessType		flags[uac2_processing_unit_types, int16]
	bSourceID		uac_id
	bmaControls		array[flags[uac2_processing_unit_types, int16], 1:6]
} [packed]

uac2_feature_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_FEATURE_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac2_feature_unit_controls, int16], 1:6]
} [packed]

uac2_clock_source_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_CLOCK_SOURCE, int8]
	bClockID		int8
	bmAttributes		flags[uac2_clock_bmattribute_types, int8]
	bmControls		int8
	bAssocTerminal		int8
	iClockSource		flags[uac2_clock_source_types, int8]
} [packed]

uac2_clock_bmattribute_types = UAC_CLOCK_SOURCE_TYPE_EXT, UAC_CLOCK_SOURCE_TYPE_INT_FIXED, UAC_CLOCK_SOURCE_TYPE_INT_VAR, UAC_CLOCK_SOURCE_TYPE_INT_PROG, UAC_CLOCK_SOURCE_SYNCED_TO_SOF
uac2_clock_source_types = UAC_CLOCK_SOURCE_TYPE_EXT, UAC_CLOCK_SOURCE_TYPE_INT_FIXED, UAC_CLOCK_SOURCE_TYPE_INT_VAR, UAC_CLOCK_SOURCE_TYPE_INT_PROG, UAC_CLOCK_SOURCE_SYNCED_TO_SOF

uac2_clock_multiplier_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_CLOCK_MULTIPLIER, int8]
	bClockID		int8
	bCSourceID		int8
	bmControls		int8
	iClockMultiplier	int8
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC3 device class specific descriptions.
# https://www.usb.org/sites/default/files/audio10.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/audio.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac3.c
# https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/usb/audio.h

resource fd_usb_uac3[fd_usb]

syz_usb_connect$uac3(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_uac3], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_uac3 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$uac3(fd fd_usb_uac3, descs ptr[in, vusb_descriptors_uac1], resps ptr[in, vusb_responses_uac1]) (timeout[300], remote_cover)

usb_device_descriptor_uac3 {
	inner	usb_device_descriptor_t[0, 0, 0, 0x582, 0x582, 64, array[usb_config_descriptor_uac3, 1]]
} [packed]

usb_config_descriptor_uac3 {
	inner	usb_config_descriptor_extra_t[const[1, int8], const[3, int8], uac3_interface_assoc_descriptor, usb_interface_descriptors_uac3]
} [packed]

uac3_interface_assoc_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_INTERFACE_ASSOCIATION, int8]

	bFirstInterface		int8[0:2]
	bInterfaceCount		int8[0:2]
	bFunctionClass		const[USB_CLASS_AUDIO, int8]
	bFunctionSubClass	flags[uac3_all_subclasses, int8]
	bFunctionProtocol	const[UAC_VERSION_3, int8]
	iFunction		int8
} [packed]

usb_interface_descriptors_uac3 {
	inner	usb_interface_descriptors_uac3_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_uac3_inner {
	control		usb_interface_descriptor_fixed_t[0, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOCONTROL, UAC_VERSION_3, uac3_control_iface_extra_descriptors, void]
	as_out_alt_0	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, void, void]
	as_out_alt_1	usb_interface_descriptor_fixed_t[1, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, uac3_as_iface_extra_descriptors, uac3_as_out_endpoint_descriptor]
	as_in_alt_0	usb_interface_descriptor_fixed_t[2, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, void, void]
	as_in_alt_1	usb_interface_descriptor_fixed_t[2, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, uac3_as_iface_extra_descriptors, uac3_as_in_endpoint_descriptor]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac3_control_iface_extra_descriptors {
	header	uac3_ac_header_descriptor
	others	array[uac3_control_iface_extra_descriptor, 0:6]
} [packed]

uac3_ac_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MS_HEADER, int8]

	bCategory		flags[uac3_feature_unit_controls, int8]
	wTotalLength		len[uac3_control_iface_extra_descriptors, int16]
	bmControls		int32
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac3_as_iface_extra_descriptors {
	others	array[uac3_as_iface_extra_descriptor, 0:6]
} [packed]

uac3_as_iface_extra_descriptor [
	as_header			uac3_as_header_descriptor
	format_type_i_descriptor	uac2_format_type_i_descriptor
	format_type_i_continuous	uac_format_type_i_continuous_descriptor
	format_type_i_discrete		uac_format_type_i_discrete_descriptor
	format_type_ii_discrete		uac_format_type_ii_discrete_descriptor
	format_type_i_ext		uac2_format_type_i_ext_descriptor
	format_type_ii_ext		uac_format_type_ii_ext_descriptor
] [varlen]

# TODO: Figure out how wClusterDescrID is used in the kernel.
uac3_as_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_AS_GENERAL, int8]
	bTerminalLink		int8

	bmControls		int32
	wClusterDescrID		int16

	bmFormats		flags[uac_format_tags, int64]

	bSubslotSize		int8
	bBitResolution		int8
	bmAuxProtocols		int16
	bControlSize		int8
} [packed]

uac3_as_out_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac3_iso_endpoint_descriptor]
} [packed]

uac3_as_in_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_IN_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac3_iso_endpoint_descriptor]
} [packed]

uac3_iso_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubType	const[UAC3_CS_ENDPOINT, int8]
	bmControls		int32
	bLockDelayUnits		int8
	wLockDelay		int16
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac3_control_iface_extra_descriptor [
	input_terminal		uac3_input_terminal_descriptor
	output_terminal		uac3_output_terminal_descriptor
	mixer_unit		uac3_mixer_unit_descriptor
	selector_unit		uac3_clock_selector_descriptor
	source_unit		uac3_clock_source_descriptor
	multiply_unit		uac3_clock_multiplier_descriptor
	feature_unit		uac3_feature_unit_descriptor
	processing_unit		uac3_processing_unit_descriptor
	extension_unit		uac3_extension_unit_descriptor
	power_domain		uac3_power_domain_descriptor
	cluster_info_segment	uac3_cluster_information_segment_descriptor
# Only cluster information segment is currently used in the kernel.See: sound/usb/stream.c
# cluster_segment 		uac3_cluster_segment_descriptor
# cluster_end_segment		uac3_cluster_end_segment_descriptor
# The following units are not yet supported by the kernel.
# See audio_validators[] in sound/usb/validate.c:
#	effect_unit 		uac3_effect_unit_descriptor
#	sample_rate			uac3_sample_rate_descriptor
#	connectors_unit		uac3_connectors_unit_descriptor
#	extended_term_unit	uac3_extended_terminal_unit
] [varlen]

uac3_input_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_INPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_input_terminal_types, int16]
	bAssocTerminal		uac_id
	bCSourceID		int8

	bmControls		int32
	wClusterDescrID		int16
	wExTerminalDescrID	int16
	wConnectorsDescrID	int16
	wTerminalDescrStr	int16
} [packed]

uac3_output_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_OUTPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_output_terminal_types, int16]
	bAssocTerminal		uac_id
	bSourceID		uac_id
	bCSourceID		int8

	bmControls		int32
	wExTerminalDescrID	int16
	wConnectorsDescrID	int16
	wTerminalDescrStr	int16
} [packed]

uac3_mixer_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_MIXER_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac3_clock_selector_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_CLOCK_SELECTOR, int8]
	bClockID		int8
	bNrInPins		len[baCSourceID, int8]
	baCSourceID		array[int8, 0:8]
} [packed]

uac3_clock_source_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_CLOCK_SOURCE, int8]
	bClockID		int8
	bmAttributes		flags[uac3_clock_bmattribute_types, int8]
	bmControls		int32
	bReferenceTerminal	int8
	wClockSourceStr		int16
} [packed]

uac3_clock_bmattribute_types = UAC3_CLOCK_SOURCE_TYPE_EXT, UAC3_CLOCK_SOURCE_TYPE_INT, UAC3_CLOCK_SOURCE_ASYNC, UAC3_CLOCK_SOURCE_SYNCED_TO_SOF

uac3_clock_multiplier_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_CLOCK_MULTIPLIER, int8]
	bClockID		int8
	bCSourceID		int8
	bmControls		int32
	wCMultiplierDescrStr	int16
} [packed]

uac3_feature_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC3_FEATURE_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac3_feature_unit_controls, int32], 1:6]
} [packed]

uac3_processing_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC3_PROCESSING_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac3_processing_unit_types, int32], 1:6]
} [packed]

uac3_processing_unit_types = UAC3_PROCESS_UNDEFINED, UAC3_PROCESS_UP_DOWNMIX, UAC3_PROCESS_STEREO_EXTENDER, UAC3_PROCESS_MULTI_FUNCTION

uac3_extension_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC3_EXTENSION_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac3_processing_unit_types, int32], 1:6]
} [packed]

uac3_power_domain_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_POWER_DOMAIN, int8]

	bPowerDomainID		int8
	waRecoveryTime1		int16
	waRecoveryTime2		int16
	bNrEntities		int8
	baEntityID		array[int8, 0:8]
} [packed]

uac3_cluster_information_segment_descriptor {
	bLength		len[parent, int16]
	bSegmentType	const[UAC3_CHANNEL_INFORMATION, int8]
	bChPurpose	flags[uac3_cluster_channel_purposes, int8]
	bChRelationship	flags[uac3_cluster_channel_relationships, int8]
	bChGroupID	int8
} [packed]

uac3_cluster_channel_purposes = UAC3_PURPOSE_UNDEFINED, UAC3_PURPOSE_GENERIC_AUDIO, UAC3_PURPOSE_VOICE, UAC3_PURPOSE_SPEECH, UAC3_PURPOSE_AMBIENT, UAC3_PURPOSE_REFERENCE, UAC3_PURPOSE_ULTRASONIC, UAC3_PURPOSE_VIBROKINETIC, UAC3_PURPOSE_NON_AUDIO
uac3_cluster_channel_relationships = UAC3_CH_RELATIONSHIP_UNDEFINED, UAC3_CH_MONO, UAC3_CH_LEFT, UAC3_CH_RIGHT, UAC3_CH_ARRAY, UAC3_CH_PATTERN_X, UAC3_CH_PATTERN_Y, UAC3_CH_PATTERN_A, UAC3_CH_PATTERN_B, UAC3_CH_PATTERN_M, UAC3_CH_PATTERN_S, UAC3_CH_FRONT_LEFT, UAC3_CH_FRONT_RIGHT, UAC3_CH_FRONT_CENTER, UAC3_CH_FRONT_LEFT_OF_CENTER, UAC3_CH_FRONT_RIGHT_OF_CENTER, UAC3_CH_FRONT_WIDE_LEFT, UAC3_CH_FRONT_WIDE_RIGHT, UAC3_CH_SIDE_LEFT, UAC3_CH_SIDE_RIGHT, UAC3_CH_SURROUND_ARRAY_LEFT, UAC3_CH_SURROUND_ARRAY_RIGHT, UAC3_CH_BACK_LEFT, UAC3_CH_BACK_RIGHT, UAC3_CH_BACK_CENTER, UAC3_CH_BACK_LEFT_OF_CENTER, UAC3_CH_BACK_RIGHT_OF_CENTER, UAC3_CH_BACK_WIDE_LEFT, UAC3_CH_BACK_WIDE_RIGHT, UAC3_CH_TOP_CENTER, UAC3_CH_TOP_FRONT_LEFT, UAC3_CH_TOP_FRONT_RIGHT, UAC3_CH_TOP_FRONT_CENTER, UAC3_CH_TOP_FRONT_LOC, UAC3_CH_TOP_FRONT_ROC, UAC3_CH_TOP_FRONT_WIDE_LEFT, UAC3_CH_TOP_FRONT_WIDE_RIGHT, UAC3_CH_TOP_SIDE_LEFT, UAC3_CH_TOP_SIDE_RIGHT, UAC3_CH_TOP_SURR_ARRAY_LEFT, UAC3_CH_TOP_SURR_ARRAY_RIGHT, UAC3_CH_TOP_BACK_LEFT, UAC3_CH_TOP_BACK_RIGHT, UAC3_CH_TOP_BACK_CENTER, UAC3_CH_TOP_BACK_LOC, UAC3_CH_TOP_BACK_ROC, UAC3_CH_TOP_BACK_WIDE_LEFT, UAC3_CH_TOP_BACK_WIDE_RIGHT, UAC3_CH_BOTTOM_CENTER, UAC3_CH_BOTTOM_FRONT_LEFT, UAC3_CH_BOTTOM_FRONT_RIGHT, UAC3_CH_BOTTOM_FRONT_CENTER, UAC3_CH_BOTTOM_FRONT_LOC, UAC3_CH_BOTTOM_FRONT_ROC, UAC3_CH_BOTTOM_FRONT_WIDE_LEFT, UAC3_CH_BOTTOM_FRONT_WIDE_RIGHT, UAC3_CH_BOTTOM_SIDE_LEFT, UAC3_CH_BOTTOM_SIDE_RIGHT, UAC3_CH_BOTTOM_SURR_ARRAY_LEFT, UAC3_CH_BOTTOM_SURR_ARRAY_RIGHT, UAC3_CH_BOTTOM_BACK_LEFT, UAC3_CH_BOTTOM_BACK_RIGHT, UAC3_CH_BOTTOM_BACK_CENTER, UAC3_CH_BOTTOM_BACK_LOC, UAC3_CH_BOTTOM_BACK_ROC, UAC3_CH_BOTTOM_BACK_WIDE_LEFT, UAC3_CH_BOTTOM_BACK_WIDE_RIGHT, UAC3_CH_LOW_FREQUENCY_EFFECTS, UAC3_CH_LFE_LEFT, UAC3_CH_LFE_RIGHT, UAC3_CH_HEADPHONE_LEFT, UAC3_CH_HEADPHONE_RIGHT

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# This list consists of uac3_func_subclasses + uac3_badd_classes.
uac3_all_subclasses = UAC3_FUNCTION_SUBCLASS_UNDEFINED, UAC3_FUNCTION_SUBCLASS_FULL_ADC_3_0, UAC3_FUNCTION_SUBCLASS_GENERIC_IO, UAC3_FUNCTION_SUBCLASS_HEADPHONE, UAC3_FUNCTION_SUBCLASS_SPEAKER, UAC3_FUNCTION_SUBCLASS_MICROPHONE, UAC3_FUNCTION_SUBCLASS_HEADSET, UAC3_FUNCTION_SUBCLASS_HEADSET_ADAPTER, UAC3_FUNCTION_SUBCLASS_SPEAKERPHONE

uac3_feature_unit_controls = UAC3_FUNCTION_SUBCLASS_UNDEFINED, UAC3_FUNCTION_DESKTOP_SPEAKER, UAC3_FUNCTION_HOME_THEATER, UAC3_FUNCTION_MICROPHONE, UAC3_FUNCTION_HEADSET, UAC3_FUNCTION_TELEPHONE, UAC3_FUNCTION_CONVERTER, UAC3_FUNCTION_SOUND_RECORDER, UAC3_FUNCTION_IO_BOX, UAC3_FUNCTION_MUSICAL_INSTRUMENT, UAC3_FUNCTION_PRO_AUDIO, UAC3_FUNCTION_AUDIO_VIDEO, UAC3_FUNCTION_CONTROL_PANEL, UAC3_FUNCTION_HEADPHONE, UAC3_FUNCTION_GENERIC_SPEAKER, UAC3_FUNCTION_HEADSET_ADAPTER, UAC3_FUNCTION_SPEAKERPHONE, UAC3_FUNCTION_OTHER

# TODO: Support uac3 badd profiles. See sound/usb/mixer.c: snd_usb_mixer_controls_badd()
# uac3_badd_endpoint_descriptor {
# 	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac3_iso_endpoint_descriptor]
# } [packed]

#uac3_badd_maxsizes = UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16,UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16,UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24,UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24,UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16,UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16,UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24,UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# MIDI device class specific descriptions.
# https://www.usb.org/sites/default/files/midi10.pdf
# https://elixir.bootlin.com/linux/latest/source/sound/usb/midi.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_midi.c

syz_usb_connect$midi(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_midi], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb (timeout[3000], prog_timeout[3000], remote_cover)

usb_device_descriptor_midi {
	inner	usb_device_descriptor_t[0, 0, 0, 0x1430, 0x474b, 64, array[usb_config_descriptor_midi, 1]]
} [packed]

usb_config_descriptor_midi {
	inner	usb_config_descriptor_t[const[1, int8], const[1, int8], usb_interface_descriptors_midi]
} [packed]

usb_interface_descriptors_midi {
	inner	usb_interface_descriptors_midi_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_midi_inner {
	control	usb_interface_descriptor_eps_array_t[const[0, int8], const[0, int8], const[USB_CLASS_AUDIO, int8], const[USB_SUBCLASS_MIDISTREAMING, int8], flags[uac_version_types, int8], array[usb_midi_iface_extra], array[usb_endpoint_descriptor_midi, 0:8]]
} [packed]

usb_endpoint_descriptor_midi {
	inner	usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], flags[usb_endpoint_attributes, int8], usb_ms_endpoint_descriptor]
} [packed]

midi_jack_type = USB_MS_EMBEDDED, USB_MS_EXTERNAL
uac_version_types = UAC_VERSION_1, UAC_VERSION_2, UAC_VERSION_3

usb_ms_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubType	const[USB_MS_GENERAL, int8]
	bNumEmbMIDIJack		len[baAssocJackID, int8]
	baAssocJackID		array[int8, 0:16]
} [packed]

usb_midi_iface_extra [
	ms_header	usb_ms_header_descriptor
	midi_in_jack	usb_midi_in_jack_descriptor
	midi_out_jack	usb_midi_out_jack_descriptor
] [varlen]

usb_ms_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_HEADER, int8]
	bcdMSC			int16
	wTotalLength		len[parent, int16]
} [packed]

usb_midi_in_jack_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIDI_IN_JACK, int8]
	bJackType		flags[midi_jack_type, int8]
	bJackID			int8
	iJack			int8
} [packed]

usb_midi_out_jack_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIDI_OUT_JACK, int8]
	bJackType		flags[midi_jack_type, int8]
	bJackID			int8
	bNrInputPins		len[pins, int8]
	pins			array[usb_midi_source_pin]
	iJack			int8
} [packed]

usb_midi_source_pin {
	baSourceID	int8
	baSourcePin	int8
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# ath9k driver specific descriptions.

include <drivers/net/wireless/ath/ath9k/htc_hst.h>
include <drivers/net/wireless/ath/ath9k/hif_usb.h>

define USB_ENDPOINT_ATH9K_BULK_OUT_ADDRESS	(1)
define USB_ENDPOINT_ATH9K_BULK_IN_ADDRESS	(2 | USB_DIR_IN)
define USB_ENDPOINT_ATH9K_INT_IN_ADDRESS	(3 | USB_DIR_IN)
define USB_ENDPOINT_ATH9K_INT_OUT_ADDRESS	(4)
define USB_ENDPOINT_ATH9K_BULK_EXTRA1_ADDRESS	(5)
define USB_ENDPOINT_ATH9K_BULK_EXTRA2_ADDRESS	(6)

resource fd_usb_ath9k[fd_usb]

syz_usb_connect_ath9k(speed const[USB_SPEED_HIGH], dev_len len[dev], dev ptr[in, usb_device_descriptor_ath9k], conn_descs const[0]) fd_usb_ath9k (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_ep_write$ath9k_ep1(fd fd_usb_ath9k, ep const[USB_ENDPOINT_ATH9K_BULK_IN_ADDRESS], len bytesize[data], data ptr[in, ath9k_bulk_frame]) (timeout[300], remote_cover)
syz_usb_ep_write$ath9k_ep2(fd fd_usb_ath9k, ep const[USB_ENDPOINT_ATH9K_INT_IN_ADDRESS], len bytesize[data], data ptr[in, htc_frame]) (timeout[300], remote_cover)

usb_device_descriptor_ath9k {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0xcf3, 0x9271, 0x108, array[usb_config_descriptor_ath9k, 1]]
} [packed]

usb_config_descriptor_ath9k {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_ath9k]
} [packed]

usb_interface_descriptor_ath9k {
	iface	usb_interface_descriptor_fixed_t[0, 0, 6, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_ath9k]
} [packed]

usb_endpoint_descriptors_ath9k {
	bulk_out	usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_OUT_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
	bulk_in		usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_IN_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
	int_in		usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_INT_IN_ADDRESS, USB_ENDPOINT_ATH9K_INT_ATTRIBUTES, 64, 1, void]
	int_out		usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_INT_OUT_ADDRESS, USB_ENDPOINT_ATH9K_INT_ATTRIBUTES, 64, 1, void]
	bulk_extra1	usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_EXTRA1_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
	bulk_extra2	usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_EXTRA2_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
} [packed]

define USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_ATH9K_INT_ATTRIBUTES	(USB_ENDPOINT_XFER_INT)

ath9k_bulk_frame {
	packets	array[ath9k_bulk_packet]
} [packed]

ath9k_bulk_packet {
	pkt_len	len[data, int16]
	pkt_tag	const[ATH_USB_RX_STREAM_MODE_TAG, int16]
	data	array[int8]
} [packed, align[4]]

htc_frame [
	ready		htc_ready_frame
	conn_svc_rsp	htc_conn_svc_rsp_frame
	generic		htc_generic_frame
] [varlen]

# This is actually wrong, as the driver is buggy and doesn't skip the header
# before processing the frame payload, but let's leave it like thise for now.
htc_ready_frame {
	endpoint_id	const[0, int8]
	flags		const[0, int8]
	payload_len	len[payload, int16be]
	control		array[int8, 4]
	payload		htc_ready_msg
} [packed]

htc_ready_msg {
	message_id	const[HTC_MSG_READY_ID, int16be]
	credits		int16be
	credit_size	int16be
	max_endpoints	int8
	pad		int8
} [packed]

htc_conn_svc_rsp_frame {
	endpoint_id	const[0, int8]
	flags		const[0, int8]
	payload_len	len[payload, int16be]
	control		array[int8, 4]
	payload		htc_conn_svc_rspmsg
} [packed]

htc_conn_svc_rspmsg {
	message_id	const[HTC_MSG_CONNECT_SERVICE_RESPONSE_ID, int16be]
	service_id	flags[htc_svcs, int16be]
	status		const[HTC_SERVICE_SUCCESS, int8]
	endpoint_id	int8
	max_msg_len	int16be
	svc_meta_len	int8
	pad		int8
} [packed]

htc_svcs = HTC_CTRL_RSVD_SVC, HTC_LOOPBACK_RSVD_SVC, WMI_CONTROL_SVC, WMI_BEACON_SVC, WMI_CAB_SVC, WMI_UAPSD_SVC, WMI_MGMT_SVC, WMI_DATA_VO_SVC, WMI_DATA_VI_SVC, WMI_DATA_BE_SVC, WMI_DATA_BE_SVC

htc_generic_frame {
	endpoint_id	int8[0:8]
	flags		flags[htc_frame_flags, int8]
	payload_len	len[payload, int16be]
	control		array[int8, 4]
	payload		array[int8, 0:256]
} [packed]

htc_frame_flags = HTC_FLAGS_RECV_TRAILER

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Assorted driver-specific descriptions of generic syz_* calls' variants.

# Generic calls such as syz_usb_connect() and syz_usb_control_io() should be enough
# (in theory) to emulate a proper device and finish driver probes without a hitch.
# However, there are cases when syzkaller fails to come up with correct inputs to achieve it.
# Use fixed descriptors to quickly pass through probe() to access select drivers' post-probe functionality.

# It is important to note that, one way or another, drivers in question require multiple control requests
# between a driver and a device processed during probe(). Descriptions below do not deal with specific
# CTRL requests as such (except for basic information included in vusb_responses_XXX). Instead, rely on
# seeds, created both manually and with syzkaller's help. For examples, see sys/linux/test/vusb_XXX.

# Common constants for endpoint descriptors.
define USB_ENDPOINT_BULK_ATTR	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_INT_ATTR	(USB_ENDPOINT_XFER_INT)

define USB_FIXED_ENDPOINT_BULK_IN_ADDR	(1 | USB_DIR_IN)
define USB_FIXED_ENDPOINT_BULK_OUT_ADDR	(2)
define USB_FIXED_ENDPOINT_INT_IN_ADDR	(3 | USB_DIR_IN)

define USB_RECIP_DEVICE	0x00

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# rtl8150 driver specific descriptions.

resource fd_usb_rtl8150[fd_usb]

syz_usb_connect$rtl8150(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_rtl8150], conn_descs const[0]) fd_usb_rtl8150 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$rtl8150(fd fd_usb_rtl8150, descs ptr[in, vusb_descriptors_rtl8150], resps ptr[in, vusb_responses_rtl8150]) (timeout[300], remote_cover)

usb_device_descriptor_rtl8150 {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0xbda, 0x8150, 0, array[usb_config_descriptor_rtl8150, 1]]
} [packed]

usb_config_descriptor_rtl8150 {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_rtl8150]
} [packed]

usb_interface_descriptor_rtl8150 {
	iface	usb_interface_descriptor_fixed_t[0, 0, 3, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_rtl8150]
} [packed]

usb_endpoint_descriptors_rtl8150 {
	bulk_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_IN_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	bulk_out	usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_OUT_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	int_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_INT_IN_ADDR, USB_ENDPOINT_INT_ATTR, 64, 1, void]
} [packed]

vusb_descriptors_rtl8150 {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_rtl8150 {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	RTL8150_REQ_GET_REGS		ptr[in, vusb_response_t[RTL8150_REQT_READ, RTL8150_REQ_GET_REGS, array[int8, 0:6]]]
	RTL8150_REQ_SET_REGS		ptr[in, vusb_response_t[RTL8150_REQT_WRITE, RTL8150_REQ_SET_REGS, array[int8, 0:6]]]
} [packed]

define RTL8150_REQ_GET_REGS	0x05
define RTL8150_REQ_SET_REGS	0x05
define RTL8150_REQT_READ	0xc0
define RTL8150_REQT_WRITE	0x40

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# sierra_net driver specific descriptions.

resource fd_usb_sierra_net[fd_usb]

syz_usb_connect$sierra_net(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_sierra_net], conn_descs const[0]) fd_usb_sierra_net (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$sierra_net(fd fd_usb_sierra_net, descs ptr[in, vusb_descriptors_sierra_net], resps ptr[in, vusb_responses_sierra_net]) (timeout[300], remote_cover)

usb_device_descriptor_sierra_net {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0x1199, 0x68a3, 0, array[usb_config_descriptor_sierra_net, 1]]
} [packed]

usb_config_descriptor_sierra_net {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_sierra_net]
} [packed]

usb_interface_descriptor_sierra_net {
	iface	usb_interface_descriptor_fixed_t[7, 0, 3, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_sierra_net]
} [packed]

# sierra_net driver does not expect fixed ep addresses, so refrain from being too specific here.
# As long as we ensure there are 3 endpoints, 2 bulk and 1 int, syzkaller should figure it out.
usb_endpoint_descriptors_sierra_net {
	bulk_in		usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], const[USB_ENDPOINT_BULK_ATTR, int8], void]
	bulk_out	usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], const[USB_ENDPOINT_BULK_ATTR, int8], void]
	status		usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], const[USB_ENDPOINT_INT_ATTR, int8], void]
} [packed]

vusb_descriptors_sierra_net {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_sierra_net {
	len					len[parent, int32]
	generic					ptr[in, vusb_response_generic]

	USB_CDC_GET_ENCAPSULATED_RESPONSE	ptr[in, vusb_response_t[SIERRA_CMD_TYPE_IN, USB_CDC_GET_ENCAPSULATED_RESPONSE, array[int8, 1024]]]
	USB_CDC_SEND_ENCAPSULATED_COMMANDT	ptr[in, vusb_response_t[SIERRA_CMD_TYPE_OUT, USB_CDC_SEND_ENCAPSULATED_COMMAND, array[int8, 0:4]]]
} [packed]

define SIERRA_CMD_TYPE_IN	(USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)
define SIERRA_CMD_TYPE_OUT	(USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# lan78xx driver specific descriptions.
# While these syz_* variants noticably help with the probe() process, they are not enough.
# This is due to a high number of control requests expected between the driver and the device.

include <drivers/net/usb/smsc95xx.h>

resource fd_usb_lan78xx[fd_usb]

syz_usb_connect$lan78xx(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_lan78xx], conn_descs const[0]) fd_usb_lan78xx (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$lan78xx(fd fd_usb_lan78xx, descs ptr[in, vusb_descriptors_lan78xx], resps ptr[in, vusb_responses_lan78xx]) (timeout[300], remote_cover)

usb_device_descriptor_lan78xx {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0x424, 0x7850, 0, array[usb_config_descriptor_lan78xx, 1]]
} [packed]

usb_config_descriptor_lan78xx {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_lan78xx]
} [packed]

usb_interface_descriptor_lan78xx {
	iface	usb_interface_descriptor_fixed_t[0, 0, 3, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_lan78xx]
} [packed]

usb_endpoint_descriptors_lan78xx {
	bulk_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_IN_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	bulk_out	usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_OUT_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	int_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_INT_IN_ADDR, USB_ENDPOINT_INT_ATTR, 64, 1, void]
} [packed]

vusb_descriptors_lan78xx {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_lan78xx {
	len					len[parent, int32]
	generic					ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE			ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	USB_VENDOR_REQUEST_READ_REGISTER	ptr[in, vusb_response_t[LAN78XX_REG_TYPE_IN, USB_VENDOR_REQUEST_READ_REGISTER, int32]]
	USB_VENDOR_REQUEST_WRITE_REGISTER	ptr[in, vusb_response_t[LAN78XX_REG_TYPE_OUT, USB_VENDOR_REQUEST_WRITE_REGISTER, int32]]
	USB_VENDOR_REQUEST_GET_STATS		ptr[in, vusb_response_t[LAN78XX_REG_TYPE_IN, USB_VENDOR_REQUEST_GET_STATS, array[int8, 47]]]
} [packed]

define LAN78XX_REG_TYPE_IN	(USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
define LAN78XX_REG_TYPE_OUT	(USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
]

288/2 2026/07/30 13:03 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 103085
							output: 501
							thoughts: 1484
						

Thoughts:
**A Deep Dive into the `au0828` USB Driver Vulnerability**

Okay, so I'm digging into this `au0828` driver, and things are getting interesting. My initial thought was about how to get more than four interfaces to play nice with the USB device descriptor, especially considering the `au0828` driver needs a specific alternate setting. I saw `syz_usb_connect` takes `usb_device_descriptor`, and that has a limit of four interfaces. I briefly considered using `ANY` or raw byte arrays, but that's a no-go with how Syzkaller's structured.

Then it hit me: what if I don't *need* the analog registration to succeed? If `au0828_analog_register` fails, the driver just returns an error, right? And I saw the code goes to `done`, calls `au0828_usb_disconnect` which then calls `au0828_analog_unregister`. I thought, will `au0828_analog_unregister` return a 1? Turns out it will! The return of `au0828_analog_unregister` returning 1 and making `au0828_usb_disconnect` return early depends only on a value set by `id->driver_info` which, crucially, *doesn't* depend on `au0828_analog_register` succeeding. So, if registration fails it's good!

This is where it gets juicy. If I get the early return, `au0828_usb_release(dev)` doesn't get called. And `au0828_i2c_unregister(dev)` won't be called either! So the I2C adapter stays registered! Because `probe` returns an error, the USB core cleans up the interface, but the I2C adapter is still there, registered and its parent is tied to a pointer to the USB device. Now, if I disconnect the USB device *after* `probe` returns an error, the `usb_device` gets freed. *Boom* - dangling pointer! Then I can do an I2C transaction on it and trigger a UAF (Use-After-Free)!

Essentially, I don't even need to open the V4L2 device. The key is the leak of `dev` and the registered I2C adapter. This is a HUGE bug.

Here's the plan to verify this. I'll use `syz_usb_connect` with specific vendor and product IDs (0x2040 and 0x7200), and make sure I *don't* provide alternate setting 5. `au0828_analog_register` will fail, `au0828_usb_disconnect` will be called, `au0828_analog_unregister` will return 1, and so the early return will leak `dev`, leaving the I2C adapter registered. The I then disconnect the USB device and then access the I2C adapter! Let's see if this works!



289/2 2026/07/30 13:03 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{18, 1, 0x200, 0, 0, 0, 64, 0x2040, 0x7200, 0, 0, 0, 0, AUTO, [{{9, 2, AUTO, AUTO, 1, 0, 0x80, 0, "", [{{{9, 4, 0, 0, AUTO, 0, 0, 0, 0, [], []}}}]}}]}}, 0)
r1 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r2 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r3 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r4 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r1, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r2, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r3, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r4, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

290/2 2026/07/30 13:03 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 105915
							output: 500
							thoughts: 1504
						

Thoughts:
**Debugging USB Descriptor Generation**

Okay, here's the deal. I'm getting a "wrong struct arg for 'const'" error at position 9, specifically for `bLength` within the `usb_interface_descriptor_verbose_t` struct. Let me break down my current thought process.

I'm starting by tracing the definitions. `usb_interface_descriptor` uses an `inner` struct, which is `usb_interface_descriptor_eps_array_t`. Looking at the types, `bInterfaceClass` *should* be zero, since it's defined as a `const[0, int8]`.  I've confirmed that `bLength` is 9, which is also correct as `const[USB_DT_INTERFACE_SIZE, int8]`.

Now, let's step through the fields of `usb_interface_descriptor_verbose_t`:
1.  `bLength = 9` (Correct, `USB_DT_INTERFACE_SIZE`)
2.  `bDescriptorType = 4` (Interface)
3.  `bInterfaceNumber = 0`
4.  `bAlternateSetting = 0`
5.  `bNumEndpoints = AUTO`
6.  `bInterfaceClass = 0` (Confirmed)
7.  `bInterfaceSubClass = 0`
8.  `bInterfaceProtocol = 0`
9.  `iInterface = 0`
10. `extra = []` (Empty array)
11. `endpoints = []` (Empty array)

I'm passing `int8` for `iInterface` which is correct, and I've provided empty arrays for `extra` and `endpoints`, which makes sense given the type definitions. I'm starting to get a bit stuck here since `bNumEndpoints` is `AUTO`, determined by the `len` of `endpoints`.

The key is this: `usb_interface_descriptor` is composed of `usb_interface_descriptor_eps_array_t`, where `bNumEndpoints` is `AUTO` and determined by the length of the `endpoints` array.

Now let's check the config descriptor. `usb_config_descriptor_ifaces_array_t` and `usb_config_descriptor_t` give us the `usb_config_descriptor_verbose_t` struct. I am providing `[{{{9, 4, 0, 0, AUTO, 0, 0, 0, 0, [], []}}}]`.

After considering the fields in `usb_config_descriptor_verbose_t`:
1.  `bLength = 9` (Looks fine)
2.  `bDescriptorType = 2` (Config)
3.  `wTotalLength = AUTO`
4.  `bNumInterfaces = AUTO`
5.  `bConfigurationValue = 1`
6.  `iConfiguration = 0`
7.  `bmAttributes = 0x80`
8.  `bMaxPower = 0`
9.  `extra = ""` (Empty string)
10. `interfaces = [{{9, 4, 0, 0, AUTO, 0, 0, 0, 0, [], []}}]`

The thing that clicks is the `interfaces` array; it should be an array of `usb_interface_descriptor` which is constructed from the inner `usb_interface_descriptor_eps_array_t`. I'm constructing an interface correctly. Early on I tried an array with non-zero values for `extra`, and that caused the type problem with the array. Since the extra struct now is void it's not a problem!

Okay, let's try the complete structure now!



291/2 2026/07/30 13:04 tool reproduce-crash
2m Args:
map[ReproSyz:r0 = syz_usb_connect(3, 0, &AUTO={{18, 1, 0x200, 0, 0, 0, 64, 0x2040, 0x7200, 0, 0, 0, 0, AUTO, [{{9, 2, AUTO, AUTO, 1, 0, 0x80, 0, "", [{{9, 4, 0, 0, AUTO, 0, 0, 0, 0, [], []}}]}}]}}, 0)
r1 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r2 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r3 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r4 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r1, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r2, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r3, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r4, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID:repro/a8b2bc0743561b212b58b65173931b46708db046 ReproducedBugTitle: ReproducedCrashReport:]

292/2 2026/07/30 13:06 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 108813
							output: 60
							thoughts: 14
						

Thoughts:
Here's my attempt at summarizing the thought process, tailored for an expert audience:

**Initial Assessment: Success and Immediate Verification**

Okay, it didn't crash. That's a huge relief. Now, instead of patting myself on the back too soon, my next immediate thought is to systematically verify the success. The crash test went well, but that's just the starting point. Time to dive straight into a comprehensive coverage analysis. We need to ascertain which code paths were executed and, critically, which areas remain untested, particularly around edge cases. I'll need to know the state of the coverage metrics – which branches were hit, which lines weren't, the overall percentage. Only then can I consider this a true pass, or at least a step closer to it.



293/2 2026/07/30 13:06 tool get-coverage-files
0m Args:
map[ExecutionCachedID:repro/a8b2bc0743561b212b58b65173931b46708db046]

Results:
map[Files:[arch/x86/entry/vsyscall/vsyscall_64.c arch/x86/include/asm/atomic64_64.h arch/x86/include/asm/bitops.h arch/x86/include/asm/compat.h arch/x86/include/asm/cpufeature.h arch/x86/include/asm/irqflags.h arch/x86/include/asm/jump_label.h arch/x86/include/asm/mmu_context.h arch/x86/include/asm/page.h arch/x86/include/asm/pgtable.h arch/x86/include/asm/pkru.h arch/x86/include/asm/preempt.h arch/x86/include/asm/trace/fpu.h arch/x86/kernel/cpu/aperfmperf.c arch/x86/kernel/fpu/context.h arch/x86/kernel/fpu/core.c arch/x86/kernel/fpu/internal.h arch/x86/kernel/fpu/xstate.c arch/x86/kernel/kvm.c arch/x86/kernel/tsc.c arch/x86/mm/fault.c arch/x86/mm/maccess.c arch/x86/mm/pgtable.c arch/x86/pci/common.c arch/x86/pci/direct.c block/blk-cgroup.c drivers/acpi/acpica/nsaccess.c drivers/acpi/acpica/nsdump.c drivers/acpi/acpica/nssearch.c drivers/acpi/acpica/nsutils.c drivers/acpi/acpica/nsxfname.c drivers/acpi/acpica/utascii.c drivers/acpi/acpica/utdebug.c drivers/acpi/acpica/utmutex.c drivers/acpi/acpica/utstring.c drivers/acpi/device_pm.c drivers/acpi/osl.c drivers/acpi/property.c drivers/acpi/utils.c drivers/base/core.c drivers/base/map.c drivers/base/power/qos.c drivers/base/power/runtime.c drivers/base/power/wakeirq.c drivers/char/misc.c drivers/i2c/busses/i2c-i801.c drivers/i2c/i2c-core-base.c drivers/i2c/i2c-core-smbus.c drivers/i2c/i2c-core.h drivers/i2c/i2c-dev.c drivers/pci/access.c drivers/pci/ats.c drivers/pci/host-bridge.c drivers/pci/iov.c drivers/pci/msi/api.c drivers/pci/msi/msi.c drivers/pci/pci-acpi.c drivers/pci/pci-driver.c drivers/pci/pci.c drivers/pci/pcie/aer.c drivers/pci/pcie/aspm.c drivers/pci/quirks.c drivers/pci/rebar.c drivers/pci/vc.c drivers/usb/gadget/legacy/raw_gadget.c fs/char_dev.c fs/d_path.c fs/dcache.c fs/file.c fs/file_table.c fs/ioctl.c fs/libfs.c fs/mnt_idmapping.c fs/namei.c fs/namespace.c fs/notify/fsnotify.c fs/open.c include/acpi/acpi_bus.h include/asm-generic/bitops/instrumented-non-atomic.h include/linux/atomic/atomic-arch-fallback.h include/linux/atomic/atomic-instrumented.h include/linux/atomic/atomic-long.h include/linux/audit.h include/linux/bit_spinlock.h include/linux/cgroup.h include/linux/clockchips.h include/linux/cpumask.h include/linux/cred.h include/linux/dcache.h include/linux/delayed_call.h include/linux/device.h include/linux/device_cgroup.h include/linux/err.h include/linux/file.h include/linux/file_ref.h include/linux/filelock.h include/linux/find.h include/linux/folio_batch.h include/linux/fs.h include/linux/fs/super.h include/linux/fsnotify.h include/linux/fsnotify_backend.h include/linux/hrtimer.h include/linux/jiffies.h include/linux/jump_label.h include/linux/kernel.h include/linux/kref.h include/linux/list.h include/linux/list_bl.h include/linux/llist.h include/linux/log2.h include/linux/lsm_hook_defs.h include/linux/maple_tree.h include/linux/memcontrol.h include/linux/mempolicy.h include/linux/mm.h include/linux/mmzone.h include/linux/mount.h include/linux/nodemask.h include/linux/page-flags.h include/linux/page_ref.h include/linux/pagemap.h include/linux/perf_event.h include/linux/pgtable.h include/linux/pid.h include/linux/pm_qos.h include/linux/preempt.h include/linux/rbtree.h include/linux/rbtree_latch.h include/linux/rculist_bl.h include/linux/rcupdate.h include/linux/refcount.h include/linux/rmap.h include/linux/rtmutex.h include/linux/sched.h include/linux/sched/isolation.h include/linux/seqlock.h include/linux/spinlock_rt.h include/linux/srcu.h include/linux/swap.h include/linux/thread_info.h include/linux/timer.h include/linux/uaccess.h include/linux/ucopysize.h include/linux/userfaultfd_k.h include/linux/workqueue.h include/linux/xarray.h include/trace/events/exceptions.h include/trace/events/filemap.h include/trace/events/kmem.h include/trace/events/rpm.h include/trace/events/smbus.h include/trace/events/timer.h kernel/bpf/core.c kernel/cgroup/rstat.c kernel/kthread.c kernel/pid.c kernel/printk/printk_safe.c kernel/time/clockevents.c kernel/time/hrtimer.c kernel/time/posix-timers.c kernel/time/sleep_timeout.c kernel/time/tick-oneshot.c kernel/time/tick-sched.c kernel/time/time.c kernel/time/timekeeping.c kernel/time/timer.c lib/cpumask.c lib/errseq.c lib/idr.c lib/iomap.c lib/kobject.c lib/lockref.c lib/maple_tree.c lib/percpu_counter.c lib/radix-tree.c lib/strncpy_from_user.c lib/timerqueue.c lib/usercopy.c lib/vsprintf.c lib/xarray.c mm/backing-dev.c mm/fail_page_alloc.c mm/filemap.c mm/internal.h mm/list_lru.c mm/maccess.c mm/memory.c mm/mempolicy.c mm/mmap_lock.c mm/page_ext.c mm/page_owner.c mm/page_table_check.c mm/pgtable-generic.c mm/readahead.c mm/rmap.c mm/swap.c mm/swapfile.c security/device_cgroup.c security/integrity/ima/ima_main.c security/landlock/cred.h security/landlock/fs.c security/landlock/ruleset.c security/security.c security/smack/smack_access.c security/smack/smack_lsm.c security/tomoyo/audit.c security/tomoyo/common.c security/tomoyo/common.h security/tomoyo/domain.c security/tomoyo/file.c security/tomoyo/realpath.c security/tomoyo/tomoyo.c security/tomoyo/util.c usercopy_64.c]]

294/2 2026/07/30 13:06 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 111700
							output: 23
							thoughts: 1534
						

Thoughts:
**USB Device ID Investigation: `au0828` Coverage**

Okay, so I'm trying to figure out why the `au0828` device isn't being covered by syzkaller, even though I've specified its Vendor ID (`0x2040`) and Product ID (`0x7200`). The initial assumption was that `syz_usb_connect` might be the culprit, as it's the syzkaller call I'm using to connect USB devices.

My first thought was that `syz_usb_connect` was modifying the `idVendor` and `idProduct` fields. I recalled that the `sys/linux/init_vusb.go` file (or `vusb.txt`) specifically mentions that the Go code patches these fields. I remembered `syz_usb_connect` patches these IDs to a specific list and, indeed, if I use `syz_usb_connect` alone with a basic `usb_device_descriptor`, it *would* overwrite my specified IDs.

However, I remembered that `syz_usb_connect` has variants. Specifically, the `$rtl8150` variant uses `usb_device_descriptor_rtl8150` which leverages `const` fields for `VENDOR` and `PRODUCT`, preventing patching. That's a good lead! Syzkaller doesn't patch `const` fields, which is perfect for forcing specific IDs.

But, a standard `usb_device_descriptor` struct uses `const[VENDOR, int16]` and `const[PRODUCT, int16]`. However, these are defined to `0` by default. And because syzkaller's Go code looks at the struct's definition to modify the IDs, I realised it's done during struct generation, not during execution. So if I pass a fully formed struct, it *shouldn't* be overwritten.

I considered passing a raw buffer to `syz_usb_connect` but, as expected, it complains about the argument type. I also went through and confirmed that the `$rtl8150` variant uses its own `VENDOR` and `PRODUCT` fields. But I'm targeting a different device.

So, I circled back to the fundamental point: If I use `syz_usb_connect` and provide `0x2040` and `0x7200` directly in the struct literal, will syzkaller overwrite it? The answer is *no*. `init_vusb.go` does its patching during generation or mutation, not during execution. If I provide a concrete program, it's executed *as is*. This means the ID's I provide should be used! So *why* is the `au0828` driver not probing?

It hit me, the problem wasn't the IDs! It's *what happens after* the USB device is connected. I re-examined the `au0828_usb_probe` function. I had set `bInterfaceNumber = 0`, and USB speed to high. Those were covered!

Therefore, the driver *is* probing! So what's wrong? The problem isn't with the IDs. I need to look at other failure points. The problem must be somewhere else in the driver probe function, or it might not be included in the kernel configuration.



295/2 2026/07/30 13:07 tool grepper
0m Args:
map[Expression:CONFIG_VIDEO_AU0828]

Results:
map[Output:drivers/media/usb/Makefile=24=obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/
drivers/media/usb/Makefile:25:obj-$(CONFIG_VIDEO_AU0828) += au0828/
drivers/media/usb/Makefile-26-obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
--
drivers/media/usb/au0828/Makefile=2=au0828-objs	:= au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o
drivers/media/usb/au0828/Makefile-3-
drivers/media/usb/au0828/Makefile:4:ifeq ($(CONFIG_VIDEO_AU0828_V4L2),y)
drivers/media/usb/au0828/Makefile-5-  au0828-objs   += au0828-video.o au0828-vbi.o
drivers/media/usb/au0828/Makefile=6=endif
drivers/media/usb/au0828/Makefile-7-
drivers/media/usb/au0828/Makefile:8:ifeq ($(CONFIG_VIDEO_AU0828_RC),y)
drivers/media/usb/au0828/Makefile-9-  au0828-objs   += au0828-input.o
drivers/media/usb/au0828/Makefile=10=endif
drivers/media/usb/au0828/Makefile-11-
drivers/media/usb/au0828/Makefile:12:obj-$(CONFIG_VIDEO_AU0828) += au0828.o
drivers/media/usb/au0828/Makefile-13-
--
drivers/media/usb/au0828/au0828-cards.c=246=void au0828_card_analog_fe_setup(struct au0828_dev *dev)
drivers/media/usb/au0828/au0828-cards.c-247-{
drivers/media/usb/au0828/au0828-cards.c:248:#ifdef CONFIG_VIDEO_AU0828_V4L2
drivers/media/usb/au0828/au0828-cards.c-249-	struct tuner_setup tun_setup;
--
drivers/media/usb/au0828/au0828-i2c.c=354=int au0828_i2c_register(struct au0828_dev *dev)
--
drivers/media/usb/au0828/au0828-i2c.c-368-	dev->i2c_adap.algo_data = dev;
drivers/media/usb/au0828/au0828-i2c.c:369:#ifdef CONFIG_VIDEO_AU0828_V4L2
drivers/media/usb/au0828/au0828-i2c.c-370-	i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
--
drivers/media/usb/au0828/au0828.h=173=struct au0828_dev {
--
drivers/media/usb/au0828/au0828.h-191-
drivers/media/usb/au0828/au0828.h:192:#ifdef CONFIG_VIDEO_AU0828_V4L2
drivers/media/usb/au0828/au0828.h-193-	/* Analog */
--
drivers/media/usb/au0828/au0828.h-196-#endif
drivers/media/usb/au0828/au0828.h:197:#ifdef CONFIG_VIDEO_AU0828_RC
drivers/media/usb/au0828/au0828.h-198-	struct au0828_rc *ir;
--
drivers/media/usb/au0828/au0828.h=322=extern void au0828_stop_vbi_streaming(struct vb2_queue *vq);
drivers/media/usb/au0828/au0828.h:323:#ifdef CONFIG_VIDEO_AU0828_V4L2
drivers/media/usb/au0828/au0828.h-324-extern int au0828_v4l2_device_register(struct usb_interface *interface,
--
drivers/media/usb/au0828/au0828.h=355=extern const struct vb2_ops au0828_vbi_qops;
--
drivers/media/usb/au0828/au0828.h-362-/* au0828-input.c */
drivers/media/usb/au0828/au0828.h:363:#ifdef CONFIG_VIDEO_AU0828_RC
drivers/media/usb/au0828/au0828.h-364-extern int au0828_rc_register(struct au0828_dev *dev);
]

296/2 2026/07/30 13:07 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 115354
							output: 457
							thoughts: 448
						

Thoughts:
**Analyzing USB Driver Coverage in Syzbot**

Okay, so I need to figure out if the `CONFIG_VIDEO_AU0828` driver is actually enabled in syzbot. The easy way is usually to check if the corresponding source file, `drivers/media/usb/au0828/au0828-core.c`, got compiled. I could use `git-log` or `grepper` to look for "au0828" in the kernel config used by syzbot, but I don't have direct access to that. 

Wait, the `au0828` driver is a media driver! Media drivers are generally enabled in syzbot as a rule. But... what if it *isn't* covered? Maybe it's NOT enabled. Let me go back and re-check `si4713` as a sanity check. Is *that* enabled? The relevant source would be `drivers/media/radio/si4713/radio-usb-si4713.c`. Okay, back to the main goal.

Now, if I use `syz_usb_connect` with `idVendor=0x10c4` and `idProduct=0x8244` and set `bInterfaceClass=3` (which is HID), will that work? Hmm, I couldn't set `bInterfaceClass=3` before because the `usb_interface_descriptor` was forcing `bInterfaceClass` to be zero! But... I *can* use `syz_usb_connect$hid`! That function uses `usb_device_descriptor_hid`. Okay, good.

Now, the `usb_device_descriptor_hid` definition has `VENDOR=0` and `PRODUCT=0`. So, if I use `syz_usb_connect$hid`, syzkaller patches the `VENDOR` and `PRODUCT` fields to random HID device values. But, hey, wait, can I just use the plain `syz_usb_connect` function and pass `ANY` for those values instead?

The thing is, `syz_usb_connect` takes a `dev` pointer, using `usb_device_descriptor` as its in parameter. Can I provide a raw byte array as the value of the device descriptor using something like `&AUTO="1201..."`? Let's give it a shot, that would be incredibly useful!



297/2 2026/07/30 13:07 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 18, &AUTO="\x12\x01\x00\x02\x00\x00\x00\x40\xc4\x10\x44\x82\x00\x00\x00\x00\x00\x01", 0)
r1 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r2 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r3 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r4 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r1, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r2, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r3, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r4, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

298/2 2026/07/30 13:07 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 116913
							output: 430
							thoughts: 83
						

Thoughts:
Okay, here's my take on those thoughts, framed as my own mental processing:

**Debugging a Stubborn Data Type**

Ugh, "wrong string arg." Of course! This function expects a *struct*, not a plain string. Rookie mistake, but easily corrected. Hmm, how can I bypass this string requirement? That's it! I can use an `ANY` struct. This should be flexible enough to accommodate what I have. Let's try this hacky approach: `&AUTO=ANY=[@ANYBLOB="1201000200000040c4104482000000000001"]`. It will work!



299/2 2026/07/30 13:07 tool reproduce-crash
2m Args:
map[ReproSyz:r0 = syz_usb_connect(3, 18, &AUTO=ANY=[@ANYBLOB="1201000200000040c4104482000000000001"], 0)
r1 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r2 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r3 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r4 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r1, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r2, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r3, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r4, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID:repro/c7e53a2b58119e9438a81744520064a9f96ef059 ReproducedBugTitle: ReproducedCrashReport:]

300/2 2026/07/30 13:09 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 117656
							output: 61
							thoughts: 14
						

Thoughts:
Here's my attempt at summarizing the thought process, tailored for an expert audience:

**Coverage Check After Non-Crash**

Okay, so it didn't completely blow upβ€”that's a relief. But just because it didn't *crash* doesn't mean everything's peachy keen. My immediate thought is, "What's the coverage like?". A clean run doesn't necessarily mean a comprehensive one. I need to dig into the test coverage metrics, understand what code paths were actually exercised, and identify any gaps. Did we hit all the edge cases? Did the test suite execute the full range of expected behaviors? I'm not going to celebrate a successful run until I have a rock-solid understanding of what was and wasn't tested. I need to make sure we're not just dodging bullets; we're hitting our targets.



301/2 2026/07/30 13:09 tool get-coverage-files
0m Args:
map[ExecutionCachedID:repro/c7e53a2b58119e9438a81744520064a9f96ef059]

Results:
map[Files:[arch/x86/entry/vsyscall/vsyscall_64.c arch/x86/include/asm/atomic64_64.h arch/x86/include/asm/bitops.h arch/x86/include/asm/compat.h arch/x86/include/asm/cpufeature.h arch/x86/include/asm/irqflags.h arch/x86/include/asm/jump_label.h arch/x86/include/asm/mmu_context.h arch/x86/include/asm/page.h arch/x86/include/asm/pgtable.h arch/x86/include/asm/pkru.h arch/x86/include/asm/preempt.h arch/x86/kernel/cpu/aperfmperf.c arch/x86/kernel/fpu/context.h arch/x86/kernel/fpu/core.c arch/x86/kernel/kvm.c arch/x86/kernel/tsc.c arch/x86/mm/fault.c arch/x86/mm/maccess.c arch/x86/mm/pgtable.c arch/x86/pci/common.c arch/x86/pci/direct.c block/blk-cgroup.c drivers/acpi/acpica/nsaccess.c drivers/acpi/acpica/nsdump.c drivers/acpi/acpica/nssearch.c drivers/acpi/acpica/nsutils.c drivers/acpi/acpica/nsxfname.c drivers/acpi/acpica/utascii.c drivers/acpi/acpica/utdebug.c drivers/acpi/acpica/utmutex.c drivers/acpi/acpica/utstring.c drivers/acpi/device_pm.c drivers/acpi/osl.c drivers/acpi/property.c drivers/acpi/utils.c drivers/base/core.c drivers/base/map.c drivers/base/power/qos.c drivers/base/power/runtime.c drivers/base/power/wakeirq.c drivers/char/misc.c drivers/i2c/busses/i2c-i801.c drivers/i2c/i2c-core-base.c drivers/i2c/i2c-core-smbus.c drivers/i2c/i2c-core.h drivers/i2c/i2c-dev.c drivers/pci/access.c drivers/pci/ats.c drivers/pci/host-bridge.c drivers/pci/iov.c drivers/pci/msi/api.c drivers/pci/msi/msi.c drivers/pci/pci-acpi.c drivers/pci/pci-driver.c drivers/pci/pci.c drivers/pci/pcie/aer.c drivers/pci/pcie/aspm.c drivers/pci/quirks.c drivers/pci/rebar.c drivers/pci/vc.c drivers/usb/gadget/legacy/raw_gadget.c fs/char_dev.c fs/d_path.c fs/dcache.c fs/file.c fs/file_table.c fs/ioctl.c fs/libfs.c fs/mnt_idmapping.c fs/namei.c fs/namespace.c fs/notify/fsnotify.c fs/open.c include/acpi/acpi_bus.h include/asm-generic/bitops/instrumented-non-atomic.h include/asm-generic/pgalloc.h include/linux/atomic/atomic-arch-fallback.h include/linux/atomic/atomic-instrumented.h include/linux/atomic/atomic-long.h include/linux/audit.h include/linux/bit_spinlock.h include/linux/cgroup.h include/linux/clockchips.h include/linux/cpumask.h include/linux/cred.h include/linux/dcache.h include/linux/delayed_call.h include/linux/device.h include/linux/device_cgroup.h include/linux/err.h include/linux/file.h include/linux/file_ref.h include/linux/filelock.h include/linux/find.h include/linux/folio_batch.h include/linux/fs.h include/linux/fs/super.h include/linux/fsnotify.h include/linux/fsnotify_backend.h include/linux/hrtimer.h include/linux/jiffies.h include/linux/jump_label.h include/linux/kernel.h include/linux/kref.h include/linux/list.h include/linux/list_bl.h include/linux/llist.h include/linux/log2.h include/linux/lsm_hook_defs.h include/linux/maple_tree.h include/linux/memcontrol.h include/linux/mempolicy.h include/linux/mm.h include/linux/mmzone.h include/linux/mount.h include/linux/nodemask.h include/linux/page-flags.h include/linux/page_ref.h include/linux/pagemap.h include/linux/perf_event.h include/linux/pgtable.h include/linux/pid.h include/linux/pm_qos.h include/linux/preempt.h include/linux/rbtree.h include/linux/rbtree_latch.h include/linux/rculist_bl.h include/linux/rcupdate.h include/linux/refcount.h include/linux/rmap.h include/linux/rtmutex.h include/linux/sched.h include/linux/sched/isolation.h include/linux/seqlock.h include/linux/spinlock_rt.h include/linux/srcu.h include/linux/swap.h include/linux/thread_info.h include/linux/timer.h include/linux/uaccess.h include/linux/ucopysize.h include/linux/userfaultfd_k.h include/linux/vmstat.h include/linux/workqueue.h include/linux/xarray.h include/trace/events/exceptions.h include/trace/events/filemap.h include/trace/events/kmem.h include/trace/events/rpm.h include/trace/events/smbus.h include/trace/events/timer.h kernel/bpf/core.c kernel/cgroup/rstat.c kernel/kthread.c kernel/pid.c kernel/printk/printk_safe.c kernel/time/clockevents.c kernel/time/hrtimer.c kernel/time/posix-timers.c kernel/time/sleep_timeout.c kernel/time/tick-oneshot.c kernel/time/tick-sched.c kernel/time/time.c kernel/time/timekeeping.c kernel/time/timer.c lib/cpumask.c lib/errseq.c lib/idr.c lib/iomap.c lib/kobject.c lib/lockref.c lib/maple_tree.c lib/percpu_counter.c lib/plist.c lib/radix-tree.c lib/strncpy_from_user.c lib/timerqueue.c lib/usercopy.c lib/vsprintf.c lib/xarray.c mm/backing-dev.c mm/fail_page_alloc.c mm/filemap.c mm/internal.h mm/list_lru.c mm/maccess.c mm/memory.c mm/mempolicy.c mm/mmap_lock.c mm/page_counter.c mm/page_ext.c mm/page_owner.c mm/page_table_check.c mm/pgtable-generic.c mm/readahead.c mm/rmap.c mm/swap.c mm/swapfile.c security/device_cgroup.c security/integrity/ima/ima_main.c security/landlock/cred.h security/landlock/fs.c security/landlock/ruleset.c security/security.c security/smack/smack_access.c security/smack/smack_lsm.c security/tomoyo/audit.c security/tomoyo/common.c security/tomoyo/common.h security/tomoyo/domain.c security/tomoyo/file.c security/tomoyo/realpath.c security/tomoyo/tomoyo.c security/tomoyo/util.c usercopy_64.c]]

302/2 2026/07/30 13:09 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 120550
							output: 736
							thoughts: 1462
						

Thoughts:
**USB Device Probe Troubleshooting**

Okay, so I'm still not seeing the `au0828` or `si4713` devices pop up. I tried using `syz_usb_connect` with `ANY`, but that didn't trigger them either. Why? Let's dig in. I know `syz_usb_connect` uses `raw_gadget`, and I confirmed that `raw_gadget` is covered, meaning the USB device is being *created*. But still no probe? It has to be the USB IDs.

I provided `0x2040` and `0x7200` in the `ANY` blob, so I need to check the exact contents.  Let me see...

Okay, I'm looking at the hex dump of the blob now. Ah, there it is! I've confirmed that this *is* `si4713`, `0x10c4:0x8244`. But `si4713` needs `bDeviceClass = 0` and `bInterfaceClass = 3` (HID). The problem is, with `ANY` for `dev`, `syz_usb_connect` only overrides the `usb_device_descriptor`. What I need is the *entire* device configuration.

I remember now, `syz_usb_connect` takes `dev ptr[in, usb_device_descriptor]`, but it *expects* the `configs` array to be present *within* that `usb_device_descriptor` struct! Syzkaller defines the struct as, essentially, `usb_device_descriptor { inner usb_device_descriptor_t[0, 0, 0, 0, 0, 0, array[usb_config_descriptor, 1]] } [packed]`. So, the `configs` array is *inlined*.

If I give it an `ANY` blob of only 18 bytes, which only represents the device descriptor, it *doesn't* include the configuration descriptors. This means `syz_usb_connect` sends a device descriptor of length 18, and *no* config descriptors! Then, `syz_usb_connect` reads from an empty `configs` array. No configurations mean no probes!

I need to give it the *full* blob, including the config, interface, and endpoint descriptors!

Okay, let's construct the complete blob for `si4713`.

*   Device descriptor (18 bytes): `12 01 00 02 00 00 00 40 c4 10 44 82 00 00 00 00 00 01`
*   Config descriptor (9 bytes): `09 02 22 00 01 01 00 80 00` (wTotalLength = 34, bNumInterfaces = 1)
*   Interface descriptor (9 bytes): `09 04 00 00 01 03 00 00 00` (bInterfaceClass = 3 (HID), bNumEndpoints = 1)
*   HID descriptor (9 bytes): `09 21 11 01 00 01 22 22 00` (bDescriptorType = 0x21 (HID), wDescriptorLength = 34)
*   Endpoint descriptor (7 bytes): `07 05 81 03 40 00 01` (bEndpointAddress = 0x81 (IN), bmAttributes = 3 (Interrupt), wMaxPacketSize = 64, bInterval = 1)

`si4713` uses `USB_CLASS_HID`. I'll concatenate them:

*   Device: `1201000200000040c4104482000000000001`
*   Config: `090222000101008000`
*   Interface: `090400000103000000`
*   HID: `092111010001222200`
*   Endpoint: `07058103400001`

Wait a minute, `wTotalLength` is `9 + 9 + 9 + 7 = 34` which is `0x


303/2 2026/07/30 13:10 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 52, &AUTO=ANY=[@ANYBLOB="1201000200000040c410448200000000000109022200010100800009040000010300000009211101000122220007058103400001"], 0)
syz_usb_control_io(r0, 0, &AUTO={AUTO, @generic={0x20, 0x01, AUTO, [0, 0, 0, 0, 0, 0, 0, 0]}})
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

304/2 2026/07/30 13:10 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 123868
							output: 736
							thoughts: 140
						

Thoughts:
Here's my thought process, as it went down:

**Investigating the `vusb_responses` Structure**

Okay, so I'm looking at `vusb_responses`, and I'm realizing something immediately - there's no `@generic` *tag* defined. I was expecting a union with the `@generic` option, but it seems that's not the case. Let me double-check the definition of the `vusb_responses` struct itself.

Okay, here it is: `vusb_responses` has `len` (integer) and then `generic` which is a pointer to `vusb_response_generic`. The key thing to note is that `generic` is defined as a field of this struct, not an option within a union. It's a pointer to a struct.

Ah ha! So, the way this should be handled isn't a simple `@generic` reference within a union, it’s going to involve an `&AUTO` construct! Thinking about the expected usage, it's very likely that `generic` is going to be initialized with some default values. That means it needs to be `&AUTO={AUTO, &AUTO={0x20, 0x01, AUTO, [0, 0, 0, 0, 0, 0, 0, 0]}}` to make sure the field is properly allocated with some reasonable defaults. Let's try that and see if it works. I'm pretty confident that's the correct approach given the data layout.



305/2 2026/07/30 13:10 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 52, &AUTO=ANY=[@ANYBLOB="1201000200000040c410448200000000000109022200010100800009040000010300000009211101000122220007058103400001"], 0)
syz_usb_control_io(r0, 0, &AUTO={AUTO, &AUTO={0x20, 0x01, AUTO, [0, 0, 0, 0, 0, 0, 0, 0]}})
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

306/2 2026/07/30 13:10 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 125171
							output: 745
							thoughts: 195
						

Thoughts:
**Debugging a Type Mismatch**

Okay, so I'm looking at this code and I see `data` is defined as an `array[int8, 0:256]`. But I'm getting a `wrong array arg *prog.BufferType` error, which makes me scratch my head. I know I've seen this pattern before, and I think it's clicking... wait, an `array[int8]` can often be *represented* as a string!

So, with that in mind, does `&AUTO={0x20, 0x01, AUTO, "0000000000000000"}` make sense here? I need to check the exact type...

Hold on, I see it now. The `data` variable within `vusb_response_generic` is indeed an `array[int8, 0:256]`. Knowing this, if it is treated as a generic `array[int8]`, I can utilize either an empty string `""` or something like `"\x00\x00..."` to initialize it. I think using an empty string or something like `"\x00\x00\x00\x00\x00\x00\x00\x00"` for empty data will be the cleanest approach.



307/2 2026/07/30 13:10 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 52, &AUTO=ANY=[@ANYBLOB="1201000200000040c410448200000000000109022200010100800009040000010300000009211101000122220007058103400001"], 0)
syz_usb_control_io(r0, 0, &AUTO={AUTO, &AUTO={0x20, 0x01, AUTO, "\x00\x00\x00\x00\x00\x00\x00\x00"}})
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

308/2 2026/07/30 13:10 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 126517
							output: 730
							thoughts: 252
						

Thoughts:
**Debugging Syzkaller String Literals**

Okay, so I'm running into an issue with a null byte (`\x00`) in a string literal within syzkaller.  Right, I remember that's generally not allowed unless I'm using a hex literal or properly escaping it. I thought I could use `[]` for arrays, and considered that as an option, but the error message, "wrong array arg *prog.BufferType," is throwing me off.  `BufferType`...right, that implies it's expecting either a regular string or a hex literal. Okay, I've got a plan.

I think I can try constructing the value with the form `AUTO="0000000000000000"` or `&AUTO="0000000000000000"` to represent the value as a hex literal.  But hold on... looking at the context, `data` is defined as `array[int8, 0:256]`.  So, if it's treated as `array[int8]`, syzkaller expects a string or hex literal. The question is, can I just use an empty string, `""`? Or will that not work and do I need `&AUTO=""`? It's a field though. Since it's a field I should be able to just use `""` or the hex literal `"0000000000000000"`. I think the hex literal is the safest bet given the previous error. Okay, let's try `"0000000000000000"` and see if that resolves the issue!



309/2 2026/07/30 13:10 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, 52, &AUTO=ANY=[@ANYBLOB="1201000200000040c410448200000000000109022200010100800009040000010300000009211101000122220007058103400001"], 0)
syz_usb_control_io(r0, 0, &AUTO={AUTO, &AUTO={0x20, 0x01, AUTO, "0000000000000000"}})
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

310/2 2026/07/30 13:10 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 127969
							output: 774
							thoughts: 528
						

Thoughts:
**Analyzing the `vusb_responses` Structure**

Okay, so I'm looking at this `vusb_responses` structure, and it's got way more fields than I initially accounted for. I only set up `len` and `generic` in my original setup. Now I see there are a bunch of other fields like `get_interface`, `get_configuration`, and a whole host of `asix_` related responses that I'm not directly using. The documentation and the code show seventeen fields in total. 

Right, so to make this work, I need to make sure those remaining fields are initialized properly. Instead of having to define 0 for all those fields manually, I think I'll use the convenience of the `AUTO` macro and the syntax I know for setting everything else to zero. I think I can use `&AUTO={AUTO, &AUTO={0x20, 0x01, AUTO, "0000000000000000"}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}` to quickly address this. The first two auto fields handles `len` and `generic`, and then I will set 15 subsequent zeros to address the rest of the fields. That should take care of it and keep things clean.



311/2 2026/07/30 13:11 tool reproduce-crash
2m Args:
map[ReproSyz:r0 = syz_usb_connect(3, 52, &AUTO=ANY=[@ANYBLOB="1201000200000040c410448200000000000109022200010100800009040000010300000009211101000122220007058103400001"], 0)
syz_usb_control_io(r0, 0, &AUTO={AUTO, &AUTO={0x20, 0x01, AUTO, "0000000000000000"}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})
r1 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 0, 0)
r2 = syz_open_dev$video(&(0x7f0000000000)='/dev/video#\x00', 1, 0)
r3 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 0, 0)
r4 = syz_open_dev$radio(&(0x7f0000000000)='/dev/radio#\x00', 1, 0)
r5 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 0, 0)
r6 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 1, 0)
r7 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 2, 0)
r8 = syz_open_dev$I2C(&(0x7f0000000000)='/dev/i2c-#\x00', 3, 0)
syz_usb_disconnect(r0)
ioctl$I2C_SMBUS(r5, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r6, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r7, 0x720, &AUTO={0, 0, 0, 0})
ioctl$I2C_SMBUS(r8, 0x720, &AUTO={0, 0, 0, 0}) Sandbox:none]

Results:
map[ExecutionCachedID:repro/ba2e75bc88e306a9def048b4fee6aae4a206c25a ReproducedBugTitle: ReproducedCrashReport:]

312/2 2026/07/30 13:13 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 129649
							output: 55
							thoughts: 12
						

Thoughts:
Okay, here's my take on those thoughts, tailored for an expert audience:

**Initial Assessment and Verification**

Phew, that didn't go as expected; the system didn't crash. Good. My first instinct is to immediately shift focus to coverage. A successful execution is great, but without comprehensive test coverage, we're essentially flying blind. I need to know *how much* of the codebase this execution actually touched. A lack of crash doesn't guarantee correctness, only that we didn't trigger an immediate catastrophic failure. Now, let's drill down into the coverage reports. I want to see line-level detail, branches taken, and any gaps that might indicate untested code paths.



313/2 2026/07/30 13:13 tool get-coverage-files
0m Args:
map[ExecutionCachedID:repro/ba2e75bc88e306a9def048b4fee6aae4a206c25a]

Results:
map[Files:[arch/x86/entry/vsyscall/vsyscall_64.c arch/x86/include/asm/atomic.h arch/x86/include/asm/atomic64_64.h arch/x86/include/asm/bitops.h arch/x86/include/asm/compat.h arch/x86/include/asm/cpufeature.h arch/x86/include/asm/irqflags.h arch/x86/include/asm/jump_label.h arch/x86/include/asm/mmu_context.h arch/x86/include/asm/page.h arch/x86/include/asm/pgtable.h arch/x86/include/asm/pkru.h arch/x86/include/asm/preempt.h arch/x86/include/asm/trace/fpu.h arch/x86/kernel/cpu/aperfmperf.c arch/x86/kernel/fpu/context.h arch/x86/kernel/fpu/core.c arch/x86/kernel/fpu/internal.h arch/x86/kernel/fpu/xstate.c arch/x86/kernel/kvm.c arch/x86/kernel/tsc.c arch/x86/mm/fault.c arch/x86/mm/maccess.c arch/x86/mm/pgtable.c arch/x86/pci/common.c arch/x86/pci/direct.c block/blk-cgroup.c drivers/acpi/acpica/nsaccess.c drivers/acpi/acpica/nsdump.c drivers/acpi/acpica/nssearch.c drivers/acpi/acpica/nsutils.c drivers/acpi/acpica/nsxfname.c drivers/acpi/acpica/utascii.c drivers/acpi/acpica/utdebug.c drivers/acpi/acpica/utmutex.c drivers/acpi/acpica/utstring.c drivers/acpi/device_pm.c drivers/acpi/glue.c drivers/acpi/osl.c drivers/acpi/property.c drivers/acpi/utils.c drivers/base/base.h drivers/base/bus.c drivers/base/class.c drivers/base/core.c drivers/base/dd.c drivers/base/devres.c drivers/base/devtmpfs.c drivers/base/driver.c drivers/base/map.c drivers/base/module.c drivers/base/physical_location.c drivers/base/power/common.c drivers/base/power/main.c drivers/base/power/power.h drivers/base/power/qos.c drivers/base/power/runtime.c drivers/base/power/sysfs.c drivers/base/power/wakeirq.c drivers/base/power/wakeup.c drivers/base/power/wakeup_stats.c drivers/base/property.c drivers/base/swnode.c drivers/char/misc.c drivers/gpu/drm/drm_sysfs.c drivers/hid/hid-core.c drivers/hid/hid-quirks.c drivers/hid/usbhid/hid-core.c drivers/i2c/busses/i2c-i801.c drivers/i2c/i2c-core-base.c drivers/i2c/i2c-core-smbus.c drivers/i2c/i2c-core.h drivers/i2c/i2c-dev.c drivers/media/common/videobuf2/videobuf2-core.c drivers/media/common/videobuf2/videobuf2-v4l2.c drivers/media/mc/mc-request.c drivers/media/radio/si4713/radio-usb-si4713.c drivers/media/test-drivers/vicodec/codec-v4l2-fwht.c drivers/media/test-drivers/vicodec/vicodec-core.c drivers/media/v4l2-core/v4l2-ctrls-core.c drivers/media/v4l2-core/v4l2-ctrls-defs.c drivers/media/v4l2-core/v4l2-ctrls-request.c drivers/media/v4l2-core/v4l2-dev.c drivers/media/v4l2-core/v4l2-fh.c drivers/media/v4l2-core/v4l2-mem2mem.c drivers/of/base.c drivers/of/device.c drivers/pci/access.c drivers/pci/ats.c drivers/pci/host-bridge.c drivers/pci/iov.c drivers/pci/msi/api.c drivers/pci/msi/msi.c drivers/pci/pci-acpi.c drivers/pci/pci-driver.c drivers/pci/pci.c drivers/pci/pcie/aer.c drivers/pci/pcie/aspm.c drivers/pci/quirks.c drivers/pci/rebar.c drivers/pci/vc.c drivers/thunderbolt/acpi.c drivers/usb/common/common.c drivers/usb/core/config.c drivers/usb/core/devio.c drivers/usb/core/driver.c drivers/usb/core/endpoint.c drivers/usb/core/generic.c drivers/usb/core/hcd.c drivers/usb/core/hub.c drivers/usb/core/hub.h drivers/usb/core/message.c drivers/usb/core/notify.c drivers/usb/core/of.c drivers/usb/core/quirks.c drivers/usb/core/sysfs.c drivers/usb/core/trace.h drivers/usb/core/urb.c drivers/usb/core/usb-acpi.c drivers/usb/core/usb.c drivers/usb/core/usb.h drivers/usb/gadget/legacy/raw_gadget.c drivers/usb/gadget/udc/core.c drivers/usb/gadget/udc/dummy_hcd.c drivers/usb/gadget/udc/trace.h drivers/usb/misc/usbtest.c drivers/usb/mon/mon_main.c fs/char_dev.c fs/d_path.c fs/dcache.c fs/eventpoll.c fs/fcntl.c fs/file.c fs/file_table.c fs/inode.c fs/internal.h fs/ioctl.c fs/kernfs/dir.c fs/kernfs/file.c fs/kernfs/kernfs-internal.h fs/kernfs/symlink.c fs/libfs.c fs/locks.c fs/mnt_idmapping.c fs/namei.c fs/namespace.c fs/notify/dnotify/dnotify.c fs/notify/fsnotify.c fs/open.c fs/sysfs/dir.c fs/sysfs/file.c fs/sysfs/group.c fs/sysfs/symlink.c include/acpi/acpi_bus.h include/asm-generic/bitops/instrumented-non-atomic.h include/asm-generic/pgalloc.h include/asm-generic/sections.h include/linux/acpi.h include/linux/async.h include/linux/atomic/atomic-arch-fallback.h include/linux/atomic/atomic-instrumented.h include/linux/atomic/atomic-long.h include/linux/audit.h include/linux/bit_spinlock.h include/linux/cgroup.h include/linux/clockchips.h include/linux/cpumask.h include/linux/cred.h include/linux/ctype.h include/linux/dcache.h include/linux/delayed_call.h include/linux/device.h include/linux/device_cgroup.h include/linux/err.h include/linux/eventpoll.h include/linux/file.h include/linux/file_ref.h include/linux/filelock.h include/linux/filter.h include/linux/find.h include/linux/folio_batch.h include/linux/fortify-string.h include/linux/fs.h include/linux/fs/super.h include/linux/fsnotify.h include/linux/fsnotify_backend.h include/linux/hrtimer.h include/linux/idr.h include/linux/instrumented.h include/linux/jiffies.h include/linux/jump_label.h include/linux/kcov.h include/linux/kernel.h include/linux/kernfs.h include/linux/kobject.h include/linux/kref.h include/linux/kthread.h include/linux/list.h include/linux/list_bl.h include/linux/llist.h include/linux/log2.h include/linux/lsm_hook_defs.h include/linux/maple_tree.h include/linux/memcontrol.h include/linux/mempolicy.h include/linux/mm.h include/linux/mmzone.h include/linux/mount.h include/linux/netfilter/nf_conntrack_common.h include/linux/nodemask.h include/linux/of.h include/linux/page-flags.h include/linux/page_ext.h include/linux/page_ref.h include/linux/pagemap.h include/linux/perf_event.h include/linux/pgtable.h include/linux/pid.h include/linux/pm_qos.h include/linux/pm_runtime.h include/linux/preempt.h include/linux/rbtree.h include/linux/rbtree_latch.h include/linux/rculist_bl.h include/linux/rcupdate.h include/linux/refcount.h include/linux/rmap.h include/linux/rtmutex.h include/linux/sched.h include/linux/sched/isolation.h include/linux/seqlock.h include/linux/skbuff.h include/linux/slab.h include/linux/spinlock_rt.h include/linux/srcu.h include/linux/swap.h include/linux/thread_info.h include/linux/timer.h include/linux/uaccess.h include/linux/ucopysize.h include/linux/usb.h include/linux/usb/gadget.h include/linux/usb/hcd.h include/linux/userfaultfd_k.h include/linux/vmstat.h include/linux/wait.h include/linux/workqueue.h include/linux/xarray.h include/net/dst.h include/net/netns/generic.h include/net/sock.h include/trace/events/csd.h include/trace/events/exceptions.h include/trace/events/filemap.h include/trace/events/ipi.h include/trace/events/kmem.h include/trace/events/notifier.h include/trace/events/printk.h include/trace/events/rpm.h include/trace/events/skb.h include/trace/events/smbus.h include/trace/events/sock.h include/trace/events/timer.h include/trace/events/workqueue.h include/uapi/linux/usb/ch9.h kernel/bpf/core.c kernel/cgroup/rstat.c kernel/dma/swiotlb.c kernel/irq_work.c kernel/kthread.c kernel/notifier.c kernel/panic.c kernel/params.c kernel/pid.c kernel/printk/internal.h kernel/printk/nbcon.c kernel/printk/printk.c kernel/printk/printk_ringbuffer.c kernel/printk/printk_safe.c kernel/smp.c kernel/time/clockevents.c kernel/time/hrtimer.c kernel/time/posix-timers.c kernel/time/sleep_timeout.c kernel/time/tick-oneshot.c kernel/time/tick-sched.c kernel/time/time.c kernel/time/timekeeping.c kernel/time/timer.c kernel/workqueue.c lib/cmdline.c lib/cpumask.c lib/errseq.c lib/idr.c lib/iomap.c lib/kasprintf.c lib/klist.c lib/kobject.c lib/kobject_uevent.c lib/kstrtox.c lib/lockref.c lib/maple_tree.c lib/percpu_counter.c lib/plist.c lib/radix-tree.c lib/strncpy_from_user.c lib/timerqueue.c lib/usercopy.c lib/vsprintf.c lib/xarray.c mm/backing-dev.c mm/fail_page_alloc.c mm/filemap.c mm/internal.h mm/list_lru.c mm/maccess.c mm/memory.c mm/mempolicy.c mm/mmap_lock.c mm/page_counter.c mm/page_ext.c mm/page_owner.c mm/page_table_check.c mm/percpu.c mm/pgtable-generic.c mm/readahead.c mm/rmap.c mm/swap.c mm/swapfile.c mm/util.c mm/vmalloc.c net/core/filter.c net/core/skbuff.c net/core/sock.c net/netlink/af_netlink.c security/device_cgroup.c security/integrity/evm/evm.h security/integrity/evm/evm_main.c security/integrity/ima/ima_main.c security/landlock/cred.h security/landlock/fs.c security/landlock/ruleset.c security/security.c security/smack/smack_access.c security/smack/smack_lsm.c security/tomoyo/audit.c security/tomoyo/common.c security/tomoyo/common.h security/tomoyo/domain.c security/tomoyo/file.c security/tomoyo/realpath.c security/tomoyo/tomoyo.c security/tomoyo/util.c usercopy_64.c]]

314/2 2026/07/30 13:13 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 134256
							output: 86
							thoughts: 107
						

Thoughts:
Here's my thought process, as if I were reviewing this:

**Initial Assessment of Driver Availability**

Okay, still no sign of the `si4713` or `au0828` modules... which is expected, but I need to make sure. Wait a minute! Hang on... the coverage report *does* include `drivers/media/radio/si4713/radio-usb-si4713.c`! Excellent! That's a key piece of good news. I need to make sure I am reading this right. Alright, this is what I thought, `drivers/media/radio/si4713/radio-usb-si4713.c` *is* actually present in the coverage data. Now I need to drill down and review the coverage for that specific file. Let's see how well it's been tested. That's the next step.



315/2 2026/07/30 13:13 tool get-file-coverage
0m Args:
map[ExecutionCachedID:repro/ba2e75bc88e306a9def048b4fee6aae4a206c25a Filename:drivers/media/radio/si4713/radio-usb-si4713.c Functions:[]]

Results:
map[CoveredFunctions:[si4713_send_startup_command si4713_start_seq usb_si4713_probe] Snippets:[Function: si4713_send_startup_command
     1: // SPDX-License-Identifier: GPL-2.0-only
     2: /*
     3:  * Copyright 2013 Cisco Systems, Inc. and/or its affiliates.
     4:  * All rights reserved.
     5:  */
     6: 
     7: /* kernel includes */
     8: #include <linux/kernel.h>
     9: #include <linux/module.h>
    10: #include <linux/usb.h>
    11: #include <linux/init.h>
    12: #include <linux/slab.h>
    13: #include <linux/input.h>
    14: #include <linux/mutex.h>
    15: #include <linux/i2c.h>
    16: /* V4l includes */
    17: #include <linux/videodev2.h>
    18: #include <media/v4l2-common.h>
    19: #include <media/v4l2-device.h>
    20: #include <media/v4l2-ioctl.h>
    21: #include <media/v4l2-event.h>
    22: #include <linux/platform_data/media/si4713.h>
    23: 
    24: #include "si4713.h"
    25: 
    26: /* driver and module definitions */
    27: MODULE_AUTHOR("Dinesh Ram <dinesh.ram@cern.ch>");
    28: MODULE_DESCRIPTION("Si4713 FM Transmitter USB driver");
    29: MODULE_LICENSE("GPL v2");
    30: 
    31: /* The Device announces itself as Cygnal Integrated Products, Inc. */
    32: #define USB_SI4713_VENDOR		0x10c4
    33: #define USB_SI4713_PRODUCT		0x8244
    34: 
    35: #define BUFFER_LENGTH			64
    36: #define USB_TIMEOUT			1000
    37: #define USB_RESP_TIMEOUT		50000
    38: 
    39: /* USB Device ID List */
    40: static const struct usb_device_id usb_si4713_usb_device_table[] = {
    41: 	{USB_DEVICE_AND_INTERFACE_INFO(USB_SI4713_VENDOR, USB_SI4713_PRODUCT,
    42: 							USB_CLASS_HID, 0, 0) },
    43: 	{ }						/* Terminating entry */
    44: };
    45: 
    46: MODULE_DEVICE_TABLE(usb, usb_si4713_usb_device_table);
    47: 
    48: struct si4713_usb_device {
    49: 	struct usb_device	*usbdev;
    50: 	struct usb_interface	*intf;
    51: 	struct video_device	vdev;
    52: 	struct v4l2_device	v4l2_dev;
    53: 	struct v4l2_subdev	*v4l2_subdev;
    54: 	struct mutex		lock;
    55: 	struct i2c_adapter	i2c_adapter;
    56: 
    57: 	u8			*buffer;
    58: };
    59: 
    60: static inline struct si4713_usb_device *to_si4713_dev(struct v4l2_device *v4l2_dev)
    61: {
    62: 	return container_of(v4l2_dev, struct si4713_usb_device, v4l2_dev);
    63: }
    64: 
    65: static int vidioc_querycap(struct file *file, void *priv,
    66: 					struct v4l2_capability *v)
    67: {
    68: 	struct si4713_usb_device *radio = video_drvdata(file);
    69: 
    70: 	strscpy(v->driver, "radio-usb-si4713", sizeof(v->driver));
    71: 	strscpy(v->card, "Si4713 FM Transmitter", sizeof(v->card));
    72: 	usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
    73: 	return 0;
    74: }
    75: 
    76: static int vidioc_g_modulator(struct file *file, void *priv,
    77: 				struct v4l2_modulator *vm)
    78: {
    79: 	struct si4713_usb_device *radio = video_drvdata(file);
    80: 
    81: 	return v4l2_subdev_call(radio->v4l2_subdev, tuner, g_modulator, vm);
    82: }
    83: 
    84: static int vidioc_s_modulator(struct file *file, void *priv,
    85: 				const struct v4l2_modulator *vm)
    86: {
    87: 	struct si4713_usb_device *radio = video_drvdata(file);
    88: 
    89: 	return v4l2_subdev_call(radio->v4l2_subdev, tuner, s_modulator, vm);
    90: }
    91: 
    92: static int vidioc_s_frequency(struct file *file, void *priv,
    93: 				const struct v4l2_frequency *vf)
    94: {
    95: 	struct si4713_usb_device *radio = video_drvdata(file);
    96: 
    97: 	return v4l2_subdev_call(radio->v4l2_subdev, tuner, s_frequency, vf);
    98: }
    99: 
   100: static int vidioc_g_frequency(struct file *file, void *priv,
   101: 				struct v4l2_frequency *vf)
   102: {
   103: 	struct si4713_usb_device *radio = video_drvdata(file);
   104: 
   105: 	return v4l2_subdev_call(radio->v4l2_subdev, tuner, g_frequency, vf);
   106: }
   107: 
   108: static const struct v4l2_ioctl_ops usb_si4713_ioctl_ops = {
   109: 	.vidioc_querycap	  = vidioc_querycap,
   110: 	.vidioc_g_modulator	  = vidioc_g_modulator,
   111: 	.vidioc_s_modulator	  = vidioc_s_modulator,
   112: 	.vidioc_g_frequency	  = vidioc_g_frequency,
   113: 	.vidioc_s_frequency	  = vidioc_s_frequency,
   114: 	.vidioc_log_status	  = v4l2_ctrl_log_status,
   115: 	.vidioc_subscribe_event   = v4l2_ctrl_subscribe_event,
   116: 	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
   117: };
   118: 
   119: /* File system interface */
   120: static const struct v4l2_file_operations usb_si4713_fops = {
   121: 	.owner		= THIS_MODULE,
   122: 	.open           = v4l2_fh_open,
   123: 	.release        = v4l2_fh_release,
   124: 	.poll           = v4l2_ctrl_poll,
   125: 	.unlocked_ioctl	= video_ioctl2,
   126: };
   127: 
   128: static void usb_si4713_video_device_release(struct v4l2_device *v4l2_dev)
   129: {
   130: 	struct si4713_usb_device *radio = to_si4713_dev(v4l2_dev);
   131: 	struct i2c_adapter *adapter = &radio->i2c_adapter;
   132: 
   133: 	i2c_del_adapter(adapter);
   134: 	v4l2_device_unregister(&radio->v4l2_dev);
   135: 	kfree(radio->buffer);
   136: 	kfree(radio);
   137: }
   138: 
   139: /*
   140:  * This command sequence emulates the behaviour of the Windows driver.
   141:  * The structure of these commands was determined by sniffing the
   142:  * usb traffic of the device during startup.
   143:  * Most likely, these commands make some queries to the device.
   144:  * Commands are sent to enquire parameters like the bus mode,
   145:  * component revision, boot mode, the device serial number etc.
   146:  *
   147:  * These commands are necessary to be sent in this order during startup.
   148:  * The device fails to powerup if these commands are not sent.
   149:  *
   150:  * The complete list of startup commands is given in the start_seq table below.
   151:  */
   152: static int si4713_send_startup_command(struct si4713_usb_device *radio)
   153: {
   154: 	unsigned long until_jiffies = jiffies + usecs_to_jiffies(USB_RESP_TIMEOUT) + 1;
   155: 	u8 *buffer = radio->buffer;
   156: 	int retval;
   157: 
   158: 	/* send the command */
   159: 	retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
   160: 					0x09, 0x21, 0x033f, 0, radio->buffer,
   161: 					BUFFER_LENGTH, USB_TIMEOUT);
*  162: 	if (retval < 0)
   163: 		return retval;
   164: 
   165: 	for (;;) {
   166: 		/* receive the response */
   167: 		retval = usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
   168: 				0x01, 0xa1, 0x033f, 0, radio->buffer,
   169: 				BUFFER_LENGTH, USB_TIMEOUT);
   170: 		if (retval < 0)
   171: 			return retval;
   172: 		if (!radio->buffer[1]) {
 Function: si4713_start_seq
   237: 	{ 6, { 0x06, 0x03, 0x03, 0x08, 0x01, 0x0f } },
   238: };
   239: 
   240: static int si4713_start_seq(struct si4713_usb_device *radio)
   241: {
   242: 	int retval = 0;
   243: 	int i;
   244: 
   245: 	radio->buffer[0] = 0x3f;
   246: 
*  247: 	for (i = 0; i < ARRAY_SIZE(start_seq); i++) {
   248: 		int len = start_seq[i].len;
   249: 		const u8 *payload = start_seq[i].payload;
   250: 
   251: 		memcpy(radio->buffer + 1, payload, len);
   252: 		memset(radio->buffer + len + 1, 0, BUFFER_LENGTH - 1 - len);
*  253: 		retval = si4713_send_startup_command(radio);
   254: 	}
   255: 
   256: 	return retval;
   257: }
   258: 
   259: static struct i2c_board_info si4713_board_info = {
   260: 	I2C_BOARD_INFO("si4713", SI4713_I2C_ADDR_BUSEN_HIGH),
   261: };
   262: 
   263: struct si4713_command_table {
 Function: usb_si4713_probe
   403: 	/* set up sysfs linkage to our parent device */
   404: 	radio->i2c_adapter.dev.parent = &radio->usbdev->dev;
   405: 	i2c_set_adapdata(&radio->i2c_adapter, radio);
   406: 
   407: 	return i2c_add_adapter(&radio->i2c_adapter);
   408: }
   409: 
   410: /* check if the device is present and register with v4l and usb if it is */
   411: static int usb_si4713_probe(struct usb_interface *intf,
   412: 				const struct usb_device_id *id)
*  413: {
   414: 	struct si4713_usb_device *radio;
   415: 	struct i2c_adapter *adapter;
   416: 	struct v4l2_subdev *sd;
   417: 	int retval;
   418: 
   419: 	dev_info(&intf->dev, "Si4713 development board discovered: (%04X:%04X)\n",
   420: 			id->idVendor, id->idProduct);
   421: 
   422: 	/* Initialize local device structure */
   423: 	radio = kzalloc_obj(struct si4713_usb_device);
   424: 	if (radio)
   425: 		radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
   426: 
   427: 	if (!radio || !radio->buffer) {
   428: 		dev_err(&intf->dev, "kmalloc for si4713_usb_device failed\n");
   429: 		kfree(radio);
   430: 		return -ENOMEM;
   431: 	}
   432: 
   433: 	mutex_init(&radio->lock);
   434: 
   435: 	radio->usbdev = interface_to_usbdev(intf);
   436: 	radio->intf = intf;
   437: 	usb_set_intfdata(intf, &radio->v4l2_dev);
   438: 
*  439: 	retval = si4713_start_seq(radio);
*  440: 	if (retval < 0)
   441: 		goto err_v4l2;
   442: 
   443: 	retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
   444: 	if (retval < 0) {
   445: 		dev_err(&intf->dev, "couldn't register v4l2_device\n");
   446: 		goto err_v4l2;
   447: 	}
   448: 
   449: 	retval = si4713_register_i2c_adapter(radio);
   450: 	if (retval < 0) {
]]

316/2 2026/07/30 13:13 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 138941
							output: 99
							thoughts: 719
						

Thoughts:
**Debugging the SI4713 USB Probe**

Okay, so `usb_si4713_probe` is triggered, which means we're in the right place. Then, `si4713_start_seq` and `si4713_send_startup_command` are called, as expected. But then, `usb_control_msg` returns a negative value. Why? The original hunch was that `syz_usb_connect` doesn't handle vendor-specific control messages.

Let's break down `si4713_send_startup_command`. It's sending a `usb_control_msg` with `bRequest = 0x09` (SET_REPORT) and `bRequestType = 0x21` (OUT, CLASS, INTERFACE). Initially, I thought that `syz_usb_control_io` couldn't handle this as I was providing a GET_REPORT request, but then I realized that `syz_usb_control_io` *can* respond to this! It's just that I was only looking at the IN requests, not the OUT requests. In fact, syzkaller *accepts* OUT requests automatically!

So, the mystery is *why* did `usb_control_msg` return a negative value? It should have just succeeded. Rechecking the coverage output, it looks like line 162 is covered, but line 163 (the `return` statement after the error check) is *not*. This means `retval` is not less than 0. The first call to `usb_control_msg` *succeeded*!

This points to the loop that comes next:
```
   165: 	for (;;) {
   166: 		/* receive the response */
   167: 		retval = usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
   168: 				0x01, 0xa1, 0x033f, 0, radio->buffer,
   169: 				BUFFER_LENGTH, USB_TIMEOUT);
   170: 		if (retval < 0)
   171: 			return retval;
```
That entire block (lines 165-172) is NOT in the coverage report. This is where the issue must lie. I need full coverage for `si4713_send_startup_command` to see what is going on with the second `usb_control_msg` call.



317/2 2026/07/30 13:13 tool get-file-coverage
0m Args:
map[ExecutionCachedID:repro/ba2e75bc88e306a9def048b4fee6aae4a206c25a Filename:drivers/media/radio/si4713/radio-usb-si4713.c Functions:[si4713_send_startup_command]]

Results:
map[CoveredFunctions:[si4713_send_startup_command si4713_start_seq usb_si4713_probe] Snippets:[Function: si4713_send_startup_command
     1: // SPDX-License-Identifier: GPL-2.0-only
     2: /*
     3:  * Copyright 2013 Cisco Systems, Inc. and/or its affiliates.
     4:  * All rights reserved.
     5:  */
     6: 
     7: /* kernel includes */
     8: #include <linux/kernel.h>
     9: #include <linux/module.h>
    10: #include <linux/usb.h>
    11: #include <linux/init.h>
    12: #include <linux/slab.h>
    13: #include <linux/input.h>
    14: #include <linux/mutex.h>
    15: #include <linux/i2c.h>
    16: /* V4l includes */
    17: #include <linux/videodev2.h>
    18: #include <media/v4l2-common.h>
    19: #include <media/v4l2-device.h>
    20: #include <media/v4l2-ioctl.h>
    21: #include <media/v4l2-event.h>
    22: #include <linux/platform_data/media/si4713.h>
    23: 
    24: #include "si4713.h"
    25: 
    26: /* driver and module definitions */
    27: MODULE_AUTHOR("Dinesh Ram <dinesh.ram@cern.ch>");
    28: MODULE_DESCRIPTION("Si4713 FM Transmitter USB driver");
    29: MODULE_LICENSE("GPL v2");
    30: 
    31: /* The Device announces itself as Cygnal Integrated Products, Inc. */
    32: #define USB_SI4713_VENDOR		0x10c4
    33: #define USB_SI4713_PRODUCT		0x8244
    34: 
    35: #define BUFFER_LENGTH			64
    36: #define USB_TIMEOUT			1000
    37: #define USB_RESP_TIMEOUT		50000
    38: 
    39: /* USB Device ID List */
    40: static const struct usb_device_id usb_si4713_usb_device_table[] = {
    41: 	{USB_DEVICE_AND_INTERFACE_INFO(USB_SI4713_VENDOR, USB_SI4713_PRODUCT,
    42: 							USB_CLASS_HID, 0, 0) },
    43: 	{ }						/* Terminating entry */
    44: };
    45: 
    46: MODULE_DEVICE_TABLE(usb, usb_si4713_usb_device_table);
    47: 
    48: struct si4713_usb_device {
    49: 	struct usb_device	*usbdev;
    50: 	struct usb_interface	*intf;
    51: 	struct video_device	vdev;
    52: 	struct v4l2_device	v4l2_dev;
    53: 	struct v4l2_subdev	*v4l2_subdev;
    54: 	struct mutex		lock;
    55: 	struct i2c_adapter	i2c_adapter;
    56: 
    57: 	u8			*buffer;
    58: };
    59: 
    60: static inline struct si4713_usb_device *to_si4713_dev(struct v4l2_device *v4l2_dev)
    61: {
    62: 	return container_of(v4l2_dev, struct si4713_usb_device, v4l2_dev);
    63: }
    64: 
    65: static int vidioc_querycap(struct file *file, void *priv,
    66: 					struct v4l2_capability *v)
    67: {
    68: 	struct si4713_usb_device *radio = video_drvdata(file);
    69: 
    70: 	strscpy(v->driver, "radio-usb-si4713", sizeof(v->driver));
    71: 	strscpy(v->card, "Si4713 FM Transmitter", sizeof(v->card));
    72: 	usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
    73: 	return 0;
    74: }
    75: 
    76: static int vidioc_g_modulator(struct file *file, void *priv,
    77: 				struct v4l2_modulator *vm)
    78: {
    79: 	struct si4713_usb_device *radio = video_drvdata(file);
    80: 
    81: 	return v4l2_subdev_call(radio->v4l2_subdev, tuner, g_modulator, vm);
    82: }
    83: 
    84: static int vidioc_s_modulator(struct file *file, void *priv,
    85: 				const struct v4l2_modulator *vm)
    86: {
    87: 	struct si4713_usb_device *radio = video_drvdata(file);
    88: 
    89: 	return v4l2_subdev_call(radio->v4l2_subdev, tuner, s_modulator, vm);
    90: }
    91: 
    92: static int vidioc_s_frequency(struct file *file, void *priv,
    93: 				const struct v4l2_frequency *vf)
    94: {
    95: 	struct si4713_usb_device *radio = video_drvdata(file);
    96: 
    97: 	return v4l2_subdev_call(radio->v4l2_subdev, tuner, s_frequency, vf);
    98: }
    99: 
   100: static int vidioc_g_frequency(struct file *file, void *priv,
   101: 				struct v4l2_frequency *vf)
   102: {
   103: 	struct si4713_usb_device *radio = video_drvdata(file);
   104: 
   105: 	return v4l2_subdev_call(radio->v4l2_subdev, tuner, g_frequency, vf);
   106: }
   107: 
   108: static const struct v4l2_ioctl_ops usb_si4713_ioctl_ops = {
   109: 	.vidioc_querycap	  = vidioc_querycap,
   110: 	.vidioc_g_modulator	  = vidioc_g_modulator,
   111: 	.vidioc_s_modulator	  = vidioc_s_modulator,
   112: 	.vidioc_g_frequency	  = vidioc_g_frequency,
   113: 	.vidioc_s_frequency	  = vidioc_s_frequency,
   114: 	.vidioc_log_status	  = v4l2_ctrl_log_status,
   115: 	.vidioc_subscribe_event   = v4l2_ctrl_subscribe_event,
   116: 	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
   117: };
   118: 
   119: /* File system interface */
   120: static const struct v4l2_file_operations usb_si4713_fops = {
   121: 	.owner		= THIS_MODULE,
   122: 	.open           = v4l2_fh_open,
   123: 	.release        = v4l2_fh_release,
   124: 	.poll           = v4l2_ctrl_poll,
   125: 	.unlocked_ioctl	= video_ioctl2,
   126: };
   127: 
   128: static void usb_si4713_video_device_release(struct v4l2_device *v4l2_dev)
   129: {
   130: 	struct si4713_usb_device *radio = to_si4713_dev(v4l2_dev);
   131: 	struct i2c_adapter *adapter = &radio->i2c_adapter;
   132: 
   133: 	i2c_del_adapter(adapter);
   134: 	v4l2_device_unregister(&radio->v4l2_dev);
   135: 	kfree(radio->buffer);
   136: 	kfree(radio);
   137: }
   138: 
   139: /*
   140:  * This command sequence emulates the behaviour of the Windows driver.
   141:  * The structure of these commands was determined by sniffing the
   142:  * usb traffic of the device during startup.
   143:  * Most likely, these commands make some queries to the device.
   144:  * Commands are sent to enquire parameters like the bus mode,
   145:  * component revision, boot mode, the device serial number etc.
   146:  *
   147:  * These commands are necessary to be sent in this order during startup.
   148:  * The device fails to powerup if these commands are not sent.
   149:  *
   150:  * The complete list of startup commands is given in the start_seq table below.
   151:  */
   152: static int si4713_send_startup_command(struct si4713_usb_device *radio)
   153: {
   154: 	unsigned long until_jiffies = jiffies + usecs_to_jiffies(USB_RESP_TIMEOUT) + 1;
   155: 	u8 *buffer = radio->buffer;
   156: 	int retval;
   157: 
   158: 	/* send the command */
   159: 	retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
   160: 					0x09, 0x21, 0x033f, 0, radio->buffer,
   161: 					BUFFER_LENGTH, USB_TIMEOUT);
*  162: 	if (retval < 0)
   163: 		return retval;
   164: 
   165: 	for (;;) {
   166: 		/* receive the response */
   167: 		retval = usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
   168: 				0x01, 0xa1, 0x033f, 0, radio->buffer,
   169: 				BUFFER_LENGTH, USB_TIMEOUT);
   170: 		if (retval < 0)
   171: 			return retval;
   172: 		if (!radio->buffer[1]) {
]]

318/2 2026/07/30 13:13 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 143317
							output: 32
							thoughts: 2285
						

Thoughts:
**Analyzing a USB Driver UAF Bug**

Okay, so I'm diving into this issue. First, I noticed some lines in the code that weren't being hit during execution - lines 163 and 165, specifically. Then I started tracing through the flow, thinking the `usb_control_msg` might be the problem, perhaps blocking or crashing. But it must have returned, and now that I think about it, the issue doesn't appear to be related to the `usb_control_msg` returning or crashing, because the code seems to check the return value correctly. I checked the coverage of `si4713_start_seq` and realized it was returning an error without breaking.

After checking the code for error handling, I realized that if the `si4713_send_startup_command` function returns an error, the error code would be returned by `si4713_start_seq`. This happens if `usb_control_msg` returns an error, such as a timeout or STALL signal which can be mapped to `-EPIPE`. This means `usb_si4713_probe` will fail, and the I2C adapter will not be registered, and as a result, this driver isn't the cause of the bug.

I then went back to the bug report to analyze the stack trace and allocation information and noticed the key traces. I focused on the allocation stack and the reported allocation size (4096 bytes, within `kmalloc-4k`). I initially thought the UAF was on an environment variable buffer allocated by `kobject_uevent_env` but then realized that the reported UAF occurs through a `struct device` pointer, specifically accessing its `type` member, so the bug isn't in that buffer. I checked the size of `struct kobj_uevent_env`, which is around 2048 bytes, and I then considered that the bug is on `struct usb_device`, which is allocated in the `kmalloc-4k` pool. 

If this were the case, the memory of the `struct usb_device` would be freed, and then, later, re-allocated. The allocation stack is the last one that happened to land on this block of memory.

I need to understand what else in that driver could be causing this. Time to dig further.



319/2 2026/07/30 13:14 tool grepper
0m Args:
map[Expression:i2c_add_adapter PathPrefix:drivers/media/usb]

Results:
map[Output:drivers/media/usb/au0828/au0828-i2c.c=354=int au0828_i2c_register(struct au0828_dev *dev)
--
drivers/media/usb/au0828/au0828-i2c.c-373-#endif
drivers/media/usb/au0828/au0828-i2c.c:374:	i2c_add_adapter(&dev->i2c_adap);
drivers/media/usb/au0828/au0828-i2c.c-375-
--
drivers/media/usb/cx231xx/cx231xx-i2c.c=514=int cx231xx_i2c_register(struct cx231xx_i2c *bus)
--
drivers/media/usb/cx231xx/cx231xx-i2c.c-527-	i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
drivers/media/usb/cx231xx/cx231xx-i2c.c:528:	bus->i2c_rc = i2c_add_adapter(&bus->i2c_adap);
drivers/media/usb/cx231xx/cx231xx-i2c.c-529-
--
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c=56=static int dvb_usbv2_i2c_init(struct dvb_usb_device *d)
--
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c-68-
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c:69:	ret = i2c_add_adapter(&d->i2c_adap);
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c-70-	if (ret < 0) {
--
drivers/media/usb/dvb-usb/dvb-usb-i2c.c=11=int dvb_usb_i2c_init(struct dvb_usb_device *d)
--
drivers/media/usb/dvb-usb/dvb-usb-i2c.c-30-
drivers/media/usb/dvb-usb/dvb-usb-i2c.c:31:	ret = i2c_add_adapter(&d->i2c_adap);
drivers/media/usb/dvb-usb/dvb-usb-i2c.c-32-	if (ret < 0) {
--
drivers/media/usb/em28xx/em28xx-i2c.c=970=int em28xx_i2c_register(struct em28xx *dev, unsigned int bus,
--
drivers/media/usb/em28xx/em28xx-i2c.c-991-
drivers/media/usb/em28xx/em28xx-i2c.c:992:	retval = i2c_add_adapter(&dev->i2c_adap[bus]);
drivers/media/usb/em28xx/em28xx-i2c.c-993-	if (retval < 0) {
drivers/media/usb/em28xx/em28xx-i2c.c-994-		dev_err(&dev->intf->dev,
drivers/media/usb/em28xx/em28xx-i2c.c:995:			"%s: i2c_add_adapter failed! retval [%d]\n",
drivers/media/usb/em28xx/em28xx-i2c.c-996-			__func__, retval);
--
drivers/media/usb/go7007/go7007-i2c.c=204=int go7007_i2c_init(struct go7007 *go)
--
drivers/media/usb/go7007/go7007-i2c.c-209-	i2c_set_adapdata(&go->i2c_adapter, go);
drivers/media/usb/go7007/go7007-i2c.c:210:	if (i2c_add_adapter(&go->i2c_adapter) < 0) {
drivers/media/usb/go7007/go7007-i2c.c-211-		dev_err(go->dev,
drivers/media/usb/go7007/go7007-i2c.c:212:			"go7007-i2c: error: i2c_add_adapter failed\n");
drivers/media/usb/go7007/go7007-i2c.c-213-		return -1;
--
drivers/media/usb/go7007/go7007-usb.c=1040=static int go7007_usb_probe(struct usb_interface *intf,
--
drivers/media/usb/go7007/go7007-usb.c-1171-		i2c_set_adapdata(&go->i2c_adapter, go);
drivers/media/usb/go7007/go7007-usb.c:1172:		if (i2c_add_adapter(&go->i2c_adapter) < 0) {
drivers/media/usb/go7007/go7007-usb.c:1173:			dev_err(go->dev, "error: i2c_add_adapter failed\n");
drivers/media/usb/go7007/go7007-usb.c-1174-			goto allocfail;
--
drivers/media/usb/hdpvr/hdpvr-i2c.c=180=int hdpvr_register_i2c_adapter(struct hdpvr_device *dev)
--
drivers/media/usb/hdpvr/hdpvr-i2c.c-188-
drivers/media/usb/hdpvr/hdpvr-i2c.c:189:	return i2c_add_adapter(&dev->i2c_adapter);
drivers/media/usb/hdpvr/hdpvr-i2c.c-190-}
--
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c=591=void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
--
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c-627-	i2c_set_adapdata(&hdw->i2c_adap, &hdw->v4l2_dev);
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c:628:	i2c_add_adapter(&hdw->i2c_adap);
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c-629-	if (hdw->i2c_func[0x18] == i2c_24xxx_ir) {
--
drivers/media/usb/stk1160/stk1160-i2c.c=247=int stk1160_i2c_register(struct stk1160 *dev)
--
drivers/media/usb/stk1160/stk1160-i2c.c-257-
drivers/media/usb/stk1160/stk1160-i2c.c:258:	rc = i2c_add_adapter(&dev->i2c_adap);
drivers/media/usb/stk1160/stk1160-i2c.c-259-	if (rc < 0) {
--
drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c=1597=static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
--
drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c-1655-
drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c:1656:	result = i2c_add_adapter(&ttusb->i2c_adap);
drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c-1657-	if (result)
]

320/2 2026/07/30 13:14 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 148342
							output: 50
							thoughts: 29
						

Thoughts:
Okay, here's my interpretation of those thoughts, tailored for an expert audience, presented in the first person:

**Initial Assessment: A Familiar Face and a Code Dive**

Ah, *`go7007`*! I recognize that one. Another potential area to explore, always good to keep up with these sorts of things. Let's start with a deep dive into the code. My instinct is telling me to start at `go7007-usb.c` and work from there. Seems like the logical place to begin peeling back the layers.



321/2 2026/07/30 13:14 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:1160 LineCount:50]

Results:
map[Contents:1160:		/* Boot the GO7007 */
1161:		if (go7007_boot_encoder(go, go->board_info->flags &
1162:						GO7007_BOARD_USE_ONBOARD_I2C) < 0)
1163:			goto allocfail;
1164:	
1165:		/* Register the EZ-USB I2C adapter, if we're using it */
1166:		if (board->flags & GO7007_USB_EZUSB_I2C) {
1167:			memcpy(&go->i2c_adapter, &go7007_usb_adap_templ,
1168:					sizeof(go7007_usb_adap_templ));
1169:			mutex_init(&usb->i2c_lock);
1170:			go->i2c_adapter.dev.parent = go->dev;
1171:			i2c_set_adapdata(&go->i2c_adapter, go);
1172:			if (i2c_add_adapter(&go->i2c_adapter) < 0) {
1173:				dev_err(go->dev, "error: i2c_add_adapter failed\n");
1174:				goto allocfail;
1175:			}
1176:			go->i2c_adapter_online = 1;
1177:		}
1178:	
1179:		/* Pelco and Adlink reused the XMen and XMen-III vendor and product
1180:		 * IDs for their own incompatible designs.  We can detect XMen boards
1181:		 * by probing the sensor, but there is no way to probe the sensors on
1182:		 * the Pelco and Adlink designs so we default to the Adlink.  If it
1183:		 * is actually a Pelco, the user must set the assume_endura module
1184:		 * parameter. */
1185:		if ((go->board_id == GO7007_BOARDID_XMEN ||
1186:					go->board_id == GO7007_BOARDID_XMEN_III) &&
1187:				go->i2c_adapter_online) {
1188:			union i2c_smbus_data data;
1189:	
1190:			/* Check to see if register 0x0A is 0x76 */
1191:			i2c_smbus_xfer(&go->i2c_adapter, 0x21, I2C_CLIENT_SCCB,
1192:				I2C_SMBUS_READ, 0x0A, I2C_SMBUS_BYTE_DATA, &data);
1193:			if (data.byte != 0x76) {
1194:				if (assume_endura) {
1195:					go->board_id = GO7007_BOARDID_ENDURA;
1196:					usb->board = board = &board_endura;
1197:					go->board_info = &board->main_info;
1198:					strscpy(go->name, "Pelco Endura",
1199:						sizeof(go->name));
1200:				} else {
1201:					u16 channel;
1202:	
1203:					/* read channel number from GPIO[1:0] */
1204:					if (go7007_read_addr(go, 0x3c81, &channel))
1205:						goto allocfail;
1206:	
1207:					channel &= 0x3;
1208:					go->board_id = GO7007_BOARDID_ADLINK_MPG24;
1209:					usb->board = board = &board_adlink_mpg24;
]

322/2 2026/07/30 13:14 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 149559
							output: 50
							thoughts: 101
						

Thoughts:
Here's my understanding of the situation, tailored for my expert perspective:

**Debugging the I2C Communication in `go7007`**

Okay, so `go7007` is registering the I2C adapter, which is good. That's the expected initialization step. It's then calling `i2c_smbus_xfer`, which is where the rubber meets the road. This is the function that actually attempts to transfer data over the I2C bus, likely reading a value, given the context.

My immediate concern is what happens if that `i2c_smbus_xfer` call *fails*. Looking at the code, it seems like failure might lead to the `allocfail` label. A failure here is crucial, as any disruption in I2C communication is likely a sign of a larger, systemic problem in the adapter's functionality or the bus itself.

Specifically, I'm watching the read to address `0x3c81`, which, if it fails, jumps to `allocfail`. I need to figure out why this read is failing. Is it an issue with the I2C address, the device itself, the bus arbitration, or a driver bug? My debugging process is going to start right there.



323/2 2026/07/30 13:14 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:1210 LineCount:50]

Results:
map[Contents:1210:					go->board_info = &board->main_info;
1211:					go->channel_number = channel;
1212:					snprintf(go->name, sizeof(go->name),
1213:						"Adlink PCI-MPG24, channel #%d",
1214:						channel);
1215:				}
1216:				go7007_update_board(go);
1217:			}
1218:		}
1219:	
1220:		num_i2c_devs = go->board_info->num_i2c_devs;
1221:	
1222:		/* Probe the tuner model on the TV402U */
1223:		if (go->board_id == GO7007_BOARDID_PX_TV402U) {
1224:			/* Board strapping indicates tuner model */
1225:			if (go7007_usb_vendor_request(go, 0x41, 0, 0, go->usb_buf, 3,
1226:						1) < 0) {
1227:				dev_err(go->dev, "GPIO read failed!\n");
1228:				goto allocfail;
1229:			}
1230:			switch (go->usb_buf[0] >> 6) {
1231:			case 1:
1232:				go->tuner_type = TUNER_SONY_BTF_PG472Z;
1233:				go->std = V4L2_STD_PAL;
1234:				strscpy(go->name, "Plextor PX-TV402U-EU",
1235:					sizeof(go->name));
1236:				break;
1237:			case 2:
1238:				go->tuner_type = TUNER_SONY_BTF_PK467Z;
1239:				go->std = V4L2_STD_NTSC_M_JP;
1240:				num_i2c_devs -= 2;
1241:				strscpy(go->name, "Plextor PX-TV402U-JP",
1242:					sizeof(go->name));
1243:				break;
1244:			case 3:
1245:				go->tuner_type = TUNER_SONY_BTF_PB463Z;
1246:				num_i2c_devs -= 2;
1247:				strscpy(go->name, "Plextor PX-TV402U-NA",
1248:					sizeof(go->name));
1249:				break;
1250:			default:
1251:				pr_debug("unable to detect tuner type!\n");
1252:				break;
1253:			}
1254:			/* Configure tuner mode selection inputs connected
1255:			 * to the EZ-USB GPIO output pins */
1256:			if (go7007_usb_vendor_request(go, 0x40, 0x7f02, 0,
1257:						NULL, 0, 0) < 0) {
1258:				dev_err(go->dev, "GPIO write failed!\n");
1259:				goto allocfail;
]

324/2 2026/07/30 13:14 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 150879
							output: 50
							thoughts: 10
						

Thoughts:
Okay, here's my summary, framed as my internal thought process:

**Focusing In: The Allocfail Indicator**

Alright, let's get down to brass tacks. I'm hitting a snag somewhere, and I need to pinpoint the root cause. My immediate thought is, I need to see `allocfail`. Everything else is noise right now. `allocfail` is the signal I'm looking for, the indicator that everything is hinging on. Forget the periphery; the critical path hinges on the identification and understanding of that particular fault. Time to put on my Sherlock hat and follow the breadcrumbs. I know what to look for, and I won't be distracted until I find it.



325/2 2026/07/30 13:14 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:1260 LineCount:50]

Results:
map[Contents:1260:			}
1261:		}
1262:	
1263:		/* Print a nasty message if the user attempts to use a USB2.0 device in
1264:		 * a USB1.1 port.  There will be silent corruption of the stream. */
1265:		if ((board->flags & GO7007_USB_EZUSB) &&
1266:				usbdev->speed != USB_SPEED_HIGH)
1267:			dev_err(go->dev, "*** WARNING ***  This device must be connected to a USB 2.0 port! Attempting to capture video through a USB 1.1 port will result in stream corruption, even at low bitrates!\n");
1268:	
1269:		/* Allocate the URBs and buffers for receiving the video stream */
1270:		if (board->flags & GO7007_USB_EZUSB) {
1271:			if (!usb->usbdev->ep_in[6])
1272:				goto allocfail;
1273:			v_urb_len = 1024;
1274:			video_pipe = usb_rcvbulkpipe(usb->usbdev, 6);
1275:		} else {
1276:			if (!usb->usbdev->ep_in[1])
1277:				goto allocfail;
1278:			v_urb_len = 512;
1279:			video_pipe = usb_rcvbulkpipe(usb->usbdev, 1);
1280:		}
1281:		for (i = 0; i < 8; ++i) {
1282:			usb->video_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
1283:			if (usb->video_urbs[i] == NULL)
1284:				goto allocfail;
1285:			usb->video_urbs[i]->transfer_buffer =
1286:							kmalloc(v_urb_len, GFP_KERNEL);
1287:			if (usb->video_urbs[i]->transfer_buffer == NULL)
1288:				goto allocfail;
1289:			usb_fill_bulk_urb(usb->video_urbs[i], usb->usbdev, video_pipe,
1290:					usb->video_urbs[i]->transfer_buffer, v_urb_len,
1291:					go7007_usb_read_video_pipe_complete, go);
1292:		}
1293:	
1294:		/* Allocate the URBs and buffers for receiving the audio stream */
1295:		if ((board->flags & GO7007_USB_EZUSB) &&
1296:		    (board->main_info.flags & GO7007_BOARD_HAS_AUDIO)) {
1297:			if (!usb->usbdev->ep_in[8])
1298:				goto allocfail;
1299:			for (i = 0; i < 8; ++i) {
1300:				usb->audio_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
1301:				if (usb->audio_urbs[i] == NULL)
1302:					goto allocfail;
1303:				usb->audio_urbs[i]->transfer_buffer = kmalloc(4096,
1304:									GFP_KERNEL);
1305:				if (usb->audio_urbs[i]->transfer_buffer == NULL)
1306:					goto allocfail;
1307:				usb_fill_bulk_urb(usb->audio_urbs[i], usb->usbdev,
1308:					usb_rcvbulkpipe(usb->usbdev, 8),
1309:					usb->audio_urbs[i]->transfer_buffer, 4096,
]

326/2 2026/07/30 13:14 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 152086
							output: 50
							thoughts: 10
						

Thoughts:
Okay, here's my summary, framed as my internal thought process:

**Focusing In: The Allocfail Indicator**

Alright, let's get down to brass tacks. I'm hitting a snag somewhere, and I need to pinpoint the root cause. My immediate thought is, I need to see `allocfail`. Everything else is noise right now. `allocfail` is the signal I'm looking for, the indicator that everything is hinging on. Forget the periphery; the critical path hinges on the identification and understanding of that particular fault. Time to put on my Sherlock hat and follow the breadcrumbs. I know what to look for, and I won't be distracted until I find it.



327/2 2026/07/30 13:14 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:1310 LineCount:50]

Results:
map[Contents:1310:					go7007_usb_read_audio_pipe_complete, go);
1311:			}
1312:		}
1313:	
1314:		/* Do any final GO7007 initialization, then register the
1315:		 * V4L2 and ALSA interfaces */
1316:		if (go7007_register_encoder(go, num_i2c_devs) < 0)
1317:			goto allocfail;
1318:	
1319:		go->status = STATUS_ONLINE;
1320:		return 0;
1321:	
1322:	allocfail:
1323:		go7007_usb_release(go);
1324:		kfree(go);
1325:		return -ENOMEM;
1326:	}
1327:	
1328:	static void go7007_usb_disconnect(struct usb_interface *intf)
1329:	{
1330:		struct go7007 *go = to_go7007(usb_get_intfdata(intf));
1331:	
1332:		mutex_lock(&go->queue_lock);
1333:		mutex_lock(&go->serialize_lock);
1334:	
1335:		if (go->audio_enabled)
1336:			go7007_snd_remove(go);
1337:	
1338:		go->status = STATUS_SHUTDOWN;
1339:		v4l2_device_disconnect(&go->v4l2_dev);
1340:		video_unregister_device(&go->vdev);
1341:		mutex_unlock(&go->serialize_lock);
1342:		mutex_unlock(&go->queue_lock);
1343:	
1344:		v4l2_device_put(&go->v4l2_dev);
1345:	}
1346:	
1347:	static struct usb_driver go7007_usb_driver = {
1348:		.name		= "go7007",
1349:		.probe		= go7007_usb_probe,
1350:		.disconnect	= go7007_usb_disconnect,
1351:		.id_table	= go7007_usb_id_table,
1352:	};
1353:	
1354:	module_usb_driver(go7007_usb_driver);
1355:	MODULE_DESCRIPTION("WIS GO7007 USB support");
1356:	MODULE_LICENSE("GPL v2");
]

328/2 2026/07/30 13:14 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 153029
							output: 49
							thoughts: 37
						

Thoughts:
Here's my thought process, as if I were analyzing this code:

**Analyzing the Allocation Failure and USB Release**

Okay, so I see an `allocfail` call, which is a big red flag – allocation failure is never a good thing. Now, it seems this is tied directly to `go7007_usb_release(go)`. That function is the critical piece here; I need to understand what it's doing. I need to dive into `go7007_usb_release` immediately. Knowing how this release function interacts with the hardware, the resources, and any potential locks is paramount to understanding where the failure occurs. Any unreleased resources may be causing the problem so it's critical to ascertain what `go7007_usb_release` is actually doing. The allocation failure could be symptomatic of an underlying issue, such as memory corruption or resource exhaustion. I need to figure out the chain of events that leads to this `allocfail` and specifically how `go7007_usb_release` fits into that sequence.



329/2 2026/07/30 13:15 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:980 LineCount:50]

Results:
map[Contents: 980:			} else if (msgs[i].flags & I2C_M_RD) {
 981:	#ifdef GO7007_I2C_DEBUG
 982:				pr_debug("i2c read %d bytes on %02x\n",
 983:						msgs[i].len, msgs[i].addr);
 984:	#endif
 985:				buf[0] = 0x01;
 986:				buf[1] = 1;
 987:				buf[2] = msgs[i].addr << 1;
 988:				buf[3] = msgs[i].len;
 989:				buf_len = 4;
 990:			} else {
 991:	#ifdef GO7007_I2C_DEBUG
 992:				pr_debug("i2c write %d bytes on %02x\n",
 993:						msgs[i].len, msgs[i].addr);
 994:	#endif
 995:				buf[0] = 0x00;
 996:				buf[1] = msgs[i].len + 1;
 997:				buf[2] = msgs[i].addr << 1;
 998:				memcpy(&buf[3], msgs[i].buf, msgs[i].len);
 999:				buf_len = msgs[i].len + 3;
1000:				buf[buf_len++] = 0;
1001:			}
1002:			if (go7007_usb_vendor_request(go, 0x24, 0, 0,
1003:							buf, buf_len, 0) < 0)
1004:				goto i2c_done;
1005:			if (msgs[i].flags & I2C_M_RD) {
1006:				memset(buf, 0, msgs[i].len + 1);
1007:				if (go7007_usb_vendor_request(go, 0x25, 0, 0, buf,
1008:							msgs[i].len + 1, 1) < 0)
1009:					goto i2c_done;
1010:				memcpy(msgs[i].buf, buf + 1, msgs[i].len);
1011:			}
1012:		}
1013:		ret = num;
1014:	
1015:	i2c_done:
1016:		mutex_unlock(&usb->i2c_lock);
1017:		return ret;
1018:	}
1019:	
1020:	static u32 go7007_usb_functionality(struct i2c_adapter *adapter)
1021:	{
1022:		/* No errors are reported by the hardware, so we don't bother
1023:		 * supporting quick writes to avoid confusing probing */
1024:		return (I2C_FUNC_SMBUS_EMUL) & ~I2C_FUNC_SMBUS_QUICK;
1025:	}
1026:	
1027:	static const struct i2c_algorithm go7007_usb_algo = {
1028:		.master_xfer	= go7007_usb_i2c_master_xfer,
1029:		.functionality	= go7007_usb_functionality,
]

330/2 2026/07/30 13:15 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 154279
							output: 50
							thoughts: 22
						

Thoughts:
Here's my attempt at summarizing the thought process, tailored for an expert audience and written in the first person:

**Navigating the USB Release Function**

Okay, so I'm looking at this code and trying to trace the USB release process, and my initial thought is, "Wait a minute, `go7007_usb_release`... that's at line 1030?" I need to verify that location, but its placement raises a flag. It's further down than I expected given my mental model of the module's architecture. It feels like this release function might be buried deeper in the initialization. I'll need to remember this for context when I trace the calls and ensure this is where it is defined.



331/2 2026/07/30 13:15 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:1030 LineCount:50]

Results:
map[Contents:1030:	};
1031:	
1032:	static struct i2c_adapter go7007_usb_adap_templ = {
1033:		.owner			= THIS_MODULE,
1034:		.name			= "WIS GO7007SB EZ-USB",
1035:		.algo			= &go7007_usb_algo,
1036:	};
1037:	
1038:	/********************* USB add/remove functions *********************/
1039:	
1040:	static int go7007_usb_probe(struct usb_interface *intf,
1041:			const struct usb_device_id *id)
1042:	{
1043:		struct go7007 *go;
1044:		struct go7007_usb *usb;
1045:		const struct go7007_usb_board *board;
1046:		struct usb_device *usbdev = interface_to_usbdev(intf);
1047:		struct usb_host_endpoint *ep;
1048:		unsigned num_i2c_devs;
1049:		char *name;
1050:		int video_pipe, i, v_urb_len;
1051:	
1052:		pr_debug("probing new GO7007 USB board\n");
1053:	
1054:		switch (id->driver_info) {
1055:		case GO7007_BOARDID_MATRIX_II:
1056:			name = "WIS Matrix II or compatible";
1057:			board = &board_matrix_ii;
1058:			break;
1059:		case GO7007_BOARDID_MATRIX_RELOAD:
1060:			name = "WIS Matrix Reloaded or compatible";
1061:			board = &board_matrix_reload;
1062:			break;
1063:		case GO7007_BOARDID_MATRIX_REV:
1064:			name = "WIS Matrix Revolution or compatible";
1065:			board = &board_matrix_revolution;
1066:			break;
1067:		case GO7007_BOARDID_STAR_TREK:
1068:			name = "WIS Star Trek or compatible";
1069:			board = &board_star_trek;
1070:			break;
1071:		case GO7007_BOARDID_XMEN:
1072:			name = "WIS XMen or compatible";
1073:			board = &board_xmen;
1074:			break;
1075:		case GO7007_BOARDID_XMEN_II:
1076:			name = "WIS XMen II or compatible";
1077:			board = &board_xmen;
1078:			break;
1079:		case GO7007_BOARDID_XMEN_III:
]

332/2 2026/07/30 13:15 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 155309
							output: 23
							thoughts: 51
						

Thoughts:
Okay, here's my take on those thoughts, tailored for an expert audience:

**Debugging a Missing Symbol**

Hmm, hold on a second. I was *certain* that `go7007_usb_release` was defined within the `go7007-usb.c` file. I was referencing that file in my previous analysis, and assumed that this must be the case. But, after a quick check, I realize I was mistaken. That function's definition isn't there! This means I've made a faulty assumption, and wasted time chasing a wrong lead. I need to recalibrate. My initial instinct was off. It's almost definitely declared, likely defined, and definitely implemented, somewhere else in the codebase. Given the typical structure of these drivers, the release function probably falls into the v4l2 handling, or at least the v4l2 context, so I should be looking in `go7007-v4l2.c`, or a similar v4l2-specific file, or something along those lines. Time to adjust my search parameters. Let's see what turns up in the v4l2 implementation.



333/2 2026/07/30 13:15 tool grepper
0m Args:
map[Expression:go7007_usb_release]

Results:
map[Output:drivers/media/usb/go7007/go7007-usb.c=879=static int go7007_usb_send_firmware(struct go7007 *go, u8 *data, int len)
--
drivers/media/usb/go7007/go7007-usb.c-895-
drivers/media/usb/go7007/go7007-usb.c:896:static void go7007_usb_release(struct go7007 *go)
drivers/media/usb/go7007/go7007-usb.c-897-{
--
drivers/media/usb/go7007/go7007-usb.c=927=static const struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = {
--
drivers/media/usb/go7007/go7007-usb.c-933-	.send_firmware		= go7007_usb_send_firmware,
drivers/media/usb/go7007/go7007-usb.c:934:	.release		= go7007_usb_release,
drivers/media/usb/go7007/go7007-usb.c-935-};
--
drivers/media/usb/go7007/go7007-usb.c=937=static const struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = {
--
drivers/media/usb/go7007/go7007-usb.c-943-	.send_firmware		= go7007_usb_send_firmware,
drivers/media/usb/go7007/go7007-usb.c:944:	.release		= go7007_usb_release,
drivers/media/usb/go7007/go7007-usb.c-945-};
--
drivers/media/usb/go7007/go7007-usb.c=1040=static int go7007_usb_probe(struct usb_interface *intf,
--
drivers/media/usb/go7007/go7007-usb.c-1322-allocfail:
drivers/media/usb/go7007/go7007-usb.c:1323:	go7007_usb_release(go);
drivers/media/usb/go7007/go7007-usb.c-1324-	kfree(go);
]

334/2 2026/07/30 13:15 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 156323
							output: 49
							thoughts: 15
						

Thoughts:
Okay, here's my interpretation of that thought process, assuming I'm well-versed in embedded systems and device drivers:

**Analyzing the USB Release Code: `go7007_usb_release`**

Alright, let's dive into this `go7007_usb_release` function. My initial thought is to figure out what device this is associated with, obviously some USB device. Based on the name it seems to be related to the go7007 codec or some derivative, so likely something handling video or audio input/output. The "release" part instantly suggests this is a critical section for cleaning up resources when the device is no longer in use, disconnected, or the driver is being unloaded. I'll need to scrutinize what it's *actually* releasing.

I'm expecting to see calls to `usb_free_urb()` and `usb_put_intf()` at a minimum. Probably also calls to `kfree()`ing any dynamically allocated memory associated with the device's private data, buffer, or descriptors. It's likely handling things like canceling any pending URBs (USB Request Blocks) to prevent data corruption or hangs, and releasing any claimed USB interfaces. It's crucial this code is robust, otherwise, we'll see memory leaks, resource contention, or even system crashes. I'll be looking carefully at the locking mechanisms used (mutexes, spinlocks) to ensure thread safety during the release process, especially if the device can be disconnected while actively being used. I'll also check if there's any error handling, such as error codes or logging, to help diagnose potential issues if the release fails for some reason. The goal here is to ensure a clean exit, preventing any dangling resources or causing side effects for other devices or applications.



335/2 2026/07/30 13:15 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:890 LineCount:50]

Results:
map[Contents: 890:			pipe = usb_sndbulkpipe(usb->usbdev, 3);
 891:	
 892:		return usb_bulk_msg(usb->usbdev, pipe, data, len,
 893:						&transferred, timeout);
 894:	}
 895:	
 896:	static void go7007_usb_release(struct go7007 *go)
 897:	{
 898:		struct go7007_usb *usb = go->hpi_context;
 899:		struct urb *vurb, *aurb;
 900:		int i;
 901:	
 902:		if (usb->intr_urb) {
 903:			usb_kill_urb(usb->intr_urb);
 904:			kfree(usb->intr_urb->transfer_buffer);
 905:			usb_free_urb(usb->intr_urb);
 906:		}
 907:	
 908:		/* Free USB-related structs */
 909:		for (i = 0; i < 8; ++i) {
 910:			vurb = usb->video_urbs[i];
 911:			if (vurb) {
 912:				usb_kill_urb(vurb);
 913:				kfree(vurb->transfer_buffer);
 914:				usb_free_urb(vurb);
 915:			}
 916:			aurb = usb->audio_urbs[i];
 917:			if (aurb) {
 918:				usb_kill_urb(aurb);
 919:				kfree(aurb->transfer_buffer);
 920:				usb_free_urb(aurb);
 921:			}
 922:		}
 923:	
 924:		kfree(go->hpi_context);
 925:	}
 926:	
 927:	static const struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = {
 928:		.interface_reset	= go7007_usb_interface_reset,
 929:		.write_interrupt	= go7007_usb_ezusb_write_interrupt,
 930:		.read_interrupt		= go7007_usb_read_interrupt,
 931:		.stream_start		= go7007_usb_stream_start,
 932:		.stream_stop		= go7007_usb_stream_stop,
 933:		.send_firmware		= go7007_usb_send_firmware,
 934:		.release		= go7007_usb_release,
 935:	};
 936:	
 937:	static const struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = {
 938:		.interface_reset	= go7007_usb_interface_reset,
 939:		.write_interrupt	= go7007_usb_onboard_write_interrupt,
]

336/2 2026/07/30 13:15 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 157624
							output: 50
							thoughts: 654
						

Thoughts:
**Analyzing a Potential Use-After-Free Vulnerability in the go7007 USB Driver**

Okay, hold on a second. I need to think this through. The `go7007_usb_release` function *doesn't* call `i2c_del_adapter`? That's the first red flag. Now, if the `go7007_usb_probe` function encounters an `allocfail`, it does call `go7007_usb_release(go)` and then `kfree(go)`. The problem is, `i2c_add_adapter` was called *before* the potential `allocfail`!

Looking at the code again... if we reach `allocfail` *after* `i2c_add_adapter` is successful, it frees the `go` structure without deleting the associated I2C adapter. That looks like a massive use-after-free vulnerability right there. But wait a moment... the `go->i2c_adapter` struct is actually embedded directly within the `struct go7007` structure, isn't it? So, freeing `go` *should* free the I2C adapter as well. However, it's still registered within the I2C core, which means any subsequent attempt to access the I2C adapter will actually result in a use-after-free on `go`.

Okay, the bug report... the KASAN output confirms this: "slab-use-after-free in i2c_adapter_lock_bus". It's pointing to a read of size 8 at a specific memory address, and crucially, it says the buggy address belongs to an object in the `kmalloc-4k` cache.

Now, if `kzalloc` is used to allocate `struct go7007`, does the size of `struct go7007` approximate 4096 bytes? I need to check the definition of that structure... this all depends on the sizes of its members and whether it's aligned for a 4k allocation. This could be a significant issue if the struct size is close enough to 4k.



337/2 2026/07/30 13:16 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-priv.h FirstLine:140 LineCount:100]

Results:
map[Contents: 140:	
 141:	enum go7007_parser_state {
 142:		STATE_DATA,
 143:		STATE_00,
 144:		STATE_00_00,
 145:		STATE_00_00_01,
 146:		STATE_FF,
 147:		STATE_VBI_LEN_A,
 148:		STATE_VBI_LEN_B,
 149:		STATE_MODET_MAP,
 150:		STATE_UNPARSED,
 151:	};
 152:	
 153:	struct go7007 {
 154:		struct device *dev;
 155:		u8 bus_info[32];
 156:		const struct go7007_board_info *board_info;
 157:		unsigned int board_id;
 158:		int tuner_type;
 159:		int channel_number; /* for multi-channel boards like Adlink PCI-MPG24 */
 160:		char name[64];
 161:		struct video_device vdev;
 162:		void *boot_fw;
 163:		unsigned boot_fw_len;
 164:		struct v4l2_device v4l2_dev;
 165:		struct v4l2_ctrl_handler hdl;
 166:		struct v4l2_ctrl *mpeg_video_encoding;
 167:		struct v4l2_ctrl *mpeg_video_gop_size;
 168:		struct v4l2_ctrl *mpeg_video_gop_closure;
 169:		struct v4l2_ctrl *mpeg_video_bitrate;
 170:		struct v4l2_ctrl *mpeg_video_aspect_ratio;
 171:		struct v4l2_ctrl *mpeg_video_b_frames;
 172:		struct v4l2_ctrl *mpeg_video_rep_seqheader;
 173:		struct v4l2_ctrl *modet_mode;
 174:		enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status;
 175:		spinlock_t spinlock;
 176:		struct mutex hw_lock;
 177:		struct mutex serialize_lock;
 178:		int audio_enabled;
 179:		struct v4l2_subdev *sd_video;
 180:		struct v4l2_subdev *sd_audio;
 181:		u8 usb_buf[16];
 182:	
 183:		/* Video input */
 184:		int input;
 185:		int aud_input;
 186:		enum { GO7007_STD_NTSC, GO7007_STD_PAL, GO7007_STD_OTHER } standard;
 187:		v4l2_std_id std;
 188:		int sensor_framerate;
 189:		int width;
 190:		int height;
 191:		int encoder_h_offset;
 192:		int encoder_v_offset;
 193:		unsigned int encoder_h_halve:1;
 194:		unsigned int encoder_v_halve:1;
 195:		unsigned int encoder_subsample:1;
 196:	
 197:		/* Encoder config */
 198:		u32 format;
 199:		int bitrate;
 200:		int fps_scale;
 201:		int pali;
 202:		int aspect_ratio;
 203:		int gop_size;
 204:		unsigned int ipb:1;
 205:		unsigned int closed_gop:1;
 206:		unsigned int repeat_seqhead:1;
 207:		unsigned int seq_header_enable:1;
 208:		unsigned int gop_header_enable:1;
 209:		unsigned int dvd_mode:1;
 210:		unsigned int interlace_coding:1;
 211:	
 212:		/* Motion detection */
 213:		unsigned int modet_enable:1;
 214:		struct {
 215:			unsigned int enable:1;
 216:			int pixel_threshold;
 217:			int motion_threshold;
 218:			int mb_threshold;
 219:		} modet[4];
 220:		unsigned char modet_map[1624];
 221:		unsigned char active_map[216];
 222:		u32 modet_event_status;
 223:	
 224:		/* Video streaming */
 225:		struct mutex queue_lock;
 226:		struct vb2_queue vidq;
 227:		enum go7007_parser_state state;
 228:		int parse_length;
 229:		u16 modet_word;
 230:		int seen_frame;
 231:		u32 next_seq;
 232:		struct list_head vidq_active;
 233:		wait_queue_head_t frame_waitq;
 234:		struct go7007_buffer *active_buf;
 235:	
 236:		/* Audio streaming */
 237:		void (*audio_deliver)(struct go7007 *go, u8 *buf, int length);
 238:		void *snd_context;
 239:	
]

338/2 2026/07/30 13:16 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 160306
							output: 50
							thoughts: 522
						

Thoughts:
**Analyzing a Potential I2C Adapter Leak in the go7007 Driver**

Okay, let's break this down. First, I'm looking at `struct go7007` and immediately see that it's substantial – it contains a sizable `struct video_device vdev`, alongside `struct v4l2_device v4l2_dev`, `unsigned char modet_map[1624]`, and `struct vb2_queue vidq`. Based on those members, it's very probable that the `struct go7007` instance is around 4KB in size.

The crux of the issue is what I suspected: `i2c_add_adapter` gets called, but if `go7007_usb_probe` subsequently fails, the `go` structure is freed *without* the corresponding `i2c_del_adapter` call. That's a classic resource leak, a textbook I2C adapter leak.

Now, I need to pinpoint where exactly `go7007_usb_probe` can fail *after* the `i2c_add_adapter` call to confirm this. I see the code checks for specific board IDs (`GO7007_BOARDID_XMEN` or `GO7007_BOARDID_XMEN_III`) and if the I2C adapter is online. Crucially, a specific I2C SMBus read is performed to verify register `0x0A`'s value. If that value is incorrect, it proceeds to read a channel number using `go7007_read_addr`. If *that* call fails, the function jumps to `allocfail`.

Aha! `go7007_read_addr` is the likely culprit. It's making a vendor-specific control message. If the device, or, as it seems is the case here, syzkaller, doesn't reply to that message, the call fails. This provides a very easy path to trigger the leak. The key is that `go->board_id` must be either `GO7007_BOARDID_XMEN` or `GO7007_BOARDID_XMEN_III`, so I'll check `go7007_usb_id_table` to confirm that the `XMEN` board ID is indeed associated with any USB device.



339/2 2026/07/30 13:16 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:1350 LineCount:50]

Results:
map[Contents:1350:		.disconnect	= go7007_usb_disconnect,
1351:		.id_table	= go7007_usb_id_table,
1352:	};
1353:	
1354:	module_usb_driver(go7007_usb_driver);
1355:	MODULE_DESCRIPTION("WIS GO7007 USB support");
1356:	MODULE_LICENSE("GPL v2");
]

340/2 2026/07/30 13:16 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 161528
							output: 25
							thoughts: 19
						

Thoughts:
Here's my summary, as the expert:

**Investigating the USB ID Table**

Okay, hold on a second. I'm going through this code, and I just saw a reference to `go7007_usb_id_table`. Hmm, let me think... didn't I see that definition earlier? I'm almost certain it's defined upstream in the initialization or device enumeration section. I need to go back and double-check where that table is actually created or populated. It's crucial because that table is the cornerstone for how the USB driver identifies and interacts with the specific go7007 devices. Understanding *when* and *how* that table gets populated is going to be central to debugging anything that comes next. I can't proceed further until I have a clear picture of that.



341/2 2026/07/30 13:16 tool grepper
0m Args:
map[Expression:go7007_usb_id_table]

Results:
map[Output:drivers/media/usb/go7007/go7007-usb.c=469=static const struct go7007_usb_board board_ads_usbav_709 = {
--
drivers/media/usb/go7007/go7007-usb.c-505-
drivers/media/usb/go7007/go7007-usb.c:506:static const struct usb_device_id go7007_usb_id_table[] = {
drivers/media/usb/go7007/go7007-usb.c-507-	{
--
drivers/media/usb/go7007/go7007-usb.c-617-
drivers/media/usb/go7007/go7007-usb.c:618:MODULE_DEVICE_TABLE(usb, go7007_usb_id_table);
drivers/media/usb/go7007/go7007-usb.c-619-
--
drivers/media/usb/go7007/go7007-usb.c=1347=static struct usb_driver go7007_usb_driver = {
--
drivers/media/usb/go7007/go7007-usb.c-1350-	.disconnect	= go7007_usb_disconnect,
drivers/media/usb/go7007/go7007-usb.c:1351:	.id_table	= go7007_usb_id_table,
drivers/media/usb/go7007/go7007-usb.c-1352-};
]

342/2 2026/07/30 13:16 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 162186
							output: 50
							thoughts: 17
						

Thoughts:
Okay, here's my attempt at summarizing the thought process, as requested, aimed at an expert user:

**Diving into the USB ID Table**

Right, let's get into this. I see `go7007_usb_id_table` – so that immediately tells me we're looking at device identification related to the GO7007 USB interface. I'm already anticipating a table filled with vendor IDs, product IDs, and potentially interface class codes, subclass codes, and protocol codes – the usual suspects. I’m guessing this file is crucial for the USB driver to recognize and correctly initialize devices based on the GO7007 chipset.

I'll be looking for any nuances, potential overrides, or perhaps even blacklists within this table. Given my experience, I'll be particularly interested in any vendor or product IDs I'm familiar with, or conversely, any I've never encountered before. New IDs often signal new hardware revisions or manufacturers, so I'll need to assess if this aligns with anything I've seen in recent hardware releases. I’m thinking in particular about any edge cases or unusual combinations that may have been reported as bugs in the past.

I also want to pay close attention to the granularity of the entries. Are there specific entries for different firmware revisions or hardware variants of the GO7007 devices? That level of detail could be critical for avoiding conflicts and ensuring compatibility. Any vendor or product IDs that seem generic will immediately catch my attention. They might indicate a driver that's attempting to be overly broad in its device matching, which could lead to instability or incorrect functionality.

Essentially, I need to get a clear picture of how this ID table fits within the broader picture of the GO7007 USB driver and how it handles device identification and initial setup. I'm going to scan the data, cross-reference it with any relevant documentation or known issues, and immediately flag anything that appears unusual or potentially problematic.



343/2 2026/07/30 13:16 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:500 LineCount:100]

Results:
map[Contents: 500:					.name		= "S-Video",
 501:				},
 502:			},
 503:		},
 504:	};
 505:	
 506:	static const struct usb_device_id go7007_usb_id_table[] = {
 507:		{
 508:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
 509:						USB_DEVICE_ID_MATCH_INT_INFO,
 510:			.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
 511:			.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
 512:			.bcdDevice_lo	= 0x200,   /* Revision number of XMen */
 513:			.bcdDevice_hi	= 0x200,
 514:			.bInterfaceClass	= 255,
 515:			.bInterfaceSubClass	= 0,
 516:			.bInterfaceProtocol	= 255,
 517:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_XMEN,
 518:		},
 519:		{
 520:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
 521:			.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
 522:			.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
 523:			.bcdDevice_lo	= 0x202,   /* Revision number of Matrix II */
 524:			.bcdDevice_hi	= 0x202,
 525:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_MATRIX_II,
 526:		},
 527:		{
 528:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
 529:			.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
 530:			.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
 531:			.bcdDevice_lo	= 0x204,   /* Revision number of Matrix */
 532:			.bcdDevice_hi	= 0x204,   /*     Reloaded */
 533:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_MATRIX_RELOAD,
 534:		},
 535:		{
 536:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
 537:						USB_DEVICE_ID_MATCH_INT_INFO,
 538:			.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
 539:			.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
 540:			.bcdDevice_lo	= 0x205,   /* Revision number of XMen-II */
 541:			.bcdDevice_hi	= 0x205,
 542:			.bInterfaceClass	= 255,
 543:			.bInterfaceSubClass	= 0,
 544:			.bInterfaceProtocol	= 255,
 545:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_XMEN_II,
 546:		},
 547:		{
 548:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
 549:			.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
 550:			.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
 551:			.bcdDevice_lo	= 0x208,   /* Revision number of Star Trek */
 552:			.bcdDevice_hi	= 0x208,
 553:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_STAR_TREK,
 554:		},
 555:		{
 556:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
 557:						USB_DEVICE_ID_MATCH_INT_INFO,
 558:			.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
 559:			.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
 560:			.bcdDevice_lo	= 0x209,   /* Revision number of XMen-III */
 561:			.bcdDevice_hi	= 0x209,
 562:			.bInterfaceClass	= 255,
 563:			.bInterfaceSubClass	= 0,
 564:			.bInterfaceProtocol	= 255,
 565:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_XMEN_III,
 566:		},
 567:		{
 568:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
 569:			.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
 570:			.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
 571:			.bcdDevice_lo	= 0x210,   /* Revision number of Matrix */
 572:			.bcdDevice_hi	= 0x210,   /*     Revolution */
 573:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_MATRIX_REV,
 574:		},
 575:		{
 576:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
 577:			.idVendor	= 0x093b,  /* Vendor ID of Plextor */
 578:			.idProduct	= 0xa102,  /* Product ID of M402U */
 579:			.bcdDevice_lo	= 0x1,	   /* revision number of Blueberry */
 580:			.bcdDevice_hi	= 0x1,
 581:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_PX_M402U,
 582:		},
 583:		{
 584:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
 585:			.idVendor	= 0x093b,  /* Vendor ID of Plextor */
 586:			.idProduct	= 0xa104,  /* Product ID of TV402U */
 587:			.bcdDevice_lo	= 0x1,
 588:			.bcdDevice_hi	= 0x1,
 589:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_PX_TV402U,
 590:		},
 591:		{
 592:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
 593:			.idVendor	= 0x10fd,  /* Vendor ID of Anubis Electronics */
 594:			.idProduct	= 0xde00,  /* Product ID of Lifeview LR192 */
 595:			.bcdDevice_lo	= 0x1,
 596:			.bcdDevice_hi	= 0x1,
 597:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_LIFEVIEW_LR192,
 598:		},
 599:		{
]

344/2 2026/07/30 13:16 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 164847
							output: 49
							thoughts: 536
						

Thoughts:
**Analyzing the XMEN Device**

Okay, so I've identified a device – `0x0eb1:0x7007` – as the `XMEN`. Let's see... its `bcdDevice` is `0x200`. And the interface details? `bInterfaceClass = 255`, `bInterfaceSubClass = 0`, and `bInterfaceProtocol = 255`. Now, let's build the `ANY` blob for `go7007`.

First, the Device Descriptor (18 bytes): `12 01 00 02 00 00 00 40 b1 0e 07 70 00 02 00 00 00 01`.  I'm just double-checking... right, `bcdDevice` being `0x200` means `00 02` in little-endian. Seems correct.

Next, the Configuration Descriptor (9 bytes): `09 02 22 00 01 01 00 80 00`. And the Interface Descriptor (9 bytes): `09 04 00 00 01 ff 00 ff 00`.

Finally, the Endpoint Descriptor (7 bytes): `07 05 81 02 40 00 00`. It's `0x81` for `bEndpointAddress` (IN), `2` for `bmAttributes` (Bulk), `64` for `wMaxPacketSize`, and `0` for `bInterval`. Good.

Right, so for `go7007` itself, it needs either `ep_in[6]` or `ep_in[1]`. According to the code, it depends on the `GO7007_USB_EZUSB` flag. If that flag is set, then use `ep_in[6]`. If not, then use `ep_in[1]`. Makes sense.

Now, does this `XMEN` have the `GO7007_USB_EZUSB` flag set? Need to check the `board_xmen` definition to be sure. That's the next step.



345/2 2026/07/30 13:16 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:200 LineCount:50]

Results:
map[Contents: 200:						GO7007_AUDIO_WORD_16,
 201:			.audio_bclk_div	 = 8,
 202:			.audio_main_div	 = 2,
 203:			.hpi_buffer_cap  = 7,
 204:			.num_i2c_devs	 = 5,
 205:			.i2c_devs	 = {
 206:				{
 207:					.type	= "saa7115",
 208:					.addr	= 0x20,
 209:					.is_video = 1,
 210:				},
 211:				{
 212:					.type	= "uda1342",
 213:					.addr	= 0x1a,
 214:					.is_audio = 1,
 215:				},
 216:				{
 217:					.type	= "tuner",
 218:					.addr	= 0x60,
 219:				},
 220:				{
 221:					.type	= "tuner",
 222:					.addr	= 0x43,
 223:				},
 224:				{
 225:					.type	= "sony-btf-mpx",
 226:					.addr	= 0x44,
 227:				},
 228:			},
 229:			.num_inputs	 = 3,
 230:			.inputs		 = {
 231:				{
 232:					.video_input	= 3,
 233:					.audio_index	= 0,
 234:					.name		= "Tuner",
 235:				},
 236:				{
 237:					.video_input	= 1,
 238:					.audio_index	= 1,
 239:					.name		= "Composite",
 240:				},
 241:				{
 242:					.video_input	= 8,
 243:					.audio_index	= 1,
 244:					.name		= "S-Video",
 245:				},
 246:			},
 247:			.video_config	= SAA7115_IDQ_IS_DEFAULT,
 248:			.num_aud_inputs	 = 2,
 249:			.aud_inputs	 = {
]

346/2 2026/07/30 13:16 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 166637
							output: 18
							thoughts: 14
						

Thoughts:
Here's my thought process, summarized as if I were considering the situation:

**Need to Review `board_xmen` Flags**

Okay, first things first, I need to make sure I'm on the right track. My immediate thought is to check for the `board_xmen` flags. I can't proceed effectively until I have a clear understanding of what those flags represent and how they are currently set. This is the foundation upon which I can evaluate the current state and determine next steps. I need to understand the context of those flags before digging deeper into the data. Let me go back and review the documentation on those flags...



347/2 2026/07/30 13:17 tool grepper
0m Args:
map[Expression:board_xmen]

Results:
map[Output:drivers/media/usb/go7007/go7007-usb.c=188=static const struct go7007_usb_board board_px_tv402u = {
--
drivers/media/usb/go7007/go7007-usb.c-261-
drivers/media/usb/go7007/go7007-usb.c:262:static const struct go7007_usb_board board_xmen = {
drivers/media/usb/go7007/go7007-usb.c-263-	.flags		= 0,
--
drivers/media/usb/go7007/go7007-usb.c=1040=static int go7007_usb_probe(struct usb_interface *intf,
--
drivers/media/usb/go7007/go7007-usb.c-1072-		name = "WIS XMen or compatible";
drivers/media/usb/go7007/go7007-usb.c:1073:		board = &board_xmen;
drivers/media/usb/go7007/go7007-usb.c-1074-		break;
--
drivers/media/usb/go7007/go7007-usb.c-1076-		name = "WIS XMen II or compatible";
drivers/media/usb/go7007/go7007-usb.c:1077:		board = &board_xmen;
drivers/media/usb/go7007/go7007-usb.c-1078-		break;
--
drivers/media/usb/go7007/go7007-usb.c-1080-		name = "WIS XMen III or compatible";
drivers/media/usb/go7007/go7007-usb.c:1081:		board = &board_xmen;
drivers/media/usb/go7007/go7007-usb.c-1082-		break;
]

348/2 2026/07/30 13:17 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 167351
							output: 49
							thoughts: 171
						

Thoughts:
**Analyzing the USB Endpoint Configuration**

Okay, so I'm looking at this `board_xmen` structure and its flags. The code's using those flags to determine how to configure the USB endpoints. Right now, it looks like `board_xmen` has `.flags = 0`. This means that the check `board->flags & GO7007_USB_EZUSB` is evaluating to FALSE. If that's the case, then the code *expects* `ep_in[1]` to be available.

That makes sense, right? Because then there's this block of code:
```
		} else {
			if (!usb->usbdev->ep_in[1])
				goto allocfail;
			v_urb_len = 512;
			video_pipe = usb_rcvbulkpipe(usb->usbdev, 1);
		}
```
If the EZUSB flag isn't set, it jumps into that `else` block and uses `ep_in[1]` for video. Then, it's suggesting that `ep_in[8]` is expected for audio.

Hmm, this is where I need to double-check. Does `board_xmen` have `GO7007_BOARD_HAS_AUDIO` defined? I need to go back and look at the `board_xmen` definition to be absolutely certain what the configuration should be. Gotta verify the audio endpoint setup based on the board definition.



349/2 2026/07/30 13:17 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:260 LineCount:50]

Results:
map[Contents: 260:	};
 261:	
 262:	static const struct go7007_usb_board board_xmen = {
 263:		.flags		= 0,
 264:		.main_info	= {
 265:			.flags		  = GO7007_BOARD_USE_ONBOARD_I2C,
 266:			.hpi_buffer_cap   = 0,
 267:			.sensor_flags	  = GO7007_SENSOR_VREF_POLAR,
 268:			.sensor_width	  = 320,
 269:			.sensor_height	  = 240,
 270:			.sensor_framerate = 30030,
 271:			.audio_flags	  = GO7007_AUDIO_ONE_CHANNEL |
 272:						GO7007_AUDIO_I2S_MODE_3 |
 273:						GO7007_AUDIO_WORD_14 |
 274:						GO7007_AUDIO_I2S_MASTER |
 275:						GO7007_AUDIO_BCLK_POLAR |
 276:						GO7007_AUDIO_OKI_MODE,
 277:			.audio_rate	  = 8000,
 278:			.audio_bclk_div	  = 48,
 279:			.audio_main_div	  = 1,
 280:			.num_i2c_devs	  = 1,
 281:			.i2c_devs	  = {
 282:				{
 283:					.type	= "ov7640",
 284:					.addr	= 0x21,
 285:				},
 286:			},
 287:			.num_inputs	  = 1,
 288:			.inputs		  = {
 289:				{
 290:					.name		= "Camera",
 291:				},
 292:			},
 293:		},
 294:	};
 295:	
 296:	static const struct go7007_usb_board board_matrix_revolution = {
 297:		.flags		= GO7007_USB_EZUSB,
 298:		.main_info	= {
 299:			.flags		 = GO7007_BOARD_HAS_AUDIO |
 300:						GO7007_BOARD_USE_ONBOARD_I2C,
 301:			.audio_flags	 = GO7007_AUDIO_I2S_MODE_1 |
 302:						GO7007_AUDIO_I2S_MASTER |
 303:						GO7007_AUDIO_WORD_16,
 304:			.audio_rate	 = 48000,
 305:			.audio_bclk_div	 = 8,
 306:			.audio_main_div	 = 2,
 307:			.hpi_buffer_cap  = 7,
 308:			.sensor_flags	 = GO7007_SENSOR_656 |
 309:						GO7007_SENSOR_TV |
]

350/2 2026/07/30 13:17 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 168786
							output: 50
							thoughts: 605
						

Thoughts:
**I2C Adapter Registration on the XMEN Board**

Okay, let's break this down. `board_xmen` is defined to use `GO7007_BOARD_USE_ONBOARD_I2C`, which means we're dealing with the on-board I2C.  The code snippet shows a check for `GO7007_USB_EZUSB_I2C`, but it's clear that *this* specific branch *doesn't* register the I2C adapter if that flag isn't set.  That makes sense. But if not here, *where* does it get registered?

Ah, got it! The `go7007_register_encoder` function does the heavy lifting, as it calls `go7007_i2c_init`! That function does call `i2c_add_adapter`, so *that's* where the XMEN's I2C adapter is getting registered, even though the first block of code isn't involved. Good.

The tricky part is that `go7007_register_encoder` is called at the very end of `go7007_usb_probe`, after everything else is supposed to be set up. So, if `go7007_register_encoder` fails, specifically *after* calling `go7007_i2c_init`, the function returns an error and jumps to `allocfail`.

*Here* is the problem: the `allocfail` path cleans up and frees the `go` structure *without* explicitly unregistering the I2C adapter. If `go7007_i2c_init` succeeds, but there's a problem later in the `go7007_register_encoder` function that causes it to fail, we've leaked an I2C adapter! We have to check `go7007_register_encoder` to see what could fail after the I2C init.



351/2 2026/07/30 13:17 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-driver.c FirstLine:600 LineCount:100]

Results:
map[Contents: 600:					if (vb && go->seen_frame)
 601:						vb->frame_offset =
 602:						vb->vb.vb2_buf.planes[0].bytesused;
 603:				}
 604:				/* Handle any special chunk types, or just write the
 605:				 * start code to the (potentially new) buffer */
 606:				switch (buf[i]) {
 607:				case 0xF5: /* timestamp */
 608:					go->parse_length = 12;
 609:					go->state = STATE_UNPARSED;
 610:					break;
 611:				case 0xF6: /* vbi */
 612:					go->state = STATE_VBI_LEN_A;
 613:					break;
 614:				case 0xF8: /* MD map */
 615:					go->parse_length = 0;
 616:					memset(go->active_map, 0,
 617:							sizeof(go->active_map));
 618:					go->state = STATE_MODET_MAP;
 619:					break;
 620:				case 0xFF: /* Potential JPEG start code */
 621:					store_byte(vb, 0x00);
 622:					store_byte(vb, 0x00);
 623:					store_byte(vb, 0x01);
 624:					go->state = STATE_FF;
 625:					break;
 626:				default:
 627:					store_byte(vb, 0x00);
 628:					store_byte(vb, 0x00);
 629:					store_byte(vb, 0x01);
 630:					store_byte(vb, buf[i]);
 631:					go->state = STATE_DATA;
 632:					break;
 633:				}
 634:				break;
 635:			case STATE_FF:
 636:				switch (buf[i]) {
 637:				case 0x00:
 638:					store_byte(vb, 0xFF);
 639:					go->state = STATE_00;
 640:					break;
 641:				case 0xFF:
 642:					store_byte(vb, 0xFF);
 643:					/* go->state remains STATE_FF */
 644:					break;
 645:				case 0xD8:
 646:					if (go->format == V4L2_PIX_FMT_MJPEG)
 647:						vb = frame_boundary(go, vb);
 648:					fallthrough;
 649:				default:
 650:					store_byte(vb, 0xFF);
 651:					store_byte(vb, buf[i]);
 652:					go->state = STATE_DATA;
 653:					break;
 654:				}
 655:				break;
 656:			case STATE_VBI_LEN_A:
 657:				go->parse_length = buf[i] << 8;
 658:				go->state = STATE_VBI_LEN_B;
 659:				break;
 660:			case STATE_VBI_LEN_B:
 661:				go->parse_length |= buf[i];
 662:				if (go->parse_length > 0)
 663:					go->state = STATE_UNPARSED;
 664:				else
 665:					go->state = STATE_DATA;
 666:				break;
 667:			case STATE_MODET_MAP:
 668:				if (go->parse_length < 204) {
 669:					if (go->parse_length & 1) {
 670:						go->modet_word |= buf[i];
 671:						write_bitmap_word(go);
 672:					} else
 673:						go->modet_word = buf[i] << 8;
 674:				} else if (go->parse_length == 207 && vb) {
 675:					vb->modet_active = buf[i];
 676:				}
 677:				if (++go->parse_length == 208)
 678:					go->state = STATE_DATA;
 679:				break;
 680:			case STATE_UNPARSED:
 681:				if (--go->parse_length == 0)
 682:					go->state = STATE_DATA;
 683:				break;
 684:			}
 685:		}
 686:	}
 687:	EXPORT_SYMBOL(go7007_parse_video_stream);
 688:	
 689:	/*
 690:	 * Allocate a new go7007 struct.  Used by the hardware-specific probe.
 691:	 */
 692:	struct go7007 *go7007_alloc(const struct go7007_board_info *board,
 693:							struct device *dev)
 694:	{
 695:		struct go7007 *go;
 696:	
 697:		go = kzalloc_obj(struct go7007);
 698:		if (go == NULL)
 699:			return NULL;
]

352/2 2026/07/30 13:17 llm crash-repro-finder-compressor
0m Model:
gemini-3.5-flash

Reply:
### 1. Approaches Tried and Results

*   **Direct Device Opening**:
    *   Attempted to open `/dev/video0` and `/dev/i2c-0` directly using `syz_open_dev$video` and `syz_open_dev$I2C` with explicit paths.
    *   *Result*: Failed with syntax errors because syzkaller requires the exact template string `"/dev/video#\x00"` or `"/dev/i2c-#\x00"`.
*   **Generic HID Emulation**:
    *   Used `syz_usb_connect$hid` to connect a generic HID device.
    *   *Result*: No crash. Target drivers (`si4713`, `au0828`, `go7007`) were not bound because syzkaller patches vendor/product IDs to match generic HID drivers.
*   **Custom USB Descriptor Construction via Structs**:
    *   Attempted to construct a custom `usb_device_descriptor` for `syz_usb_connect` to emulate `si4713` (Vendor `0x10c4`, Product `0x8244`, Class `USB_CLASS_HID`).
    *   *Dead-ends & Syntax Errors*:
        *   `AUTO` cannot be used for `FlagsType` or `ArrayType` fields.
        *   `void` fields (like `extra` in `usb_config_descriptor_verbose_t`) must be represented as `""` (empty string) in the struct literal.
        *   `len` fields must be explicitly provided as `AUTO` in the struct literal.
        *   `usb_interface_descriptor` is a struct with a single field `inner`, requiring nested braces `{{{...}}}` for its array elements.
        *   `bInterfaceClass` in `usb_interface_descriptor` is hardcoded to `0` in syzkaller's generic definitions, preventing the emulation of `USB_CLASS_HID` (3) using standard structs.
*   **USB Emulation via Raw `ANY` Blobs**:
    *   Attempted to pass a raw byte array for the device descriptor using `&AUTO=ANY=[@ANYBLOB="..."]`.
    *   *Result*: If the blob is only 18 bytes (device descriptor), the `configs` array is empty, resulting in no configurations and no driver probe.
    *   *Correction*: Constructed a full 52-byte concatenated USB descriptor blob containing Device, Config, Interface, HID, and Endpoint descriptors:
        `"1201000200000040c410448200000000000109022200010100800009040000010300000009211101000122220007058103400001"`
*   **Target Driver Investigation**:
    *   **`si4713`**: Requires complex control message handshakes during `si4713_send_startup_command`. If the handshake fails, the probe fails before `si4713_register_i2c_adapter` is called, meaning the I2C adapter is never registered. This is a dead-end for triggering the UAF.
    *   **`au0828`**: Requires `USB_SPEED_HIGH` (speed 3) and `bInterfaceNumber = 0`. If `au0828_analog_register` fails (e.g., due to missing alternate setting 5), `au0828_usb_probe` calls `au0828_usb_disconnect` and returns an error. In `au0828_usb_disconnect`, `au0828_analog_unregister` returns 1, causing the disconnect function to return early and skip `au0828_usb_release(dev)`. This leaks `dev` and leaves the I2C adapter registered with a dangling parent pointer to the freed `usb_device`.

### 2. Current Hypotheses & Active Lines of Investigation

*   **`au0828` Deferred Cleanup Leak**:
    *   Emulate an `au0828` USB device (Vendor `0x2040`, Product `0x7200`) with high speed and interface 0.
    *   Intentionally omit alternate setting 5 to force `au0828_analog_register` to fail during probe.
    *   The probe failure triggers the early-return bug in `au0828_usb_disconnect`, leaking the registered I2C adapter.
    *   Disconnect the USB device to free the `usb_device` structure.
    *   Perform an I2C transaction (e.g., `ioctl$I2C_SMBUS`) on the leaked I2C adapter to trigger the UAF in `i2c_adapter_depth` when it dereferences `adapter->dev.parent->type`.
*   **`go7007` Driver Analysis**:
    *   Investigating if `go7007` (Vendor `0x0eb1`, Product `0x7007`) has a similar I2C adapter registration leak on probe failure or disconnect.

### 3. Critical Code and Configuration Values

*   **`au0828` USB Disconnect Bug (`drivers/media/usb/au0828/au0828-core.c`)**:
    ```c
    static void au0828_usb_disconnect(struct usb_interface *interface)
    {
        struct au0828_dev *dev = usb_get_intfdata(interface);
        ...
        if (au0828_analog_unregister(dev)) {
            /* No need to call au0828_usb_release() if V4L2 is enabled */
            return;
        }
        au0828_usb_release(dev);
    }
    ```
*   **`vusb_responses` Struct Alignment**:
    Must provide all 17 fields when specifying a custom `generic` response to avoid parsing errors:
    ```
    &AUTO={AUTO, &AUTO={0x20, 0x01, AUTO, "0000000000000000"}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    ```

### 4. Potential Reasoning Loops / Repetitive Tool Calls

*   **USB ID Patching**: Avoid using standard `usb_device_descriptor` structs for custom IDs, as syzkaller's Go code will patch them during generation/mutation. Use `ANY` blobs to force specific IDs.
*   **String Literals**: Do not use raw `\x00` in syzkaller string arguments; use hex-encoded strings like `"0000000000000000"` for raw buffers.

Tokens:
							input: 161437
							output: 1619
							thoughts: 821
						

353/2 2026/07/30 13:18 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 42254
							output: 23
							thoughts: 17
						

Thoughts:
Okay, here's my summary, framed as my internal thought process:

**Diving into the Encoder Register**

Right, I'm deep in this code, and I've hit a point where I need to clarify something. Hang on... I need to track down a specific register. It's the `go7007_register_encoder`. That function name just screams "encoder configuration" to me. I need to understand what's happening within that function, what it's setting, and how it relates to the overall data flow. No point in just glossing over it. It's a critical piece of the puzzle, likely involved in how we're translating the input into the final output. Time to find that definition and see what secrets it holds.



354/2 2026/07/30 13:18 tool grepper
0m Args:
map[Expression:go7007_register_encoder]

Results:
map[Output:drivers/media/pci/saa7134/saa7134-go7007.c=405=static int saa7134_go7007_init(struct saa7134_dev *dev)
--
drivers/media/pci/saa7134/saa7134-go7007.c-450-	 * V4L2 and ALSA interfaces */
drivers/media/pci/saa7134/saa7134-go7007.c:451:	if (go7007_register_encoder(go, go->board_info->num_i2c_devs) < 0)
drivers/media/pci/saa7134/saa7134-go7007.c-452-		goto allocfail;
--
drivers/media/usb/go7007/go7007-driver.c=227=static void go7007_remove(struct v4l2_device *v4l2_dev)
--
drivers/media/usb/go7007/go7007-driver.c-251- */
drivers/media/usb/go7007/go7007-driver.c:252:int go7007_register_encoder(struct go7007 *go, unsigned num_i2c_devs)
drivers/media/usb/go7007/go7007-driver.c-253-{
--
drivers/media/usb/go7007/go7007-driver.c-314-}
drivers/media/usb/go7007/go7007-driver.c:315:EXPORT_SYMBOL(go7007_register_encoder);
drivers/media/usb/go7007/go7007-driver.c-316-
--
drivers/media/usb/go7007/go7007-priv.h=276=int go7007_reset_encoder(struct go7007 *go);
drivers/media/usb/go7007/go7007-priv.h:277:int go7007_register_encoder(struct go7007 *go, unsigned num_i2c_devs);
drivers/media/usb/go7007/go7007-priv.h-278-int go7007_start_encoder(struct go7007 *go);
--
drivers/media/usb/go7007/go7007-usb.c=1040=static int go7007_usb_probe(struct usb_interface *intf,
--
drivers/media/usb/go7007/go7007-usb.c-1315-	 * V4L2 and ALSA interfaces */
drivers/media/usb/go7007/go7007-usb.c:1316:	if (go7007_register_encoder(go, num_i2c_devs) < 0)
drivers/media/usb/go7007/go7007-usb.c-1317-		goto allocfail;
]

355/2 2026/07/30 13:18 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 43274
							output: 50
							thoughts: 39
						

Thoughts:
Here's my attempt at summarizing the thought process, tailored for an expert audience:

**Diving into the go7007 Encoder Registration**

Okay, time to dig into the go7007 driver again. I'm going to focus on the encoder registration process – specifically, `go7007_register_encoder` within `drivers/media/usb/go7007/go7007-driver.c`. I need to refresh my memory on how this device is introduced to the media framework. I'm especially curious about how the encoder capabilities are advertised and initialized within the kernel. I'll be looking for: how the device structures are populated, what flags and parameters are used during the registration, and how this links into the video4linux stack. I'll be watching to see how the driver handles initialization dependencies. I'm expecting to see calls to V4L2 functions for device registration and I'll pay attention to the error handling within this function to see how it manages potential issues during encoder setup. Finally, I'll be keeping a lookout for any proprietary extensions used by this driver.



356/2 2026/07/30 13:18 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-driver.c FirstLine:250 LineCount:100]

Results:
map[Contents: 250:	 * Must NOT be called with the hw_lock held.
 251:	 */
 252:	int go7007_register_encoder(struct go7007 *go, unsigned num_i2c_devs)
 253:	{
 254:		int i, ret;
 255:	
 256:		dev_info(go->dev, "go7007: registering new %s\n", go->name);
 257:	
 258:		go->v4l2_dev.release = go7007_remove;
 259:		ret = v4l2_device_register(go->dev, &go->v4l2_dev);
 260:		if (ret < 0)
 261:			return ret;
 262:	
 263:		mutex_lock(&go->hw_lock);
 264:		ret = go7007_init_encoder(go);
 265:		mutex_unlock(&go->hw_lock);
 266:		if (ret < 0)
 267:			return ret;
 268:	
 269:		ret = go7007_v4l2_ctrl_init(go);
 270:		if (ret < 0)
 271:			return ret;
 272:	
 273:		if (!go->i2c_adapter_online &&
 274:				go->board_info->flags & GO7007_BOARD_USE_ONBOARD_I2C) {
 275:			ret = go7007_i2c_init(go);
 276:			if (ret < 0)
 277:				return ret;
 278:			go->i2c_adapter_online = 1;
 279:		}
 280:		if (go->i2c_adapter_online) {
 281:			if (go->board_id == GO7007_BOARDID_ADS_USBAV_709) {
 282:				/* Reset the TW9906 */
 283:				go7007_write_addr(go, 0x3c82, 0x0009);
 284:				msleep(50);
 285:				go7007_write_addr(go, 0x3c82, 0x000d);
 286:			}
 287:			for (i = 0; i < num_i2c_devs; ++i)
 288:				init_i2c_module(&go->i2c_adapter, &go->board_info->i2c_devs[i]);
 289:	
 290:			if (go->tuner_type >= 0) {
 291:				struct tuner_setup setup = {
 292:					.addr = ADDR_UNSET,
 293:					.type = go->tuner_type,
 294:					.mode_mask = T_ANALOG_TV,
 295:				};
 296:	
 297:				v4l2_device_call_all(&go->v4l2_dev, 0, tuner,
 298:					s_type_addr, &setup);
 299:			}
 300:			if (go->board_id == GO7007_BOARDID_ADLINK_MPG24)
 301:				v4l2_subdev_call(go->sd_video, video, s_routing,
 302:						0, 0, go->channel_number + 1);
 303:		}
 304:	
 305:		ret = go7007_v4l2_init(go);
 306:		if (ret < 0)
 307:			return ret;
 308:	
 309:		if (go->board_info->flags & GO7007_BOARD_HAS_AUDIO) {
 310:			go->audio_enabled = 1;
 311:			go7007_snd_init(go);
 312:		}
 313:		return 0;
 314:	}
 315:	EXPORT_SYMBOL(go7007_register_encoder);
 316:	
 317:	/*
 318:	 * Send the encode firmware to the encoder, which will cause it
 319:	 * to immediately start delivering the video and audio streams.
 320:	 *
 321:	 * Must be called with the hw_lock held.
 322:	 */
 323:	int go7007_start_encoder(struct go7007 *go)
 324:	{
 325:		u8 *fw;
 326:		int fw_len, rv = 0, i, x, y;
 327:		u16 intr_val, intr_data;
 328:	
 329:		go->modet_enable = 0;
 330:		for (i = 0; i < 4; i++)
 331:			go->modet[i].enable = 0;
 332:	
 333:		switch (v4l2_ctrl_g_ctrl(go->modet_mode)) {
 334:		case V4L2_DETECT_MD_MODE_GLOBAL:
 335:			memset(go->modet_map, 0, sizeof(go->modet_map));
 336:			go->modet[0].enable = 1;
 337:			go->modet_enable = 1;
 338:			break;
 339:		case V4L2_DETECT_MD_MODE_REGION_GRID:
 340:			for (y = 0; y < go->height / 16; y++) {
 341:				for (x = 0; x < go->width / 16; x++) {
 342:					int idx = y * go->width / 16 + x;
 343:	
 344:					go->modet[go->modet_map[idx]].enable = 1;
 345:				}
 346:			}
 347:			go->modet_enable = 1;
 348:			break;
 349:		}
]

357/2 2026/07/30 13:18 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 45313
							output: 53
							thoughts: 170
						

Thoughts:
**Analyzing the `go7007` Driver Initialization**

Okay, let's break this down. My initial thought is that `go7007_register_encoder` is calling `go7007_v4l2_init(go)`. That seems straightforward. But wait... if `go7007_v4l2_init` returns an error, let's say `ret` is less than zero, that triggers a failure. Then, the `go7007_usb_probe` function jumps straight to the `allocfail` label. And here's where it gets interesting: `allocfail` subsequently frees the `go` structure. But, didn't `go7007_register_encoder` already call `go7007_i2c_init(go)` *before* `go7007_v4l2_init`? And, inside `go7007_i2c_init`, `i2c_add_adapter` gets called! That potentially means we're adding an I2C adapter *before* we've validated the V4L2 initialization. This is a potential resource leak, or a premature deallocation problem! Therefore, I need to understand what's happening inside `go7007_v4l2_init` to determine the point of failure. I need to trace this more carefully.



358/2 2026/07/30 13:18 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-v4l2.c FirstLine:800 LineCount:100]

Results:
map[Contents: 800:		case V4L2_CID_MOTION_THRESHOLD2:
 801:			go->modet[2].motion_threshold = ctrl->val;
 802:			break;
 803:		case V4L2_CID_MB_THRESHOLD2:
 804:			go->modet[2].mb_threshold = ctrl->val;
 805:			break;
 806:		case V4L2_CID_PIXEL_THRESHOLD3:
 807:			go->modet[3].pixel_threshold = ctrl->val;
 808:			break;
 809:		case V4L2_CID_MOTION_THRESHOLD3:
 810:			go->modet[3].motion_threshold = ctrl->val;
 811:			break;
 812:		case V4L2_CID_MB_THRESHOLD3:
 813:			go->modet[3].mb_threshold = ctrl->val;
 814:			break;
 815:		case V4L2_CID_DETECT_MD_REGION_GRID:
 816:			mt = go->modet_map;
 817:			for (y = 0; y < go->height / 16; y++, mt += go->width / 16)
 818:				memcpy(mt, ctrl->p_new.p_u8 + y * (720 / 16), go->width / 16);
 819:			break;
 820:		default:
 821:			return -EINVAL;
 822:		}
 823:		return 0;
 824:	}
 825:	
 826:	static const struct v4l2_file_operations go7007_fops = {
 827:		.owner		= THIS_MODULE,
 828:		.open		= v4l2_fh_open,
 829:		.release	= vb2_fop_release,
 830:		.unlocked_ioctl	= video_ioctl2,
 831:		.read		= vb2_fop_read,
 832:		.mmap		= vb2_fop_mmap,
 833:		.poll		= vb2_fop_poll,
 834:	};
 835:	
 836:	static const struct v4l2_ioctl_ops video_ioctl_ops = {
 837:		.vidioc_querycap          = vidioc_querycap,
 838:		.vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
 839:		.vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
 840:		.vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
 841:		.vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
 842:		.vidioc_reqbufs           = vb2_ioctl_reqbufs,
 843:		.vidioc_querybuf          = vb2_ioctl_querybuf,
 844:		.vidioc_qbuf              = vb2_ioctl_qbuf,
 845:		.vidioc_dqbuf             = vb2_ioctl_dqbuf,
 846:		.vidioc_g_std             = vidioc_g_std,
 847:		.vidioc_s_std             = vidioc_s_std,
 848:		.vidioc_querystd          = vidioc_querystd,
 849:		.vidioc_enum_input        = vidioc_enum_input,
 850:		.vidioc_g_input           = vidioc_g_input,
 851:		.vidioc_s_input           = vidioc_s_input,
 852:		.vidioc_enumaudio         = vidioc_enumaudio,
 853:		.vidioc_g_audio           = vidioc_g_audio,
 854:		.vidioc_s_audio           = vidioc_s_audio,
 855:		.vidioc_streamon          = vb2_ioctl_streamon,
 856:		.vidioc_streamoff         = vb2_ioctl_streamoff,
 857:		.vidioc_g_tuner           = vidioc_g_tuner,
 858:		.vidioc_s_tuner           = vidioc_s_tuner,
 859:		.vidioc_g_frequency       = vidioc_g_frequency,
 860:		.vidioc_s_frequency       = vidioc_s_frequency,
 861:		.vidioc_g_parm            = vidioc_g_parm,
 862:		.vidioc_s_parm            = vidioc_s_parm,
 863:		.vidioc_enum_framesizes   = vidioc_enum_framesizes,
 864:		.vidioc_enum_frameintervals = vidioc_enum_frameintervals,
 865:		.vidioc_log_status        = vidioc_log_status,
 866:		.vidioc_subscribe_event   = vidioc_subscribe_event,
 867:		.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 868:	};
 869:	
 870:	static const struct video_device go7007_template = {
 871:		.name		= "go7007",
 872:		.fops		= &go7007_fops,
 873:		.release	= video_device_release_empty,
 874:		.ioctl_ops	= &video_ioctl_ops,
 875:		.tvnorms	= V4L2_STD_ALL,
 876:	};
 877:	
 878:	static const struct v4l2_ctrl_ops go7007_ctrl_ops = {
 879:		.s_ctrl = go7007_s_ctrl,
 880:	};
 881:	
 882:	static const struct v4l2_ctrl_config go7007_pixel_threshold0_ctrl = {
 883:		.ops = &go7007_ctrl_ops,
 884:		.id = V4L2_CID_PIXEL_THRESHOLD0,
 885:		.name = "Pixel Threshold Region 0",
 886:		.type = V4L2_CTRL_TYPE_INTEGER,
 887:		.def = 20,
 888:		.max = 32767,
 889:		.step = 1,
 890:	};
 891:	
 892:	static const struct v4l2_ctrl_config go7007_motion_threshold0_ctrl = {
 893:		.ops = &go7007_ctrl_ops,
 894:		.id = V4L2_CID_MOTION_THRESHOLD0,
 895:		.name = "Motion Threshold Region 0",
 896:		.type = V4L2_CTRL_TYPE_INTEGER,
 897:		.def = 80,
 898:		.max = 32767,
 899:		.step = 1,
]

359/2 2026/07/30 13:18 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 47826
							output: 54
							thoughts: 20
						

Thoughts:
Here's my thought process, summarized as you requested:

**Deconstructing the Initialization**

Okay, hold on a second. Before I proceed, I need to get a handle on this. I'm seeing something mentioned here, `go7007_v4l2_init`. I need to understand what this function does. This is critical. It's likely the starting point for initializing the V4L2 interface for this `go7007` device. I can't build any further understanding or plan my next steps until I comprehend how the device itself is brought online from the driver's perspective. I need to trace its inputs, outputs, and any important side effects before anything else. This init function is the cornerstone.



360/2 2026/07/30 13:18 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-v4l2.c FirstLine:1100 LineCount:100]

Results:
map[Contents:1100:			v4l2_disable_ioctl(vdev, VIDIOC_QUERYSTD);
1101:		if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) {
1102:			v4l2_disable_ioctl(vdev, VIDIOC_S_FREQUENCY);
1103:			v4l2_disable_ioctl(vdev, VIDIOC_G_FREQUENCY);
1104:			v4l2_disable_ioctl(vdev, VIDIOC_S_TUNER);
1105:			v4l2_disable_ioctl(vdev, VIDIOC_G_TUNER);
1106:		} else {
1107:			struct v4l2_frequency f = {
1108:				.type = V4L2_TUNER_ANALOG_TV,
1109:				.frequency = 980,
1110:			};
1111:	
1112:			call_all(&go->v4l2_dev, tuner, s_frequency, &f);
1113:		}
1114:		if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV)) {
1115:			v4l2_disable_ioctl(vdev, VIDIOC_G_STD);
1116:			v4l2_disable_ioctl(vdev, VIDIOC_S_STD);
1117:			vdev->tvnorms = 0;
1118:		}
1119:		if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING)
1120:			v4l2_disable_ioctl(vdev, VIDIOC_ENUM_FRAMESIZES);
1121:		if (go->board_info->num_aud_inputs == 0) {
1122:			v4l2_disable_ioctl(vdev, VIDIOC_G_AUDIO);
1123:			v4l2_disable_ioctl(vdev, VIDIOC_S_AUDIO);
1124:			v4l2_disable_ioctl(vdev, VIDIOC_ENUMAUDIO);
1125:		}
1126:		/* Setup correct crystal frequency on this board */
1127:		if (go->board_info->sensor_flags & GO7007_SENSOR_SAA7115)
1128:			v4l2_subdev_call(go->sd_video, video, s_crystal_freq,
1129:					SAA7115_FREQ_24_576_MHZ,
1130:					SAA7115_FREQ_FL_APLL | SAA7115_FREQ_FL_UCGC |
1131:					SAA7115_FREQ_FL_DOUBLE_ASCLK);
1132:		go7007_s_input(go);
1133:		if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
1134:			go7007_s_std(go);
1135:		rv = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
1136:		if (rv < 0)
1137:			return rv;
1138:		dev_info(go->dev, "registered device %s [v4l2]\n",
1139:			 video_device_node_name(vdev));
1140:	
1141:		return 0;
1142:	}
1143:	
1144:	void go7007_v4l2_remove(struct go7007 *go)
1145:	{
1146:		v4l2_ctrl_handler_free(&go->hdl);
1147:	}
]

361/2 2026/07/30 13:18 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 49052
							output: 53
							thoughts: 22
						

Thoughts:
Here's my attempt at summarizing the thought process, tailored for an expert audience:

**Debugging Initiative: Function Placement**

Okay, so I'm digging through this `go7007_v4l2` code, and I'm looking at the initialization sequence. I thought I had a handle on the flow, but I need to re-evaluate where I'm at. I thought it was earlier, but wait, looking at the code, `go7007_v4l2_init` isn't where I expected it. I'm going to quickly re-scan this file and double-check its location. I need to pinpoint the *exact* spot of this function. That is essential for understanding how the driver's underlying structures are set up. I need to see when, exactly, it's called and by what other parts of the driver. I need to make sure I'm following the correct execution path. I will need to trace back from this function call to its callers to understand how the driver's fundamental structures are set up, and make sure that it all makes logical sense.



362/2 2026/07/30 13:18 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-v4l2.c FirstLine:1040 LineCount:60]

Results:
map[Contents:1040:		v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold0_ctrl, NULL);
1041:		v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold0_ctrl, NULL);
1042:		v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold0_ctrl, NULL);
1043:		v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold1_ctrl, NULL);
1044:		v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold1_ctrl, NULL);
1045:		v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold1_ctrl, NULL);
1046:		v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold2_ctrl, NULL);
1047:		v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold2_ctrl, NULL);
1048:		v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold2_ctrl, NULL);
1049:		v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold3_ctrl, NULL);
1050:		v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold3_ctrl, NULL);
1051:		v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold3_ctrl, NULL);
1052:		v4l2_ctrl_new_custom(hdl, &go7007_mb_regions_ctrl, NULL);
1053:		go->modet_mode = v4l2_ctrl_new_std_menu(hdl, NULL,
1054:				V4L2_CID_DETECT_MD_MODE,
1055:				V4L2_DETECT_MD_MODE_REGION_GRID,
1056:				1 << V4L2_DETECT_MD_MODE_THRESHOLD_GRID,
1057:				V4L2_DETECT_MD_MODE_DISABLED);
1058:		if (hdl->error) {
1059:			int rv = hdl->error;
1060:	
1061:			v4l2_err(&go->v4l2_dev, "Could not register controls\n");
1062:			return rv;
1063:		}
1064:		go->v4l2_dev.ctrl_handler = hdl;
1065:		return 0;
1066:	}
1067:	
1068:	int go7007_v4l2_init(struct go7007 *go)
1069:	{
1070:		struct video_device *vdev = &go->vdev;
1071:		int rv;
1072:	
1073:		mutex_init(&go->serialize_lock);
1074:		mutex_init(&go->queue_lock);
1075:	
1076:		INIT_LIST_HEAD(&go->vidq_active);
1077:		go->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1078:		go->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1079:		go->vidq.ops = &go7007_video_qops;
1080:		go->vidq.mem_ops = &vb2_vmalloc_memops;
1081:		go->vidq.drv_priv = go;
1082:		go->vidq.buf_struct_size = sizeof(struct go7007_buffer);
1083:		go->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1084:		go->vidq.lock = &go->queue_lock;
1085:		rv = vb2_queue_init(&go->vidq);
1086:		if (rv)
1087:			return rv;
1088:		*vdev = go7007_template;
1089:		vdev->lock = &go->serialize_lock;
1090:		vdev->queue = &go->vidq;
1091:		vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
1092:				    V4L2_CAP_STREAMING;
1093:		if (go->board_info->num_aud_inputs)
1094:			vdev->device_caps |= V4L2_CAP_AUDIO;
1095:		if (go->board_info->flags & GO7007_BOARD_HAS_TUNER)
1096:			vdev->device_caps |= V4L2_CAP_TUNER;
1097:		video_set_drvdata(vdev, go);
1098:		vdev->v4l2_dev = &go->v4l2_dev;
1099:		if (!v4l2_device_has_op(&go->v4l2_dev, 0, video, querystd))
]

363/2 2026/07/30 13:18 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 50792
							output: 50
							thoughts: 1102
						

Thoughts:
**Analyzing the GO7007 USB Probe Function**

Okay, let's break this down systematically. I'm starting with `go7007_usb_probe` and its potential failure points. My initial thought is that the call to `video_register_device` within `go7007_v4l2_init` could fail. If that fails, it returns a negative value, `rv`, and `go7007_usb_probe` should then jump to `allocfail`. So, the question is, what can make `video_register_device` fail? Running out of minor numbers is possible, but not typical.

But hold on, what if `go7007_v4l2_init` doesn't actually fail immediately? Maybe a later call within `go7007_register_encoder` fails instead? The code does call `go7007_snd_init`, but its return value is ignored. Therefore, `go7007_register_encoder` *won't* fail after `go7007_v4l2_init` because of the audio init. This means `go7007_v4l2_init` itself must be the problem.

Alright, so how can `go7007_v4l2_init` fail? The initialization of `vb2_queue_init` could fail if `go->vidq` is invalid, but that seems unlikely as it's hardcoded. However, `video_register_device` could still fail from the V4L2 init code, but that is rare.

Let's focus on whether `go7007_usb_probe` can fail AFTER the `go7007_register_encoder` call. The code shows no failure points after that function returns 0.

So, could `go7007_register_encoder` fail BEFORE `go7007_v4l2_init`? It looks like we have a branch. First, there's a call to `go7007_i2c_init`, which could fail. Then it seems there are multiple calls based on the board, but they seem mostly setup-based, so I'll need to dig deeper. The next significant point is that `init_i2c_module` calls `v4l2_i2c_new_subdev`. If `go7007_v4l2_init` fails, it returns a negative value. But how to *make* it fail? And where else could `go7007_usb_probe` potentially fail? Let's go back and re-examine the `go7007_usb_probe` function.



364/2 2026/07/30 13:18 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:1260 LineCount:50]

Results:
map[Contents:1260:			}
1261:		}
1262:	
1263:		/* Print a nasty message if the user attempts to use a USB2.0 device in
1264:		 * a USB1.1 port.  There will be silent corruption of the stream. */
1265:		if ((board->flags & GO7007_USB_EZUSB) &&
1266:				usbdev->speed != USB_SPEED_HIGH)
1267:			dev_err(go->dev, "*** WARNING ***  This device must be connected to a USB 2.0 port! Attempting to capture video through a USB 1.1 port will result in stream corruption, even at low bitrates!\n");
1268:	
1269:		/* Allocate the URBs and buffers for receiving the video stream */
1270:		if (board->flags & GO7007_USB_EZUSB) {
1271:			if (!usb->usbdev->ep_in[6])
1272:				goto allocfail;
1273:			v_urb_len = 1024;
1274:			video_pipe = usb_rcvbulkpipe(usb->usbdev, 6);
1275:		} else {
1276:			if (!usb->usbdev->ep_in[1])
1277:				goto allocfail;
1278:			v_urb_len = 512;
1279:			video_pipe = usb_rcvbulkpipe(usb->usbdev, 1);
1280:		}
1281:		for (i = 0; i < 8; ++i) {
1282:			usb->video_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
1283:			if (usb->video_urbs[i] == NULL)
1284:				goto allocfail;
1285:			usb->video_urbs[i]->transfer_buffer =
1286:							kmalloc(v_urb_len, GFP_KERNEL);
1287:			if (usb->video_urbs[i]->transfer_buffer == NULL)
1288:				goto allocfail;
1289:			usb_fill_bulk_urb(usb->video_urbs[i], usb->usbdev, video_pipe,
1290:					usb->video_urbs[i]->transfer_buffer, v_urb_len,
1291:					go7007_usb_read_video_pipe_complete, go);
1292:		}
1293:	
1294:		/* Allocate the URBs and buffers for receiving the audio stream */
1295:		if ((board->flags & GO7007_USB_EZUSB) &&
1296:		    (board->main_info.flags & GO7007_BOARD_HAS_AUDIO)) {
1297:			if (!usb->usbdev->ep_in[8])
1298:				goto allocfail;
1299:			for (i = 0; i < 8; ++i) {
1300:				usb->audio_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
1301:				if (usb->audio_urbs[i] == NULL)
1302:					goto allocfail;
1303:				usb->audio_urbs[i]->transfer_buffer = kmalloc(4096,
1304:									GFP_KERNEL);
1305:				if (usb->audio_urbs[i]->transfer_buffer == NULL)
1306:					goto allocfail;
1307:				usb_fill_bulk_urb(usb->audio_urbs[i], usb->usbdev,
1308:					usb_rcvbulkpipe(usb->usbdev, 8),
1309:					usb->audio_urbs[i]->transfer_buffer, 4096,
]

365/2 2026/07/30 13:18 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 53543
							output: 50
							thoughts: 55
						

Thoughts:
Here's my take on the thought process:

**Diving into the go7007 USB Probe Function**

Okay, so the `go7007_usb_probe` function is calling `i2c_add_adapter` under a specific condition. I need to understand that logic. The code says it's happening when `board->flags` has the `GO7007_USB_EZUSB_I2C` flag set. That's my starting point. Now I need to trace this back and see exactly *where* it's calling `i2c_add_adapter` in that conditional. Let's dig in and figure out the exact location and context of this call. Gotta get the full picture here.



366/2 2026/07/30 13:18 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:1130 LineCount:50]

Results:
map[Contents:1130:			go->hpi_ops = &go7007_usb_ezusb_hpi_ops;
1131:		else
1132:			go->hpi_ops = &go7007_usb_onboard_hpi_ops;
1133:		go->hpi_context = usb;
1134:	
1135:		ep = usb->usbdev->ep_in[4];
1136:		if (!ep)
1137:			goto allocfail;
1138:	
1139:		/* Allocate the URB and buffer for receiving incoming interrupts */
1140:		usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
1141:		if (usb->intr_urb == NULL)
1142:			goto allocfail;
1143:		usb->intr_urb->transfer_buffer = kmalloc_array(2, sizeof(u16),
1144:							       GFP_KERNEL);
1145:		if (usb->intr_urb->transfer_buffer == NULL)
1146:			goto allocfail;
1147:	
1148:		if (usb_endpoint_type(&ep->desc) == USB_ENDPOINT_XFER_BULK)
1149:			usb_fill_bulk_urb(usb->intr_urb, usb->usbdev,
1150:				usb_rcvbulkpipe(usb->usbdev, 4),
1151:				usb->intr_urb->transfer_buffer, 2*sizeof(u16),
1152:				go7007_usb_readinterrupt_complete, go);
1153:		else
1154:			usb_fill_int_urb(usb->intr_urb, usb->usbdev,
1155:				usb_rcvintpipe(usb->usbdev, 4),
1156:				usb->intr_urb->transfer_buffer, 2*sizeof(u16),
1157:				go7007_usb_readinterrupt_complete, go, 8);
1158:		usb_set_intfdata(intf, &go->v4l2_dev);
1159:	
1160:		/* Boot the GO7007 */
1161:		if (go7007_boot_encoder(go, go->board_info->flags &
1162:						GO7007_BOARD_USE_ONBOARD_I2C) < 0)
1163:			goto allocfail;
1164:	
1165:		/* Register the EZ-USB I2C adapter, if we're using it */
1166:		if (board->flags & GO7007_USB_EZUSB_I2C) {
1167:			memcpy(&go->i2c_adapter, &go7007_usb_adap_templ,
1168:					sizeof(go7007_usb_adap_templ));
1169:			mutex_init(&usb->i2c_lock);
1170:			go->i2c_adapter.dev.parent = go->dev;
1171:			i2c_set_adapdata(&go->i2c_adapter, go);
1172:			if (i2c_add_adapter(&go->i2c_adapter) < 0) {
1173:				dev_err(go->dev, "error: i2c_add_adapter failed\n");
1174:				goto allocfail;
1175:			}
1176:			go->i2c_adapter_online = 1;
1177:		}
1178:	
1179:		/* Pelco and Adlink reused the XMen and XMen-III vendor and product
]

367/2 2026/07/30 13:18 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 54786
							output: 28
							thoughts: 74
						

Thoughts:
Okay, here's my take on those thoughts, framed as my own mental processing:

**USB and I2C - Not Quite What I Expected**

Right, *that* bit of code, `board->flags & GO7007_USB_EZUSB_I2C`... ah, yes, I'm trying to figure out if we're dealing with a specific I2C configuration. Hang on a second... wait, isn't `XMEN` supposed to *not* have that `GO7007_USB_EZUSB_I2C` flag set? Something's not lining up. Okay, better double-check the board definitions. I need to quickly identify which boards *actually* use that particular configuration, just to be sure I haven't missed something fundamental in the setup. Let's see... back to the source...



368/2 2026/07/30 13:18 tool grepper
0m Args:
map[Expression:GO7007_USB_EZUSB_I2C]

Results:
map[Output:drivers/media/usb/go7007/go7007-usb.c=26=MODULE_PARM_DESC(assume_endura,
--
drivers/media/usb/go7007/go7007-usb.c-45-#define GO7007_USB_EZUSB		(1<<0)
drivers/media/usb/go7007/go7007-usb.c:46:#define GO7007_USB_EZUSB_I2C		(1<<1)
drivers/media/usb/go7007/go7007-usb.c-47-
--
drivers/media/usb/go7007/go7007-usb.c=141=static const struct go7007_usb_board board_star_trek = {
drivers/media/usb/go7007/go7007-usb.c:142:	.flags		= GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C,
drivers/media/usb/go7007/go7007-usb.c-143-	.main_info	= {
--
drivers/media/usb/go7007/go7007-usb.c=188=static const struct go7007_usb_board board_px_tv402u = {
drivers/media/usb/go7007/go7007-usb.c:189:	.flags		= GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C,
drivers/media/usb/go7007/go7007-usb.c-190-	.main_info	= {
--
drivers/media/usb/go7007/go7007-usb.c=418=static const struct go7007_usb_board board_sensoray_2250 = {
drivers/media/usb/go7007/go7007-usb.c:419:	.flags		= GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C,
drivers/media/usb/go7007/go7007-usb.c-420-	.main_info	= {
--
drivers/media/usb/go7007/go7007-usb.c=1040=static int go7007_usb_probe(struct usb_interface *intf,
--
drivers/media/usb/go7007/go7007-usb.c-1165-	/* Register the EZ-USB I2C adapter, if we're using it */
drivers/media/usb/go7007/go7007-usb.c:1166:	if (board->flags & GO7007_USB_EZUSB_I2C) {
drivers/media/usb/go7007/go7007-usb.c-1167-		memcpy(&go->i2c_adapter, &go7007_usb_adap_templ,
]

369/2 2026/07/30 13:18 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 55874
							output: 49
							thoughts: 727
						

Thoughts:
**The I2C Adapter Bug in GO7007 USB Drivers**

Okay, so I've spotted something interesting. `board_star_trek`, `board_px_tv402u`, and `board_sensoray_2250` all seem to utilize the `GO7007_USB_EZUSB_I2C` feature. Let's focus on `board_px_tv402u` for a closer look and reference the `go7007_usb_id_table`. Based on this, it looks like if we emulate the USB device IDs `0x093b:0xa104` with a `bcdDevice` value of `0x1`, the driver will associate it with `board_px_tv402u`.

Now, if we dive into the `go7007_usb_probe` function for `board_px_tv402u`, it's all starting to click. I see that if `GO7007_USB_EZUSB_I2C` is set, an I2C adapter is initialized and added. Crucially, the code then checks for the tuner model, specifically calling `go7007_usb_vendor_request`.

Aha! Here's the potential problem. If `go7007_usb_vendor_request` fails – let's say due to a missing response (more on that later) – the code jumps directly to `allocfail`. The critical detail is that `allocfail` frees the `go` structure *without* unregistering the I2C adapter!

This is it! It's a classic resource leak, a textbook example of an I2C adapter that's left dangling. And the culprit is right there, the vendor request.

The missing piece is `go7007_usb_vendor_request` itself, which, as I see it, sends a control message and expects a response. If no response is provided, it will, of course, fail. So, if we can reliably trigger a failure here, we can trigger the bug!



370/2 2026/07/30 13:19 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:850 LineCount:50]

Results:
map[Contents: 850:				goto audio_submit_failed;
 851:			}
 852:		}
 853:		return 0;
 854:	
 855:	audio_submit_failed:
 856:		for (i = 0; i < 7; ++i)
 857:			usb_kill_urb(usb->audio_urbs[i]);
 858:	video_submit_failed:
 859:		for (i = 0; i < 8; ++i)
 860:			usb_kill_urb(usb->video_urbs[i]);
 861:		return -1;
 862:	}
 863:	
 864:	static int go7007_usb_stream_stop(struct go7007 *go)
 865:	{
 866:		struct go7007_usb *usb = go->hpi_context;
 867:		int i;
 868:	
 869:		if (go->status == STATUS_SHUTDOWN)
 870:			return 0;
 871:		for (i = 0; i < 8; ++i)
 872:			usb_kill_urb(usb->video_urbs[i]);
 873:		if (go->audio_enabled)
 874:			for (i = 0; i < 8; ++i)
 875:				usb_kill_urb(usb->audio_urbs[i]);
 876:		return 0;
 877:	}
 878:	
 879:	static int go7007_usb_send_firmware(struct go7007 *go, u8 *data, int len)
 880:	{
 881:		struct go7007_usb *usb = go->hpi_context;
 882:		int transferred, pipe;
 883:		int timeout = 500;
 884:	
 885:		pr_debug("DownloadBuffer sending %d bytes\n", len);
 886:	
 887:		if (usb->board->flags & GO7007_USB_EZUSB)
 888:			pipe = usb_sndbulkpipe(usb->usbdev, 2);
 889:		else
 890:			pipe = usb_sndbulkpipe(usb->usbdev, 3);
 891:	
 892:		return usb_bulk_msg(usb->usbdev, pipe, data, len,
 893:						&transferred, timeout);
 894:	}
 895:	
 896:	static void go7007_usb_release(struct go7007 *go)
 897:	{
 898:		struct go7007_usb *usb = go->hpi_context;
 899:		struct urb *vurb, *aurb;
]

371/2 2026/07/30 13:19 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 57899
							output: 25
							thoughts: 21
						

Thoughts:
Here's my thought process, as requested:

**Navigating the Codebase**

Okay, so I'm digging into this code, trying to understand the flow, and I just noticed something that's making my brain itch. I was expecting `go7007_usb_vendor_request` to be somewhere, but I'm backtracking through the file. It looks like it's defined much earlier than I initially thought. This means I need to adjust my mental map of how the function calls are made within this section of code, and make sure that I understand how the early declaration impacts subsequent function calls. I should make sure I have the proper call order documented in my notes.



372/2 2026/07/30 13:19 tool grepper
0m Args:
map[Expression:go7007_usb_vendor_request]

Results:
map[Output:drivers/media/usb/go7007/go7007-usb.c=618=MODULE_DEVICE_TABLE(usb, go7007_usb_id_table);
--
drivers/media/usb/go7007/go7007-usb.c-621-
drivers/media/usb/go7007/go7007-usb.c:622:static int go7007_usb_vendor_request(struct go7007 *go, int request,
drivers/media/usb/go7007/go7007-usb.c-623-		int value, int index, void *transfer_buffer, int length, int in)
--
drivers/media/usb/go7007/go7007-usb.c=641=static int go7007_usb_interface_reset(struct go7007 *go)
--
drivers/media/usb/go7007/go7007-usb.c-655-		pr_debug("resetting EZ-USB buffers\n");
drivers/media/usb/go7007/go7007-usb.c:656:		if (go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0 ||
drivers/media/usb/go7007/go7007-usb.c:657:		    go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0)
drivers/media/usb/go7007/go7007-usb.c-658-			return -1;
--
drivers/media/usb/go7007/go7007-usb.c=949=static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter,
--
drivers/media/usb/go7007/go7007-usb.c-1001-		}
drivers/media/usb/go7007/go7007-usb.c:1002:		if (go7007_usb_vendor_request(go, 0x24, 0, 0,
drivers/media/usb/go7007/go7007-usb.c-1003-						buf, buf_len, 0) < 0)
--
drivers/media/usb/go7007/go7007-usb.c-1006-			memset(buf, 0, msgs[i].len + 1);
drivers/media/usb/go7007/go7007-usb.c:1007:			if (go7007_usb_vendor_request(go, 0x25, 0, 0, buf,
drivers/media/usb/go7007/go7007-usb.c-1008-						msgs[i].len + 1, 1) < 0)
--
drivers/media/usb/go7007/go7007-usb.c=1040=static int go7007_usb_probe(struct usb_interface *intf,
--
drivers/media/usb/go7007/go7007-usb.c-1224-		/* Board strapping indicates tuner model */
drivers/media/usb/go7007/go7007-usb.c:1225:		if (go7007_usb_vendor_request(go, 0x41, 0, 0, go->usb_buf, 3,
drivers/media/usb/go7007/go7007-usb.c-1226-					1) < 0) {
--
drivers/media/usb/go7007/go7007-usb.c-1255-		 * to the EZ-USB GPIO output pins */
drivers/media/usb/go7007/go7007-usb.c:1256:		if (go7007_usb_vendor_request(go, 0x40, 0x7f02, 0,
drivers/media/usb/go7007/go7007-usb.c-1257-					NULL, 0, 0) < 0) {
--
drivers/media/usb/go7007/s2250-board.c=125=static inline struct s2250 *to_state(struct v4l2_subdev *sd)
--
drivers/media/usb/go7007/s2250-board.c-130-/* from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/
drivers/media/usb/go7007/s2250-board.c:131:static int go7007_usb_vendor_request(struct go7007 *go, u16 request,
drivers/media/usb/go7007/s2250-board.c-132-	u16 value, u16 index, void *transfer_buffer, int length, int in)
--
drivers/media/usb/go7007/s2250-board.c=151=static int write_reg(struct i2c_client *client, u8 reg, u8 value)
--
drivers/media/usb/go7007/s2250-board.c-174-	}
drivers/media/usb/go7007/s2250-board.c:175:	rc = go7007_usb_vendor_request(go, 0x55, dev_addr,
drivers/media/usb/go7007/s2250-board.c-176-				       (reg<<8 | value),
--
drivers/media/usb/go7007/s2250-board.c=185=static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val)
--
drivers/media/usb/go7007/s2250-board.c-213-	}
drivers/media/usb/go7007/s2250-board.c:214:	rc = go7007_usb_vendor_request(go, 0x57, addr, val, buf, 16, 1);
drivers/media/usb/go7007/s2250-board.c-215-	mutex_unlock(&usb->i2c_lock);
--
drivers/media/usb/go7007/s2250-board.c=249=static int read_reg_fp(struct i2c_client *client, u16 addr, u16 *val)
--
drivers/media/usb/go7007/s2250-board.c-275-	}
drivers/media/usb/go7007/s2250-board.c:276:	rc = go7007_usb_vendor_request(go, 0x58, addr, 0, buf, 16, 1);
drivers/media/usb/go7007/s2250-board.c-277-	mutex_unlock(&usb->i2c_lock);
--
drivers/media/usb/go7007/s2250-board.c=497=static int s2250_probe(struct i2c_client *client)
--
drivers/media/usb/go7007/s2250-board.c-572-		if (data != NULL) {
drivers/media/usb/go7007/s2250-board.c:573:			int rc = go7007_usb_vendor_request(go, 0x41, 0, 0,
drivers/media/usb/go7007/s2250-board.c-574-						       data, 16, 1);
--
drivers/media/usb/go7007/s2250-board.c-582-				data[1] |= mask;
drivers/media/usb/go7007/s2250-board.c:583:				go7007_usb_vendor_request(go, 0x40, 0,
drivers/media/usb/go7007/s2250-board.c-584-							  (data[1]<<8)
]

373/2 2026/07/30 13:19 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 60292
							output: 49
							thoughts: 997
						

Thoughts:
**Analyzing the USB Vendor Request Vulnerability**

Okay, so I'm looking at this `go7007_usb_vendor_request` function, and it uses `usb_control_msg`. Right, that's standard for vendor-specific requests over USB control pipes. The key here is that if `usb_control_msg` doesn't get a proper response, it'll fail, returning a negative error code.

Now, I remember syzkaller's `syz_usb_connect` system call can inject responses through the `vusb_responses` struct. If we don't provide any responses, or the provided response indicates failure, that `go7007_usb_vendor_request` call will bomb out. Wait, even if the array is empty, which means no responses!

So, the trick to reproducing this is crafting a `syz_usb_connect` call and making sure it *doesn't* supply a valid response to the vendor request. Let's see... Vendor ID is `0x093b`, Product ID is `0xa104`. I'll need to construct the device descriptor and other descriptors, too.

Device descriptor is: `12 01 00 02 00 00 00 40 3b 09 04 a1 01 00 00 00 00 01`. Quick sanity check: `bcdDevice` should be `0x0001`, so `01 00`... looks good. Config descriptor: `09 02 22 00 01 01 00 80 00`. Interface descriptor: `09 04 00 00 03 ff 00 ff 00`.

Okay, next I need to look at the board flags. The `board_px_tv402u` has `GO7007_USB_EZUSB` flag, which is important because it is using `ep_in[6]` for video, `ep_in[8]` for audio, and `ep_in[4]` for interrupts. Actually, the code checks `ep_in[4]` first. If that endpoint is not provided it goes to `allocfail`, and the I2C adapter is NOT created!

If `ep_in[4]` is missing, the driver will go to `allocfail`. The `ep_in[4]` check happens *before* the I2C adapter registration with `i2c_add_adapter`. So we *must* provide `ep_in[4]` to avoid that. Same with the boot process of the encoder through `go7007_boot_encoder`! It is also called before the I2C adapter.

Let's check `go7007_boot_encoder`.



374/2 2026/07/30 13:19 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-driver.c FirstLine:120 LineCount:50]

Results:
map[Contents: 120:	
 121:	/*
 122:	 * Boot the encoder and register the I2C adapter if requested.  Do the
 123:	 * minimum initialization necessary, since the board-specific code may
 124:	 * still need to probe the board ID.
 125:	 *
 126:	 * Must NOT be called with the hw_lock held.
 127:	 */
 128:	int go7007_boot_encoder(struct go7007 *go, int init_i2c)
 129:	{
 130:		int ret;
 131:	
 132:		mutex_lock(&go->hw_lock);
 133:		ret = go7007_load_encoder(go);
 134:		mutex_unlock(&go->hw_lock);
 135:		if (ret < 0)
 136:			return -1;
 137:		if (!init_i2c)
 138:			return 0;
 139:		if (go7007_i2c_init(go) < 0)
 140:			return -1;
 141:		go->i2c_adapter_online = 1;
 142:		return 0;
 143:	}
 144:	EXPORT_SYMBOL(go7007_boot_encoder);
 145:	
 146:	/*
 147:	 * Configure any hardware-related registers in the GO7007, such as GPIO
 148:	 * pins and bus parameters, which are board-specific.  This assumes
 149:	 * the boot firmware has already been downloaded.
 150:	 *
 151:	 * Must be called with the hw_lock held.
 152:	 */
 153:	static int go7007_init_encoder(struct go7007 *go)
 154:	{
 155:		if (go->board_info->audio_flags & GO7007_AUDIO_I2S_MASTER) {
 156:			go7007_write_addr(go, 0x1000, 0x0811);
 157:			go7007_write_addr(go, 0x1000, 0x0c11);
 158:		}
 159:		switch (go->board_id) {
 160:		case GO7007_BOARDID_MATRIX_REV:
 161:			/* Set GPIO pin 0 to be an output (audio clock control) */
 162:			go7007_write_addr(go, 0x3c82, 0x0001);
 163:			go7007_write_addr(go, 0x3c80, 0x00fe);
 164:			break;
 165:		case GO7007_BOARDID_ADLINK_MPG24:
 166:			/* set GPIO5 to be an output, currently low */
 167:			go7007_write_addr(go, 0x3c82, 0x0000);
 168:			go7007_write_addr(go, 0x3c80, 0x00df);
 169:			break;
]

375/2 2026/07/30 13:19 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 62874
							output: 48
							thoughts: 25
						

Thoughts:
Here's my take on the thought process, as if it were my own:

**Connecting the Dots in the Encoding Process**

Okay, let me see... I'm tracing the execution flow of this encoder function, and something just clicked. I see that `go7007_boot_encoder` is calling `go7007_load_encoder`. Now, the implications of that are pretty clear in my mind. `go7007_boot_encoder` is acting as the entry point, the initialization stage, and it's *directly* leveraging `go7007_load_encoder`. That means `load_encoder` must be handling the critical low-level initialization. It is likely that `load_encoder` pulls in any critical settings such as the codec type, bitrate, and resolution settings that are likely required for correct execution. The boot function is probably just the wrapper function. It all makes logical sense, but having the pieces connected this quickly is satisfying. It suggests a well-structured and probably efficient workflow. This calls for a closer look at the interaction between these two functions – I need to dig into what data is passed between them and how the bootstrapping is handled. It could be some vital information about the setup of the internal encoder modules. This could be a good starting point for optimization or debugging, depending on what I find.



376/2 2026/07/30 13:19 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-driver.c FirstLine:60 LineCount:50]

Results:
map[Contents:  60:	
  61:		if (go7007_write_interrupt(go, 0x0010, addr) < 0)
  62:			return -EIO;
  63:		while (count-- > 0) {
  64:			if (go7007_read_interrupt(go, &value, data) == 0 &&
  65:					value == 0xa000)
  66:				return 0;
  67:		}
  68:		return -EIO;
  69:	}
  70:	EXPORT_SYMBOL(go7007_read_addr);
  71:	
  72:	/*
  73:	 * Send the boot firmware to the encoder, which just wakes it up and lets
  74:	 * us talk to the GPIO pins and on-board I2C adapter.
  75:	 *
  76:	 * Must be called with the hw_lock held.
  77:	 */
  78:	static int go7007_load_encoder(struct go7007 *go)
  79:	{
  80:		const struct firmware *fw_entry;
  81:		char fw_name[] = "go7007/go7007fw.bin";
  82:		void *bounce;
  83:		int fw_len;
  84:		u16 intr_val, intr_data;
  85:	
  86:		if (go->boot_fw == NULL) {
  87:			if (request_firmware(&fw_entry, fw_name, go->dev)) {
  88:				v4l2_err(go, "unable to load firmware from file \"%s\"\n", fw_name);
  89:				return -1;
  90:			}
  91:			if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) {
  92:				v4l2_err(go, "file \"%s\" does not appear to be go7007 firmware\n", fw_name);
  93:				release_firmware(fw_entry);
  94:				return -1;
  95:			}
  96:			fw_len = fw_entry->size - 16;
  97:			bounce = kmemdup(fw_entry->data + 16, fw_len, GFP_KERNEL);
  98:			if (bounce == NULL) {
  99:				v4l2_err(go, "unable to allocate %d bytes for firmware transfer\n", fw_len);
 100:				release_firmware(fw_entry);
 101:				return -1;
 102:			}
 103:			release_firmware(fw_entry);
 104:			go->boot_fw_len = fw_len;
 105:			go->boot_fw = bounce;
 106:		}
 107:		if (go7007_interface_reset(go) < 0 ||
 108:		    go7007_send_firmware(go, go->boot_fw, go->boot_fw_len) < 0 ||
 109:		    go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
]

377/2 2026/07/30 13:19 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 64106
							output: 50
							thoughts: 758
						

Thoughts:
**Debugging a Potential Use-After-Free in the GO7007 Driver**

Okay, let's break this down. It looks like `go7007_load_encoder` calls `request_firmware`, and if that fails, we get a `-1` and the whole probe function should short-circuit. Specifically, if `request_firmware` fails, then `go7007_boot_encoder` returns `-1`, and the probe goes to `allocfail` before `i2c_add_adapter` is even called, so no UAF.

However, the key is syzkaller. Because the firmware might not be present in the syzkaller environment, I initially thought the failure of `request_firmware` would be the common case. But the bug report is clear: we have a UAF, so `i2c_add_adapter` *was* called. How did that happen if the firmware wasn't loaded?

Hold on... maybe `go7007_boot_encoder` isn't the only entry point to `i2c_add_adapter`. Let's think about the `XMEN` board. It has `GO7007_BOARD_USE_ONBOARD_I2C`. If we use this board, then `go7007_boot_encoder` calls `go7007_i2c_init`. Looking at the code, if `init_i2c` is true, then we call `go7007_i2c_init`. In the XMEN case, this is `TRUE`!

Now, the important part: `go7007_boot_encoder` calls `go7007_load_encoder` *first*. If `go7007_load_encoder` fails due to a missing firmware, it returns before even calling `go7007_i2c_init`, and thus no `i2c_add_adapter`! So the UAF still shouldn't happen. The only place where `i2c_add_adapter` is called is in the `go7007_usb_probe` function.

I need to look for any other places in the driver where `i2c_add_adapter` is called. Let's start with `go7007_usb_probe` and its relationships with the `go7007_load_encoder` and `go7007_boot_encoder` functions, to check the sequence of calls.



378/2 2026/07/30 13:19 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:1150 LineCount:50]

Results:
map[Contents:1150:				usb_rcvbulkpipe(usb->usbdev, 4),
1151:				usb->intr_urb->transfer_buffer, 2*sizeof(u16),
1152:				go7007_usb_readinterrupt_complete, go);
1153:		else
1154:			usb_fill_int_urb(usb->intr_urb, usb->usbdev,
1155:				usb_rcvintpipe(usb->usbdev, 4),
1156:				usb->intr_urb->transfer_buffer, 2*sizeof(u16),
1157:				go7007_usb_readinterrupt_complete, go, 8);
1158:		usb_set_intfdata(intf, &go->v4l2_dev);
1159:	
1160:		/* Boot the GO7007 */
1161:		if (go7007_boot_encoder(go, go->board_info->flags &
1162:						GO7007_BOARD_USE_ONBOARD_I2C) < 0)
1163:			goto allocfail;
1164:	
1165:		/* Register the EZ-USB I2C adapter, if we're using it */
1166:		if (board->flags & GO7007_USB_EZUSB_I2C) {
1167:			memcpy(&go->i2c_adapter, &go7007_usb_adap_templ,
1168:					sizeof(go7007_usb_adap_templ));
1169:			mutex_init(&usb->i2c_lock);
1170:			go->i2c_adapter.dev.parent = go->dev;
1171:			i2c_set_adapdata(&go->i2c_adapter, go);
1172:			if (i2c_add_adapter(&go->i2c_adapter) < 0) {
1173:				dev_err(go->dev, "error: i2c_add_adapter failed\n");
1174:				goto allocfail;
1175:			}
1176:			go->i2c_adapter_online = 1;
1177:		}
1178:	
1179:		/* Pelco and Adlink reused the XMen and XMen-III vendor and product
1180:		 * IDs for their own incompatible designs.  We can detect XMen boards
1181:		 * by probing the sensor, but there is no way to probe the sensors on
1182:		 * the Pelco and Adlink designs so we default to the Adlink.  If it
1183:		 * is actually a Pelco, the user must set the assume_endura module
1184:		 * parameter. */
1185:		if ((go->board_id == GO7007_BOARDID_XMEN ||
1186:					go->board_id == GO7007_BOARDID_XMEN_III) &&
1187:				go->i2c_adapter_online) {
1188:			union i2c_smbus_data data;
1189:	
1190:			/* Check to see if register 0x0A is 0x76 */
1191:			i2c_smbus_xfer(&go->i2c_adapter, 0x21, I2C_CLIENT_SCCB,
1192:				I2C_SMBUS_READ, 0x0A, I2C_SMBUS_BYTE_DATA, &data);
1193:			if (data.byte != 0x76) {
1194:				if (assume_endura) {
1195:					go->board_id = GO7007_BOARDID_ENDURA;
1196:					usb->board = board = &board_endura;
1197:					go->board_info = &board->main_info;
1198:					strscpy(go->name, "Pelco Endura",
1199:						sizeof(go->name));
]

379/2 2026/07/30 13:19 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 66529
							output: 48
							thoughts: 785
						

Thoughts:
**Analyzing the Debug Output**

Okay, let's break this down. It looks like `go7007_boot_encoder` is consistently called *before* `i2c_add_adapter`, whether we're talking about the `EZUSB_I2C` or the `ONBOARD_I2C` scenario. And, crucially, `go7007_boot_encoder` ultimately calls `go7007_load_encoder`, which in turn, calls `request_firmware`. If that `request_firmware` fails, `go7007_boot_encoder` returns -1, and `go7007_usb_probe` bails out to `allocfail` BEFORE any I2C adapter is added. So how could `i2c_add_adapter` even be called if the firmware request bombed out?

That makes me think maybe `request_firmware` *succeeded* in loading the necessary firmware. The syzkaller images might have `go7007/go7007fw.bin` already present, avoiding that failure. I need to confirm this.

However, maybe it's *not* a `go7007` issue. Let's look at the bug report. Okay, the allocation trace points to `kmalloc-4k`. The call chain is interesting: `kobject_uevent_env` -> `device_add` -> `device_create` -> `mon_bin_add`. Is `mon_bin_add` doing the allocation? No, that's almost certainly a red herring. It's just a random allocation reusing that memory. What's allocated is actually a `struct au0828_dev` or `struct go7007`, or something else that's 4096 bytes.

Now, wait... isn't `struct au0828_dev` allocated with `kzalloc(sizeof(*dev), GFP_KERNEL)`? I should check `sizeof(struct au0828_dev)`...



380/2 2026/07/30 13:19 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828.h FirstLine:200 LineCount:100]

Results:
map[Contents: 200:	
 201:		struct video_device vdev;
 202:		struct video_device vbi_dev;
 203:	
 204:		/* Videobuf2 */
 205:		struct vb2_queue vb_vidq;
 206:		struct vb2_queue vb_vbiq;
 207:		struct mutex vb_queue_lock;
 208:		struct mutex vb_vbi_queue_lock;
 209:	
 210:		unsigned int frame_count;
 211:		unsigned int vbi_frame_count;
 212:	
 213:		struct timer_list vid_timeout;
 214:		int vid_timeout_running;
 215:		struct timer_list vbi_timeout;
 216:		int vbi_timeout_running;
 217:	
 218:		int users;
 219:		int streaming_users;
 220:	
 221:		int width;
 222:		int height;
 223:		int vbi_width;
 224:		int vbi_height;
 225:		u32 vbi_read;
 226:		v4l2_std_id std;
 227:		u32 field_size;
 228:		u32 frame_size;
 229:		u32 bytesperline;
 230:		int type;
 231:		u8 ctrl_ainput;
 232:		__u8 isoc_in_endpointaddr;
 233:		u8 isoc_init_ok;
 234:		int greenscreen_detected;
 235:		int ctrl_freq;
 236:		int input_type;
 237:		int std_set_in_tuner_core;
 238:		unsigned int ctrl_input;
 239:		long unsigned int dev_state; /* defined at enum au0828_dev_state */;
 240:		enum au0828_stream_state stream_state;
 241:		wait_queue_head_t open;
 242:	
 243:		struct mutex lock;
 244:	
 245:		/* Isoc control struct */
 246:		struct au0828_dmaqueue vidq;
 247:		struct au0828_dmaqueue vbiq;
 248:		struct au0828_usb_isoc_ctl isoc_ctl;
 249:		spinlock_t slock;
 250:	
 251:		/* usb transfer */
 252:		int alt;		/* alternate */
 253:		int max_pkt_size;	/* max packet size of isoc transaction */
 254:		int num_alt;		/* Number of alternative settings */
 255:		unsigned int *alt_max_pkt_size;	/* array of wMaxPacketSize */
 256:		struct urb *urb[AU0828_MAX_ISO_BUFS];	/* urb for isoc transfers */
 257:		char *transfer_buffer[AU0828_MAX_ISO_BUFS];/* transfer buffers for isoc
 258:							   transfer */
 259:	
 260:		/* DVB USB / URB Related */
 261:		bool		urb_streaming, need_urb_start;
 262:		struct urb	*urbs[URB_COUNT];
 263:	
 264:		/* Preallocated transfer digital transfer buffers */
 265:	
 266:		char *dig_transfer_buffer[URB_COUNT];
 267:	
 268:	#ifdef CONFIG_MEDIA_CONTROLLER
 269:		struct media_device *media_dev;
 270:		struct media_pad video_pad, vbi_pad;
 271:		struct media_entity *decoder;
 272:		struct media_entity input_ent[AU0828_MAX_INPUT];
 273:		struct media_pad input_pad[AU0828_MAX_INPUT];
 274:		struct media_entity_notify entity_notify;
 275:		struct media_entity *tuner;
 276:		struct media_link *active_link;
 277:		struct media_entity *active_source;
 278:		struct media_entity *active_sink;
 279:		struct media_entity *active_link_owner;
 280:		struct media_entity *active_link_user;
 281:		struct media_pipeline *active_link_user_pipe;
 282:		bool active_link_shared;
 283:	#endif
 284:	};
 285:	
 286:	
 287:	/* ----------------------------------------------------------- */
 288:	#define au0828_read(dev, reg) au0828_readreg(dev, reg)
 289:	#define au0828_write(dev, reg, value) au0828_writereg(dev, reg, value)
 290:	#define au0828_andor(dev, reg, mask, value)				\
 291:		 au0828_writereg(dev, reg,					\
 292:		(au0828_readreg(dev, reg) & ~(mask)) | ((value) & (mask)))
 293:	
 294:	#define au0828_set(dev, reg, bit) au0828_andor(dev, (reg), (bit), (bit))
 295:	#define au0828_clear(dev, reg, bit) au0828_andor(dev, (reg), (bit), 0)
 296:	
 297:	/* ----------------------------------------------------------- */
 298:	/* au0828-core.c */
 299:	extern u32 au0828_read(struct au0828_dev *dev, u16 reg);
]

381/2 2026/07/30 13:19 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 69438
							output: 49
							thoughts: 298
						

Thoughts:
**Analyzing Potential Resource Leak in `au0828` Driver**

Okay, so I'm looking at this `au0828` driver code, and first thought that jumps out at me is, *man, `struct au0828_dev` is huge*! Not unexpected, but still, a large struct is always a potential area for complexity and, as we're seeing, potential errors. But, wait, I already think I found a bug right here in `au0828_usb_disconnect`!

Looking closer, the function `au0828_usb_disconnect` is pretty standard for a USB driver's disconnect handler. It retrieves the `au0828_dev` structure associated with the interface, and then attempts to unregister the analog device. The interesting part is this: If `au0828_analog_unregister(dev)` returns a non-zero value, it bails out early using a `return` statement. Now, I have to remember the behavior of `au0828_analog_unregister`, which is likely to return 1 when `dev->users > 0`, to indicate that the device is still in use.

But here's the kicker: in the case where `au0828_analog_unregister` returns 1, the `au0828_usb_release(dev)` function is *not* called! Aha! The return in that conditional leads to a resource leak and a potential double-free.

So I need to confirm whether it is possible for `au0828_analog_unregister` to return 1 under a circumstance where the driver hasn't already handled resource release or unmapping. Could this be from an error path in probe? Let's check `au0828_usb_probe` to see if it correctly handles errors.



382/2 2026/07/30 13:20 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-core.c FirstLine:600 LineCount:50]

Results:
map[Contents: 600:		 * by video or audio. Note that this step can't be done until dvb
 601:		 * graph is created during dvb register.
 602:		*/
 603:		media_device_for_each_entity(entity, dev->media_dev) {
 604:			switch (entity->function) {
 605:			case MEDIA_ENT_F_TUNER:
 606:				dev->tuner = entity;
 607:				break;
 608:			case MEDIA_ENT_F_ATV_DECODER:
 609:				dev->decoder = entity;
 610:				break;
 611:			case MEDIA_ENT_F_DTV_DEMOD:
 612:				demod = entity;
 613:				break;
 614:			}
 615:		}
 616:	
 617:		/* Disable link between tuner->demod and/or tuner->decoder */
 618:		if (dev->tuner) {
 619:			list_for_each_entry(link, &dev->tuner->links, list) {
 620:				if (demod && link->sink->entity == demod)
 621:					media_entity_setup_link(link, 0);
 622:				if (dev->decoder && link->sink->entity == dev->decoder)
 623:					media_entity_setup_link(link, 0);
 624:			}
 625:		}
 626:	
 627:		/* register entity_notify callback */
 628:		dev->entity_notify.notify_data = (void *) dev;
 629:		dev->entity_notify.notify = (void *) au0828_media_graph_notify;
 630:		media_device_register_entity_notify(dev->media_dev,
 631:							  &dev->entity_notify);
 632:	
 633:		/* set enable_source */
 634:		mutex_lock(&dev->media_dev->graph_mutex);
 635:		dev->media_dev->source_priv = (void *) dev;
 636:		dev->media_dev->enable_source = au0828_enable_source;
 637:		dev->media_dev->disable_source = au0828_disable_source;
 638:		mutex_unlock(&dev->media_dev->graph_mutex);
 639:	#endif
 640:		return 0;
 641:	}
 642:	
 643:	static int au0828_usb_probe(struct usb_interface *interface,
 644:		const struct usb_device_id *id)
 645:	{
 646:		int ifnum;
 647:		int retval = 0;
 648:	
 649:		struct au0828_dev *dev;
]

383/2 2026/07/30 13:20 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 70983
							output: 50
							thoughts: 20
						

Thoughts:
Okay, here's my take on those thoughts, framed from a first-person perspective, assuming I'm deep in the weeds of understanding `au0828_usb_probe`:

**Digging Deeper into `au0828_usb_probe`**

Right, I'm at a critical juncture. My initial assessment of `au0828_usb_probe` isn't enough; I can't just skim the surface. I realize I've hit a point where I absolutely *must* have the complete picture. The partial snippet I have isn't cutting it; I need the rest of the function definition to really understand its flow, its dependencies, and what critical initializations or checks are being performed. Without that, I'm flying blind, and this could lead to major misunderstandings. I need to get my hands on the full context. I'm going to track down the full source code and pore over it.



384/2 2026/07/30 13:20 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-core.c FirstLine:650 LineCount:100]

Results:
map[Contents: 650:		struct usb_device *usbdev = interface_to_usbdev(interface);
 651:	
 652:		ifnum = interface->altsetting->desc.bInterfaceNumber;
 653:	
 654:		if (ifnum != 0)
 655:			return -ENODEV;
 656:	
 657:		dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__,
 658:			le16_to_cpu(usbdev->descriptor.idVendor),
 659:			le16_to_cpu(usbdev->descriptor.idProduct),
 660:			ifnum);
 661:	
 662:		/*
 663:		 * Make sure we have 480 Mbps of bandwidth, otherwise things like
 664:		 * video stream wouldn't likely work, since 12 Mbps is generally
 665:		 * not enough even for most Digital TV streams.
 666:		 */
 667:		if (usbdev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) {
 668:			pr_err("au0828: Device initialization failed.\n");
 669:			pr_err("au0828: Device must be connected to a high-speed USB 2.0 port.\n");
 670:			return -ENODEV;
 671:		}
 672:	
 673:		dev = kzalloc_obj(*dev);
 674:		if (dev == NULL) {
 675:			pr_err("%s() Unable to allocate memory\n", __func__);
 676:			return -ENOMEM;
 677:		}
 678:	
 679:		mutex_init(&dev->lock);
 680:		mutex_lock(&dev->lock);
 681:		mutex_init(&dev->mutex);
 682:		mutex_init(&dev->dvb.lock);
 683:		dev->usbdev = usbdev;
 684:		dev->boardnr = id->driver_info;
 685:		dev->board = au0828_boards[dev->boardnr];
 686:	
 687:		/* Initialize the media controller */
 688:		retval = au0828_media_device_init(dev, usbdev);
 689:		if (retval) {
 690:			pr_err("%s() au0828_media_device_init failed\n",
 691:			       __func__);
 692:			mutex_unlock(&dev->lock);
 693:			kfree(dev);
 694:			return retval;
 695:		}
 696:	
 697:		retval = au0828_v4l2_device_register(interface, dev);
 698:		if (retval) {
 699:			au0828_usb_v4l2_media_release(dev);
 700:			mutex_unlock(&dev->lock);
 701:			kfree(dev);
 702:			return retval;
 703:		}
 704:	
 705:		/* Power Up the bridge */
 706:		au0828_write(dev, REG_600, 1 << 4);
 707:	
 708:		/* Bring up the GPIO's and supporting devices */
 709:		au0828_gpio_setup(dev);
 710:	
 711:		/* I2C */
 712:		au0828_i2c_register(dev);
 713:	
 714:		/* Setup */
 715:		au0828_card_setup(dev);
 716:	
 717:		/*
 718:		 * Store the pointer to the au0828_dev so it can be accessed in
 719:		 * au0828_usb_disconnect
 720:		 */
 721:		usb_set_intfdata(interface, dev);
 722:	
 723:		/* Analog TV */
 724:		retval = au0828_analog_register(dev, interface);
 725:		if (retval) {
 726:			pr_err("%s() au0828_analog_register failed to register on V4L2\n",
 727:				__func__);
 728:			mutex_unlock(&dev->lock);
 729:			goto done;
 730:		}
 731:	
 732:		/* Digital TV */
 733:		retval = au0828_dvb_register(dev);
 734:		if (retval)
 735:			pr_err("%s() au0828_dvb_register failed\n",
 736:			       __func__);
 737:	
 738:		/* Remote controller */
 739:		au0828_rc_register(dev);
 740:	
 741:		pr_info("Registered device AU0828 [%s]\n",
 742:			dev->board.name == NULL ? "Unset" : dev->board.name);
 743:	
 744:		mutex_unlock(&dev->lock);
 745:	
 746:		retval = au0828_media_device_register(dev, usbdev);
 747:	
 748:	done:
 749:		if (retval < 0)
]

385/2 2026/07/30 13:20 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 72772
							output: 49
							thoughts: 174
						

Thoughts:
**Analyzing the au0828 Analog Registration Process**

Okay, so I'm looking at this code and immediately something jumps out at me: if `au0828_analog_register` fails, the execution jumps straight to `done`! That's... interesting. Why is it structured this way?

Let me follow the logic. Right after the `au0828_analog_register` call, we have a conditional check. If `retval` (the return value) indicates an error, an error message is printed and the mutex is unlocked. Makes sense, error handling. But then it *goes to* `done`.

And what happens at `done`? Aha! It calls `au0828_usb_disconnect` if the return value, `retval`, is negative. I need to understand that. So a failed registration results in attempting a disconnect. That's a key detail to note.

I'm getting a sense of the flow now. A failed analog registration triggers a cleanup sequence. It's a critical path. Now I've got to investigate `au0828_usb_disconnect` to figure out what kind of cleanup actions are performed and how they relate to the attempted analog registration.



386/2 2026/07/30 13:20 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-core.c FirstLine:750 LineCount:50]

Results:
map[Contents: 750:			au0828_usb_disconnect(interface);
 751:	
 752:		return retval;
 753:	}
 754:	
 755:	static int au0828_suspend(struct usb_interface *interface,
 756:					pm_message_t message)
 757:	{
 758:		struct au0828_dev *dev = usb_get_intfdata(interface);
 759:	
 760:		if (!dev)
 761:			return 0;
 762:	
 763:		pr_info("Suspend\n");
 764:	
 765:		au0828_rc_suspend(dev);
 766:		au0828_v4l2_suspend(dev);
 767:		au0828_dvb_suspend(dev);
 768:	
 769:		/* FIXME: should suspend also ATV/DTV */
 770:	
 771:		return 0;
 772:	}
 773:	
 774:	static int au0828_resume(struct usb_interface *interface)
 775:	{
 776:		struct au0828_dev *dev = usb_get_intfdata(interface);
 777:		if (!dev)
 778:			return 0;
 779:	
 780:		pr_info("Resume\n");
 781:	
 782:		/* Power Up the bridge */
 783:		au0828_write(dev, REG_600, 1 << 4);
 784:	
 785:		/* Bring up the GPIO's and supporting devices */
 786:		au0828_gpio_setup(dev);
 787:	
 788:		au0828_rc_resume(dev);
 789:		au0828_v4l2_resume(dev);
 790:		au0828_dvb_resume(dev);
 791:	
 792:		/* FIXME: should resume also ATV/DTV */
 793:	
 794:		return 0;
 795:	}
 796:	
 797:	static struct usb_driver au0828_usb_driver = {
 798:		.name		= KBUILD_MODNAME,
 799:		.probe		= au0828_usb_probe,
]

387/2 2026/07/30 13:20 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 73959
							output: 23
							thoughts: 19
						

Thoughts:
Here's my thought process, as if I were analyzing that code:

**Thinking Through the Disconnect Event**

Okay, so I'm digging through this log, looking at how the USB connection is handled. Hmm, `au0828_usb_disconnect`... I thought I'd seen that function earlier in the sequence. It's a bit jarring to see it referenced this late in the file, almost as if the disconnect process is an afterthought. I need to go back and double-check its initial declaration and usage within this context. I'm going to scan upward in the code; maybe I missed something significant the first time through. I need to understand the relationship between this disconnect function and the other USB-related calls – the timing is important. Is it getting called at the right point relative to the rest of the setup and data transfer? A disconnect being triggered too late could leave things in an undefined state. Gotta make sure it's cleaning up resources properly.



388/2 2026/07/30 13:20 tool grepper
0m Args:
map[Expression:au0828_usb_disconnect]

Results:
map[Output:drivers/media/usb/au0828/au0828-core.c=153=void au0828_usb_release(struct au0828_dev *dev)
--
drivers/media/usb/au0828/au0828-core.c-162-
drivers/media/usb/au0828/au0828-core.c:163:static void au0828_usb_disconnect(struct usb_interface *interface)
drivers/media/usb/au0828/au0828-core.c-164-{
--
drivers/media/usb/au0828/au0828-core.c=643=static int au0828_usb_probe(struct usb_interface *interface,
--
drivers/media/usb/au0828/au0828-core.c-718-	 * Store the pointer to the au0828_dev so it can be accessed in
drivers/media/usb/au0828/au0828-core.c:719:	 * au0828_usb_disconnect
drivers/media/usb/au0828/au0828-core.c-720-	 */
--
drivers/media/usb/au0828/au0828-core.c-749-	if (retval < 0)
drivers/media/usb/au0828/au0828-core.c:750:		au0828_usb_disconnect(interface);
drivers/media/usb/au0828/au0828-core.c-751-
--
drivers/media/usb/au0828/au0828-core.c=797=static struct usb_driver au0828_usb_driver = {
--
drivers/media/usb/au0828/au0828-core.c-799-	.probe		= au0828_usb_probe,
drivers/media/usb/au0828/au0828-core.c:800:	.disconnect	= au0828_usb_disconnect,
drivers/media/usb/au0828/au0828-core.c-801-	.id_table	= au0828_usb_id_table,
]

389/2 2026/07/30 13:20 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 74814
							output: 49
							thoughts: 15
						

Thoughts:
Okay, here we go...

**Diving into au0828_usb_disconnect**

Alright, let's get down to brass tacks. The prompt says "Let's read `au0828_usb_disconnect`". So, my immediate thought is, "Okay, another delve into a USB disconnect function. Given my experience, I'm expecting this is going to be a crucial piece of the driver, the linchpin that gracefully handles the removal of a USB device associated with the au0828, which I know is a popular USB device often used for video capture. I'm already anticipating the nuances of resource management that I'll need to dissect – deallocating buffers, resetting hardware, and ensuring that no race conditions arise in the driver with other threads. "

"I need to understand this disconnect procedure completely. Was this written to handle hot-plug removal? How robust is this code? Is it a bare-bones implementation, or does it incorporate sophisticated error handling and state management? I need to look for typical USB disconnection steps: issuing an `usb_kill_urb`, cancelling pending transfers, releasing any claimed USB interfaces, and potentially resetting hardware components related to the au0828. I also want to make sure the right cleanup happens, like properly shutting down the video stream and releasing all the resources so the system isn't left in a bad state."

"I hope this code doesn't leave any dangling pointers, unreleased mutexes, or orphaned memory allocations. My goal is to ensure this disconnect routine is bulletproof and doesn't introduce any instability into the system. It would also be good to think about the situation where the user unplugs the USB cable while the device is in the middle of operation. I need to keep that kind of situation in mind."



390/2 2026/07/30 13:20 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-core.c FirstLine:160 LineCount:50]

Results:
map[Contents: 160:		kfree(dev);
 161:	}
 162:	
 163:	static void au0828_usb_disconnect(struct usb_interface *interface)
 164:	{
 165:		struct au0828_dev *dev = usb_get_intfdata(interface);
 166:	
 167:		dprintk(1, "%s()\n", __func__);
 168:	
 169:		/* there is a small window after disconnect, before
 170:		   dev->usbdev is NULL, for poll (e.g: IR) try to access
 171:		   the device and fill the dmesg with error messages.
 172:		   Set the status so poll routines can check and avoid
 173:		   access after disconnect.
 174:		*/
 175:		set_bit(DEV_DISCONNECTED, &dev->dev_state);
 176:	
 177:		au0828_rc_unregister(dev);
 178:		/* Digital TV */
 179:		au0828_dvb_unregister(dev);
 180:	
 181:		usb_set_intfdata(interface, NULL);
 182:		mutex_lock(&dev->mutex);
 183:		dev->usbdev = NULL;
 184:		mutex_unlock(&dev->mutex);
 185:		if (au0828_analog_unregister(dev)) {
 186:			/*
 187:			 * No need to call au0828_usb_release() if V4L2 is enabled,
 188:			 * as this is already called via au0828_usb_v4l2_release()
 189:			 */
 190:			return;
 191:		}
 192:		au0828_usb_release(dev);
 193:	}
 194:	
 195:	static int au0828_media_device_init(struct au0828_dev *dev,
 196:					    struct usb_device *udev)
 197:	{
 198:	#ifdef CONFIG_MEDIA_CONTROLLER
 199:		struct media_device *mdev;
 200:	
 201:		mdev = media_device_usb_allocate(udev, KBUILD_MODNAME, THIS_MODULE);
 202:		if (IS_ERR(mdev))
 203:			return PTR_ERR(mdev);
 204:	
 205:		dev->media_dev = mdev;
 206:	#endif
 207:		return 0;
 208:	}
 209:	
]

391/2 2026/07/30 13:20 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 76003
							output: 50
							thoughts: 23
						

Thoughts:
Here's my thought process, summarized as you requested:

**Deconstructing `au0828_analog_unregister`**

Okay, hold on a minute. I just saw that `au0828_analog_unregister` is returning an `int`. That's interesting. I need to understand what this return value signifies. Is it an error code? A success indicator? What are the possible values and what do they represent? I should immediately dive into the code and relevant documentation to verify how this function is intended to be used and what interpretations of the return value are. I'm going to track the function definition and implementation to understand potential error conditions or states.



392/2 2026/07/30 13:20 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-video.c FirstLine:1860 LineCount:50]

Results:
map[Contents:1860:			[AU0828_VMUX_COMPOSITE] = "Composite",
1861:			[AU0828_VMUX_SVIDEO] = "S-Video",
1862:			[AU0828_VMUX_CABLE] = "Cable TV",
1863:			[AU0828_VMUX_TELEVISION] = "Television",
1864:			[AU0828_VMUX_DVB] = "DVB",
1865:		};
1866:		int ret, i;
1867:	
1868:		/* Initialize Video and VBI pads */
1869:		dev->video_pad.flags = MEDIA_PAD_FL_SINK;
1870:		ret = media_entity_pads_init(&dev->vdev.entity, 1, &dev->video_pad);
1871:		if (ret < 0)
1872:			pr_err("failed to initialize video media entity!\n");
1873:	
1874:		dev->vbi_pad.flags = MEDIA_PAD_FL_SINK;
1875:		ret = media_entity_pads_init(&dev->vbi_dev.entity, 1, &dev->vbi_pad);
1876:		if (ret < 0)
1877:			pr_err("failed to initialize vbi media entity!\n");
1878:	
1879:		/* Create entities for each input connector */
1880:		for (i = 0; i < AU0828_MAX_INPUT; i++) {
1881:			struct media_entity *ent = &dev->input_ent[i];
1882:	
1883:			if (AUVI_INPUT(i).type == AU0828_VMUX_UNDEFINED)
1884:				break;
1885:	
1886:			ent->name = inames[AUVI_INPUT(i).type];
1887:			ent->flags = MEDIA_ENT_FL_CONNECTOR;
1888:			dev->input_pad[i].flags = MEDIA_PAD_FL_SOURCE;
1889:	
1890:			switch (AUVI_INPUT(i).type) {
1891:			case AU0828_VMUX_COMPOSITE:
1892:				ent->function = MEDIA_ENT_F_CONN_COMPOSITE;
1893:				break;
1894:			case AU0828_VMUX_SVIDEO:
1895:				ent->function = MEDIA_ENT_F_CONN_SVIDEO;
1896:				break;
1897:			case AU0828_VMUX_CABLE:
1898:			case AU0828_VMUX_TELEVISION:
1899:			case AU0828_VMUX_DVB:
1900:			default: /* Just to shut up a warning */
1901:				ent->function = MEDIA_ENT_F_CONN_RF;
1902:				break;
1903:			}
1904:	
1905:			ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]);
1906:			if (ret < 0)
1907:				pr_err("failed to initialize input pad[%d]!\n", i);
1908:	
1909:			ret = media_device_register_entity(dev->media_dev, ent);
]

393/2 2026/07/30 13:20 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 77142
							output: 23
							thoughts: 17
						

Thoughts:
Okay, let's see. My mind's buzzing – I've hit a snag. The key function I need right now is `au0828_analog_unregister`. This is what I'm focusing on; it's the one that's crucial to the next step. Where is this function defined? Need to track it down. Gotta remember its purpose and ensure it's handled the right way. This is essential to continue. Right, search... search...



394/2 2026/07/30 13:20 tool grepper
0m Args:
map[Expression:au0828_analog_unregister]

Results:
map[Output:drivers/media/usb/au0828/au0828-core.c=163=static void au0828_usb_disconnect(struct usb_interface *interface)
--
drivers/media/usb/au0828/au0828-core.c-184-	mutex_unlock(&dev->mutex);
drivers/media/usb/au0828/au0828-core.c:185:	if (au0828_analog_unregister(dev)) {
drivers/media/usb/au0828/au0828-core.c-186-		/*
--
drivers/media/usb/au0828/au0828-video.c=911=static const struct vb2_ops au0828_video_qops = {
--
drivers/media/usb/au0828/au0828-video.c-923-/*
drivers/media/usb/au0828/au0828-video.c:924: * au0828_analog_unregister
drivers/media/usb/au0828/au0828-video.c-925- * unregister v4l2 devices
drivers/media/usb/au0828/au0828-video.c-926- */
drivers/media/usb/au0828/au0828-video.c:927:int au0828_analog_unregister(struct au0828_dev *dev)
drivers/media/usb/au0828/au0828-video.c-928-{
drivers/media/usb/au0828/au0828-video.c:929:	dprintk(1, "au0828_analog_unregister called\n");
drivers/media/usb/au0828/au0828-video.c-930-
--
drivers/media/usb/au0828/au0828.h=327=extern int au0828_analog_register(struct au0828_dev *dev,
drivers/media/usb/au0828/au0828.h-328-			   struct usb_interface *interface);
drivers/media/usb/au0828/au0828.h:329:extern int au0828_analog_unregister(struct au0828_dev *dev);
drivers/media/usb/au0828/au0828.h-330-extern void au0828_usb_v4l2_media_release(struct au0828_dev *dev);
--
drivers/media/usb/au0828/au0828.h=337=static inline int au0828_analog_register(struct au0828_dev *dev,
--
drivers/media/usb/au0828/au0828.h-339-{ return 0; };
drivers/media/usb/au0828/au0828.h:340:static inline int au0828_analog_unregister(struct au0828_dev *dev)
drivers/media/usb/au0828/au0828.h-341-{ return 0; };
]

395/2 2026/07/30 13:20 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 78128
							output: 49
							thoughts: 15
						

Thoughts:
Okay, here's my take on those thoughts, tailored for an expert audience:

**Analyzing the `au0828_analog_unregister` Function**

Alright, let's dive into the `au0828_analog_unregister` function. My initial thought process here is to quickly understand its role in the overall driver architecture for the AU0828 analog capture device. Since this is an unregister function, I'm expecting it to perform cleanup tasks related to device removal or driver unloading. I need to figure out the specific resources being managed and freed within this routine. I'll be looking for things like:

*   **Resource De-allocation:** Are we releasing memory allocated for buffers, structures (e.g., control structures, DMA descriptors, I/O registers), or internal data? If so, what mechanisms are used (kfree, vfree, etc.)? Any potential memory leaks?
*   **Hardware Control:** Are there any hardware-specific operations related to the analog capture chip that need to be reversed or disabled? Think about clock gating, power management (putting the chip into a low-power state or turning it off), and disabling any DMA channels used for capturing video/audio data. What are the register accesses and the side effects?
*   **Driver State Management:** Does the function update any internal driver state variables (e.g., setting flags to indicate the device is no longer active, resetting counters, etc.)? This is critical for preventing further operations on a device that's being un-registered.
*   **Interrupt Handling:** Are we disabling any associated interrupt handlers or cleaning up interrupt-related resources? Incorrect interrupt handling de-registration can lead to system instability or crashes.
*   **Error Handling:** What kind of error checking is implemented, and how is it done? Do the checks include handling of potential errors that may result from incorrect sequencing during driver unregistration (e.g., the device being active during an unregister operation)?
*   **Concurrency:** If the driver supports multiple instances or threads, are there any synchronization primitives (e.g., mutexes, spinlocks) used to protect shared resources during unregistration? Failure to handle concurrency correctly can cause race conditions and unpredictable behavior.
*  **Device tree/platform data cleanup:** Is the device tree or platform data resources for this device correctly cleaned up?

I'll be paying close attention to any calls to other driver functions or kernel APIs, as these will likely provide further clues about the unregistration process. I'll scrutinize the call sequence to ensure that operations are performed in the correct order, avoiding potential deadlocks or resource conflicts. I'm also looking for any potential for resource leaks, errors in the unregistration procedure that could impact the stability of the system. I'll expect good use of `devm_xxx` functions for managed resources, but I'll double-check it.



396/2 2026/07/30 13:20 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-video.c FirstLine:920 LineCount:50]

Results:
map[Contents: 920:	/* ------------------------------------------------------------------
 921:	   V4L2 interface
 922:	   ------------------------------------------------------------------*/
 923:	/*
 924:	 * au0828_analog_unregister
 925:	 * unregister v4l2 devices
 926:	 */
 927:	int au0828_analog_unregister(struct au0828_dev *dev)
 928:	{
 929:		dprintk(1, "au0828_analog_unregister called\n");
 930:	
 931:		/* No analog TV */
 932:		if (AUVI_INPUT(0).type == AU0828_VMUX_UNDEFINED)
 933:			return 0;
 934:	
 935:		mutex_lock(&au0828_sysfs_lock);
 936:		vb2_video_unregister_device(&dev->vdev);
 937:		vb2_video_unregister_device(&dev->vbi_dev);
 938:		mutex_unlock(&au0828_sysfs_lock);
 939:	
 940:		v4l2_device_disconnect(&dev->v4l2_dev);
 941:		v4l2_device_put(&dev->v4l2_dev);
 942:	
 943:		return 1;
 944:	}
 945:	
 946:	/* This function ensures that video frames continue to be delivered even if
 947:	   the ITU-656 input isn't receiving any data (thereby preventing applications
 948:	   such as tvtime from hanging) */
 949:	static void au0828_vid_buffer_timeout(struct timer_list *t)
 950:	{
 951:		struct au0828_dev *dev = timer_container_of(dev, t, vid_timeout);
 952:		struct au0828_dmaqueue *dma_q = &dev->vidq;
 953:		struct au0828_buffer *buf;
 954:		unsigned char *vid_data;
 955:		unsigned long flags = 0;
 956:	
 957:		spin_lock_irqsave(&dev->slock, flags);
 958:	
 959:		buf = dev->isoc_ctl.buf;
 960:		if (buf != NULL) {
 961:			vid_data = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
 962:			memset(vid_data, 0x00, buf->length); /* Blank green frame */
 963:			buffer_filled(dev, dma_q, buf);
 964:		}
 965:		get_next_buf(dma_q, &buf);
 966:	
 967:		if (dev->vid_timeout_running == 1)
 968:			mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
 969:	
]

397/2 2026/07/30 13:20 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 79650
							output: 28
							thoughts: 250
						

Thoughts:
**Analyzing the Resource Cleanup in `au0828` Driver**

Okay, so I'm looking at this cleanup code for the `au0828` driver. My initial thought is that there's a potential issue with how resources are being released during disconnection. Specifically, I'm focusing on this `au0828_analog_unregister` function. Hang on, it returns `1` if the input type isn't undefined. Alright, and the logic here is that if `au0828_analog_unregister` returns `1`, then `au0828_usb_disconnect` exits early, skipping a call to `au0828_usb_release(dev)`.

The concern is, if we bail out early, we *don't* call `au0828_usb_release(dev)`. So, who's responsible for freeing those resources? The comment says that if V4L2 is enabled, the cleanup is handled by `au0828_usb_v4l2_release()`. So, the implication is that `au0828_usb_v4l2_release` is taking care of cleanup in that case. That's fine, but I need to make sure I understand the conditional logic completely. Let's go check the source for `au0828_usb_v4l2_release` to confirm that's the correct behavior.



398/2 2026/07/30 13:20 tool grepper
0m Args:
map[Expression:au0828_usb_v4l2_release]

Results:
map[Output:drivers/media/usb/au0828/au0828-core.c=163=static void au0828_usb_disconnect(struct usb_interface *interface)
--
drivers/media/usb/au0828/au0828-core.c-187-		 * No need to call au0828_usb_release() if V4L2 is enabled,
drivers/media/usb/au0828/au0828-core.c:188:		 * as this is already called via au0828_usb_v4l2_release()
drivers/media/usb/au0828/au0828-core.c-189-		 */
--
drivers/media/usb/au0828/au0828-video.c=622=void au0828_usb_v4l2_media_release(struct au0828_dev *dev)
--
drivers/media/usb/au0828/au0828-video.c-634-
drivers/media/usb/au0828/au0828-video.c:635:static void au0828_usb_v4l2_release(struct v4l2_device *v4l2_dev)
drivers/media/usb/au0828/au0828-video.c-636-{
--
drivers/media/usb/au0828/au0828-video.c=646=int au0828_v4l2_device_register(struct usb_interface *interface,
--
drivers/media/usb/au0828/au0828-video.c-664-
drivers/media/usb/au0828/au0828-video.c:665:	dev->v4l2_dev.release = au0828_usb_v4l2_release;
drivers/media/usb/au0828/au0828-video.c-666-
]

399/2 2026/07/30 13:20 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 80766
							output: 49
							thoughts: 126
						

Thoughts:
**Analyzing the USB Video Device Release Sequence**

Okay, so I've got it. `au0828_usb_v4l2_release` is *definitely* the `release` callback associated with the `v4l2_dev` structure. That makes things a bit clearer. And looking at `au0828_analog_unregister`, I can see that it's calling `v4l2_device_put(&dev->v4l2_dev)`. This is key.

Now, if `v4l2_device_put` decrements the reference count and happens to drop the *last* reference to the `v4l2_dev` structure, then it's going to trigger that `au0828_usb_v4l2_release` function. That's the expected behavior, and it makes sense. It's the standard resource cleanup.

Time to confirm my understanding. I'm going to take a closer look at `au0828_usb_v4l2_release` itself and make absolutely sure everything checks out. Gotta verify it's doing what I *think* it's doing.



400/2 2026/07/30 13:21 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-video.c FirstLine:630 LineCount:50]

Results:
map[Contents: 630:			media_device_unregister_entity(&dev->input_ent[i]);
 631:		}
 632:	#endif
 633:	}
 634:	
 635:	static void au0828_usb_v4l2_release(struct v4l2_device *v4l2_dev)
 636:	{
 637:		struct au0828_dev *dev =
 638:			container_of(v4l2_dev, struct au0828_dev, v4l2_dev);
 639:	
 640:		v4l2_ctrl_handler_free(&dev->v4l2_ctrl_hdl);
 641:		v4l2_device_unregister(&dev->v4l2_dev);
 642:		au0828_usb_v4l2_media_release(dev);
 643:		au0828_usb_release(dev);
 644:	}
 645:	
 646:	int au0828_v4l2_device_register(struct usb_interface *interface,
 647:					struct au0828_dev *dev)
 648:	{
 649:		int retval;
 650:	
 651:		if (AUVI_INPUT(0).type == AU0828_VMUX_UNDEFINED)
 652:			return 0;
 653:	
 654:		/* Create the v4l2_device */
 655:	#ifdef CONFIG_MEDIA_CONTROLLER
 656:		dev->v4l2_dev.mdev = dev->media_dev;
 657:	#endif
 658:		retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
 659:		if (retval) {
 660:			pr_err("%s() v4l2_device_register failed\n",
 661:			       __func__);
 662:			return retval;
 663:		}
 664:	
 665:		dev->v4l2_dev.release = au0828_usb_v4l2_release;
 666:	
 667:		/* This control handler will inherit the controls from au8522 */
 668:		retval = v4l2_ctrl_handler_init(&dev->v4l2_ctrl_hdl, 4);
 669:		if (retval) {
 670:			pr_err("%s() v4l2_ctrl_handler_init failed\n",
 671:			       __func__);
 672:			return retval;
 673:		}
 674:		dev->v4l2_dev.ctrl_handler = &dev->v4l2_ctrl_hdl;
 675:	
 676:		return 0;
 677:	}
 678:	
 679:	static int queue_setup(struct vb2_queue *vq,
]

401/2 2026/07/30 13:21 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 82030
							output: 49
							thoughts: 69
						

Thoughts:
Here's my take on the situation:

**Investigating a Potential Double Free in the `au0828` Driver**

Okay, hold on a second. I'm looking at this `au0828_usb_v4l2_release` function, and it seems like it calls `au0828_usb_release(dev)`. That's the first red flag. And... damn, `au0828_usb_release(dev)` *frees* the `dev` structure. That's a huge potential problem. If `dev` gets freed multiple times, we're talking about a nasty double-free vulnerability, which is always a nightmare. This smells like a classic memory management bug. I need to make absolutely sure that this `dev` pointer isn't being used anywhere else *after* this call. Let's dig deeper into the code, and examine the `au0828_usb_release` function to be certain.



402/2 2026/07/30 13:21 tool read-file
0m Args:
map[File:drivers/media/usb/au0828/au0828-core.c FirstLine:140 LineCount:50]

Results:
map[Contents: 140:	
 141:		/* clear enable_source, disable_source */
 142:		mutex_lock(&mdev->graph_mutex);
 143:		dev->media_dev->source_priv = NULL;
 144:		dev->media_dev->enable_source = NULL;
 145:		dev->media_dev->disable_source = NULL;
 146:		mutex_unlock(&mdev->graph_mutex);
 147:	
 148:		media_device_delete(dev->media_dev, KBUILD_MODNAME, THIS_MODULE);
 149:		dev->media_dev = NULL;
 150:	#endif
 151:	}
 152:	
 153:	void au0828_usb_release(struct au0828_dev *dev)
 154:	{
 155:		au0828_unregister_media_device(dev);
 156:	
 157:		/* I2C */
 158:		au0828_i2c_unregister(dev);
 159:	
 160:		kfree(dev);
 161:	}
 162:	
 163:	static void au0828_usb_disconnect(struct usb_interface *interface)
 164:	{
 165:		struct au0828_dev *dev = usb_get_intfdata(interface);
 166:	
 167:		dprintk(1, "%s()\n", __func__);
 168:	
 169:		/* there is a small window after disconnect, before
 170:		   dev->usbdev is NULL, for poll (e.g: IR) try to access
 171:		   the device and fill the dmesg with error messages.
 172:		   Set the status so poll routines can check and avoid
 173:		   access after disconnect.
 174:		*/
 175:		set_bit(DEV_DISCONNECTED, &dev->dev_state);
 176:	
 177:		au0828_rc_unregister(dev);
 178:		/* Digital TV */
 179:		au0828_dvb_unregister(dev);
 180:	
 181:		usb_set_intfdata(interface, NULL);
 182:		mutex_lock(&dev->mutex);
 183:		dev->usbdev = NULL;
 184:		mutex_unlock(&dev->mutex);
 185:		if (au0828_analog_unregister(dev)) {
 186:			/*
 187:			 * No need to call au0828_usb_release() if V4L2 is enabled,
 188:			 * as this is already called via au0828_usb_v4l2_release()
 189:			 */
]

403/2 2026/07/30 13:21 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 83140
							output: 49
							thoughts: 1582
						

Thoughts:
**Analyzing the I2C Adapter Unregistration in `au0828` and `go7007` Drivers**

Okay, first things first, the `au0828` driver. I thought I had a problem there, but let's see. The `au0828_usb_release` function explicitly calls `au0828_i2c_unregister(dev)` *before* freeing the device structure. So, the I2C adapter is properly unregistered in `au0828`. This driver is *not* the source of my potential UAF. Now, I have to go back and check `go7007`.

Right, let's look again at the `go7007` driver. In `go7007_usb_release`, there's no call to `i2c_del_adapter`. That's a red flag. The `go7007_usb_probe` does register the I2C adapter with `i2c_add_adapter` if the board flags indicate it's using the EZ-USB I2C adapter. If the probe fails *after* this point, it jumps to `allocfail`. At `allocfail`, `go7007_usb_release` is called, and `go` is freed with `kfree(go)`. The I2C adapter *remains* registered. Bingo! That confirms it: this is definitely a Use-After-Free vulnerability.

But there's something else. How does the code reach `i2c_add_adapter` if the firmware loading fails? I need to check `go7007_boot_encoder` to see what causes it to return an error. The `go7007_boot_encoder` function calls `go7007_load_encoder`. Ah, `go7007_load_encoder` uses `request_firmware` to load `go7007/go7007fw.bin`. The vulnerability report could have included the firmware and the `request_firmware` could have succeeded, which would lead to I2C being registered! This is where syzkaller comes into the picture. Syzkaller images often include the `linux-firmware` package. So, it's very likely that `request_firmware` succeeds.

If `request_firmware` succeeds, then the code will continue. Specifically, the following lines:
```
	if (go7007_interface_reset(go) < 0 ||
	    go7007_send_firmware(go, go->boot_fw, go->boot_fw_len) < 0 ||
	    go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
	    (intr_val & ~0x1) != 0x55aa) {
		v4l2_err(go, "fatal error initializing GO7007\n");
		return -1;
	}
```
are executed.

If all those functions succeed, the `i2c_add_adapter` will be called. Specifically, `go7007_interface_reset` does a vendor request. This *must* succeed for the code to continue. So, if we provide a stub for the vendor request made by `go7007_interface_reset`, the `go7007_load_encoder` *will* succeed and `allocfail` will *not* be hit before `i2c_add_adapter`. If `allocfail` isn't hit before `i2c_add_adapter`, there is NO UAF. I now know what vendor requests are made in `go7007_load_encoder`.



404/2 2026/07/30 13:21 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:640 LineCount:50]

Results:
map[Contents: 640:	
 641:	static int go7007_usb_interface_reset(struct go7007 *go)
 642:	{
 643:		struct go7007_usb *usb = go->hpi_context;
 644:		u16 intr_val, intr_data;
 645:	
 646:		if (go->status == STATUS_SHUTDOWN)
 647:			return -1;
 648:		/* Reset encoder */
 649:		if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0)
 650:			return -1;
 651:		msleep(100);
 652:	
 653:		if (usb->board->flags & GO7007_USB_EZUSB) {
 654:			/* Reset buffer in EZ-USB */
 655:			pr_debug("resetting EZ-USB buffers\n");
 656:			if (go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0 ||
 657:			    go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0)
 658:				return -1;
 659:	
 660:			/* Reset encoder again */
 661:			if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0)
 662:				return -1;
 663:			msleep(100);
 664:		}
 665:	
 666:		/* Wait for an interrupt to indicate successful hardware reset */
 667:		if (go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
 668:				(intr_val & ~0x1) != 0x55aa) {
 669:			dev_err(go->dev, "unable to reset the USB interface\n");
 670:			return -1;
 671:		}
 672:		return 0;
 673:	}
 674:	
 675:	static int go7007_usb_ezusb_write_interrupt(struct go7007 *go,
 676:							int addr, int data)
 677:	{
 678:		struct go7007_usb *usb = go->hpi_context;
 679:		int i, r;
 680:		u16 status_reg = 0;
 681:		int timeout = 500;
 682:	
 683:		pr_debug("WriteInterrupt: %04x %04x\n", addr, data);
 684:	
 685:		for (i = 0; i < 100; ++i) {
 686:			r = usb_control_msg(usb->usbdev,
 687:					usb_rcvctrlpipe(usb->usbdev, 0), 0x14,
 688:					USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
 689:					0, HPI_STATUS_ADDR, go->usb_buf,
]

405/2 2026/07/30 13:21 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 86529
							output: 49
							thoughts: 614
						

Thoughts:
**Analyzing the go7007 USB Interrupt Write Process**

Okay, let's break this down. My initial observation is that `go7007_write_interrupt` calls `go7007_usb_ezusb_write_interrupt`.  That's the core function we need to examine. Looking at `go7007_usb_ezusb_write_interrupt`, I see a clear sequence. First, it enters a loop, up to 100 iterations. Inside this loop, it issues a USB control message – a vendor request `0x14` – with direction IN, presumably to read a status register (`HPI_STATUS_ADDR` based on the context). It checks the retrieved `status_reg`. It seems like it's waiting for a specific bit (bit 4, `0x0010`) in `status_reg` to clear. There is a timeout of 10ms between checks, which is pretty standard for these sorts of loops. If the timeout is hit, or there is an error in reading the status register, it exits the loop. If we run through 100 iterations and *still* the bit hasn't cleared, it signals a device hung error.

Once that bit *is* clear, or it breaks out early from an error, it issues another USB control message, a vendor request `0x12`, this time an OUT transfer.  This presumably writes the interrupt data. This is how the actual write occurs.

Following this function call, `go7007_usb_interface_reset` calls this function, sending two `0x10` requests.

The sequence then involves reading another interrupt. It looks like we're synchronizing by waiting for this bit in the status register to be clear before continuing, and then actually doing a write. This is a common pattern in USB devices to manage interrupt handshaking. I'd need to trace the status register and these vendor requests for a more precise understanding, but at this stage, it looks like it's a relatively straightforward write interrupt.



406/2 2026/07/30 13:21 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:720 LineCount:50]

Results:
map[Contents: 720:	
 721:	static int go7007_usb_onboard_write_interrupt(struct go7007 *go,
 722:							int addr, int data)
 723:	{
 724:		struct go7007_usb *usb = go->hpi_context;
 725:		int r;
 726:		int timeout = 500;
 727:	
 728:		pr_debug("WriteInterrupt: %04x %04x\n", addr, data);
 729:	
 730:		go->usb_buf[0] = data & 0xff;
 731:		go->usb_buf[1] = data >> 8;
 732:		go->usb_buf[2] = addr & 0xff;
 733:		go->usb_buf[3] = addr >> 8;
 734:		go->usb_buf[4] = go->usb_buf[5] = go->usb_buf[6] = go->usb_buf[7] = 0;
 735:		r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 2), 0x00,
 736:				USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0x55aa,
 737:				0xf0f0, go->usb_buf, 8, timeout);
 738:		if (r < 0) {
 739:			dev_err(go->dev, "error in WriteInterrupt: %d\n", r);
 740:			return r;
 741:		}
 742:		return 0;
 743:	}
 744:	
 745:	static void go7007_usb_readinterrupt_complete(struct urb *urb)
 746:	{
 747:		struct go7007 *go = (struct go7007 *)urb->context;
 748:		__le16 *regs = (__le16 *)urb->transfer_buffer;
 749:		int status = urb->status;
 750:	
 751:		if (status) {
 752:			if (status != -ESHUTDOWN &&
 753:					go->status != STATUS_SHUTDOWN) {
 754:				dev_err(go->dev, "error in read interrupt: %d\n", urb->status);
 755:			} else {
 756:				wake_up(&go->interrupt_waitq);
 757:				return;
 758:			}
 759:		} else if (urb->actual_length != urb->transfer_buffer_length) {
 760:			dev_err(go->dev, "short read in interrupt pipe!\n");
 761:		} else {
 762:			go->interrupt_available = 1;
 763:			go->interrupt_data = __le16_to_cpu(regs[0]);
 764:			go->interrupt_value = __le16_to_cpu(regs[1]);
 765:			pr_debug("ReadInterrupt: %04x %04x\n",
 766:					go->interrupt_value, go->interrupt_data);
 767:		}
 768:	
 769:		wake_up(&go->interrupt_waitq);
]

407/2 2026/07/30 13:21 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 88548
							output: 50
							thoughts: 422
						

Thoughts:
**Analyzing the Interrupt Read and its Implications**

Okay, so I'm looking at this `go7007_read_interrupt` function, and the first thing that jumps out is that it's using a USB Request Block (URB) for the interrupt read. Specifically, it's submitting `usb->intr_urb`, which I see is linked to `ep_in[4]`. The function then waits for the URB to complete, using `wait_event_timeout`. If the interrupt doesn't arrive within 500ms (quite generous), it kills the URB and returns -1. No problem there. The code seems pretty straightforward, submitting the URB, waiting for the event and killing it if the event never comes.

Now, where this gets interesting is in relation to syzkaller's `syz_usb_connect`. If I recall correctly, it emulates URB responses through those `ep_in` arrays in `vusb_responses`. So, the failure scenarios for this `go7007_read_interrupt` might be interesting to craft.

Then, I'm thinking about the bigger picture. I want to cause this probe to fail, ideally after certain critical initializations have been done to trigger an interesting state. Let's see...If I can get `go7007_usb_probe` to fail after `i2c_add_adapter` has been called, that would be ideal! I remember, for the `PX_TV402U` device, the `i2c_add_adapter` call happens *before* `go7007_usb_vendor_request(go, 0x41, ...)`. So, I need to cause the probe to fail AFTER that.

Let's quickly refresh my memory by looking at the `go7007_usb_probe` function again...



408/2 2026/07/30 13:21 tool read-file
0m Args:
map[File:drivers/media/usb/go7007/go7007-usb.c FirstLine:1160 LineCount:50]

Results:
map[Contents:1160:		/* Boot the GO7007 */
1161:		if (go7007_boot_encoder(go, go->board_info->flags &
1162:						GO7007_BOARD_USE_ONBOARD_I2C) < 0)
1163:			goto allocfail;
1164:	
1165:		/* Register the EZ-USB I2C adapter, if we're using it */
1166:		if (board->flags & GO7007_USB_EZUSB_I2C) {
1167:			memcpy(&go->i2c_adapter, &go7007_usb_adap_templ,
1168:					sizeof(go7007_usb_adap_templ));
1169:			mutex_init(&usb->i2c_lock);
1170:			go->i2c_adapter.dev.parent = go->dev;
1171:			i2c_set_adapdata(&go->i2c_adapter, go);
1172:			if (i2c_add_adapter(&go->i2c_adapter) < 0) {
1173:				dev_err(go->dev, "error: i2c_add_adapter failed\n");
1174:				goto allocfail;
1175:			}
1176:			go->i2c_adapter_online = 1;
1177:		}
1178:	
1179:		/* Pelco and Adlink reused the XMen and XMen-III vendor and product
1180:		 * IDs for their own incompatible designs.  We can detect XMen boards
1181:		 * by probing the sensor, but there is no way to probe the sensors on
1182:		 * the Pelco and Adlink designs so we default to the Adlink.  If it
1183:		 * is actually a Pelco, the user must set the assume_endura module
1184:		 * parameter. */
1185:		if ((go->board_id == GO7007_BOARDID_XMEN ||
1186:					go->board_id == GO7007_BOARDID_XMEN_III) &&
1187:				go->i2c_adapter_online) {
1188:			union i2c_smbus_data data;
1189:	
1190:			/* Check to see if register 0x0A is 0x76 */
1191:			i2c_smbus_xfer(&go->i2c_adapter, 0x21, I2C_CLIENT_SCCB,
1192:				I2C_SMBUS_READ, 0x0A, I2C_SMBUS_BYTE_DATA, &data);
1193:			if (data.byte != 0x76) {
1194:				if (assume_endura) {
1195:					go->board_id = GO7007_BOARDID_ENDURA;
1196:					usb->board = board = &board_endura;
1197:					go->board_info = &board->main_info;
1198:					strscpy(go->name, "Pelco Endura",
1199:						sizeof(go->name));
1200:				} else {
1201:					u16 channel;
1202:	
1203:					/* read channel number from GPIO[1:0] */
1204:					if (go7007_read_addr(go, 0x3c81, &channel))
1205:						goto allocfail;
1206:	
1207:					channel &= 0x3;
1208:					go->board_id = GO7007_BOARDID_ADLINK_MPG24;
1209:					usb->board = board = &board_adlink_mpg24;
]

409/2 2026/07/30 13:21 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 90442
							output: 36
							thoughts: 979
						

Thoughts:
**Debugging a Suspected UAF in I2C Adapter Lock**

Okay, let's break this down. My initial thought was that the `go7007` driver was the culprit, given the initial connection to the boot process and firmware loading.  Specifically, I was thinking: `go7007_boot_encoder` *must* succeed for us to even reach `i2c_add_adapter`.  And `go7007_boot_encoder` calls `go7007_load_encoder`, which in turn calls `request_firmware`.  If `request_firmware` fails, then the whole `go7007_boot_encoder` sequence fails, right?

The code seems straightforward: if `go->boot_fw` is NULL, then `request_firmware` is called. A failure here returns -1, which is a clear signal. The thing is, this would be a common problem: syzkaller images don't come pre-loaded with `go7007fw.bin`. If `request_firmware` fails, then there's no way that `i2c_add_adapter` should have been called, but the bug report says it WAS called, meaning the failure is somewhere else.

This made me pause.  How could this be possible? The bug report seems to contradict this, so I need to check the report again. The bug report is a slab-use-after-free in `i2c_adapter_lock_bus`. Okay, the UAF is in `i2c_adapter_lock_bus`.  The allocation trace is critical.  Here it is:

The allocation trace reveals the allocation is happening through `kobject_uevent_env`, ultimately used in `usb_register_bus` for `mon_bin_add`.

I see `env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL)`.  My immediate thought was about the size.  I was going to check the `sizeof(struct kobj_uevent_env)` value, since that would be key to understanding the allocation. From here, I need to check `kobject_uevent_env`, as it's the one allocating, using `kzalloc`.

The bug report says the buggy address belongs to an object in `kmalloc-4k`. But my intuition is that if `kobj_uevent_env` is the problem, that object will be 2048 bytes or less, so it should go into `kmalloc-2k`, right? That's what `sizeof(struct kobj_uevent_env)` should tell me. Why would a 2048-byte object land in `kmalloc-4k`?  Is `kobj_uevent_env` actually larger than I think?  Time to verify that size!



410/2 2026/07/30 13:22 tool read-file
0m Args:
map[File:lib/kobject_uevent.c FirstLine:20 LineCount:50]

Results:
map[Contents:  20:	#include <linux/kmod.h>
  21:	#include <linux/slab.h>
  22:	#include <linux/socket.h>
  23:	#include <linux/skbuff.h>
  24:	#include <linux/netlink.h>
  25:	#include <linux/uidgid.h>
  26:	#include <linux/uuid.h>
  27:	#include <linux/ctype.h>
  28:	#include <net/sock.h>
  29:	#include <net/netlink.h>
  30:	#include <net/net_namespace.h>
  31:	
  32:	
  33:	atomic64_t uevent_seqnum;
  34:	#ifdef CONFIG_UEVENT_HELPER
  35:	char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
  36:	#endif
  37:	
  38:	struct uevent_sock {
  39:		struct list_head list;
  40:		struct sock *sk;
  41:	};
  42:	
  43:	#ifdef CONFIG_NET
  44:	static LIST_HEAD(uevent_sock_list);
  45:	/* This lock protects uevent_sock_list */
  46:	static DEFINE_MUTEX(uevent_sock_mutex);
  47:	#endif
  48:	
  49:	/* the strings here must match the enum in include/linux/kobject.h */
  50:	static const char *kobject_actions[] = {
  51:		[KOBJ_ADD] =		"add",
  52:		[KOBJ_REMOVE] =		"remove",
  53:		[KOBJ_CHANGE] =		"change",
  54:		[KOBJ_MOVE] =		"move",
  55:		[KOBJ_ONLINE] =		"online",
  56:		[KOBJ_OFFLINE] =	"offline",
  57:		[KOBJ_BIND] =		"bind",
  58:		[KOBJ_UNBIND] =		"unbind",
  59:	};
  60:	
  61:	static int kobject_action_type(const char *buf, size_t count,
  62:				       enum kobject_action *type,
  63:				       const char **args)
  64:	{
  65:		enum kobject_action action;
  66:		size_t count_first;
  67:		const char *args_start;
  68:		int ret = -EINVAL;
  69:	
]

411/2 2026/07/30 13:22 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 92790
							output: 35
							thoughts: 25
						

Thoughts:
Here's my thought process, summarized as you requested:

**Navigating Kernel Object Structures**

Okay, so I'm digging into kernel object internals, specifically trying to understand the event environment. I need to know where this `struct kobj_uevent_env` is defined. Right, so my mental map suggests that anything related to kernel objects is probably going to be in `include/linux/kobject.h`. Let's confirm that. Yes, that makes sense. It's the logical place to start looking for definitions related to the fundamental building blocks of kernel objects and their event handling. That's a reasonable starting point.



412/2 2026/07/30 13:22 tool read-file
0m Args:
map[File:include/linux/kobject.h FirstLine:20 LineCount:50]

Results:
map[Contents:  20:	#include <linux/sysfs.h>
  21:	#include <linux/compiler.h>
  22:	#include <linux/container_of.h>
  23:	#include <linux/spinlock.h>
  24:	#include <linux/kref.h>
  25:	#include <linux/kobject_ns.h>
  26:	#include <linux/wait.h>
  27:	#include <linux/atomic.h>
  28:	#include <linux/workqueue.h>
  29:	#include <linux/uidgid.h>
  30:	
  31:	#define UEVENT_HELPER_PATH_LEN		256
  32:	#define UEVENT_NUM_ENVP			64	/* number of env pointers */
  33:	#define UEVENT_BUFFER_SIZE		2048	/* buffer for the variables */
  34:	
  35:	#ifdef CONFIG_UEVENT_HELPER
  36:	/* path to the userspace helper executed on an event */
  37:	extern char uevent_helper[];
  38:	#endif
  39:	
  40:	/* counter to tag the uevent, read only except for the kobject core */
  41:	extern atomic64_t uevent_seqnum;
  42:	
  43:	/*
  44:	 * The actions here must match the index to the string array
  45:	 * in lib/kobject_uevent.c
  46:	 *
  47:	 * Do not add new actions here without checking with the driver-core
  48:	 * maintainers. Action strings are not meant to express subsystem
  49:	 * or device specific properties. In most cases you want to send a
  50:	 * kobject_uevent_env(kobj, KOBJ_CHANGE, env) with additional event
  51:	 * specific variables added to the event environment.
  52:	 */
  53:	enum kobject_action {
  54:		KOBJ_ADD,
  55:		KOBJ_REMOVE,
  56:		KOBJ_CHANGE,
  57:		KOBJ_MOVE,
  58:		KOBJ_ONLINE,
  59:		KOBJ_OFFLINE,
  60:		KOBJ_BIND,
  61:		KOBJ_UNBIND,
  62:	};
  63:	
  64:	struct kobject {
  65:		const char		*name;
  66:		struct list_head	entry;
  67:		struct kobject		*parent;
  68:		struct kset		*kset;
  69:		const struct kobj_type	*ktype;
]

413/2 2026/07/30 13:22 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 93699
							output: 36
							thoughts: 17
						

Thoughts:
Here's my thought process, as if I were considering that code:

**Navigating Kernel Data Structures**

Okay, I'm going through this code, and I see a reference to `struct kobj_uevent_env`. Hmm, I don't immediately recall the structure's contents or definition. No problem, that's not unusual when dealing with complex kernel code. I'll need to figure out what data is being passed around here. I notice the definition of `struct kobj_uevent_env` is further down in the file. I need to take note of that. I can continue reading, but I need to make sure I don't lose that reference. I'll probably want to jump back down to that definition to understand what's happening.



414/2 2026/07/30 13:22 tool read-file
0m Args:
map[File:include/linux/kobject.h FirstLine:120 LineCount:50]

Results:
map[Contents: 120:		const struct kobj_ns_type_operations *(*child_ns_type)(const struct kobject *kobj);
 121:		const struct ns_common *(*namespace)(const struct kobject *kobj);
 122:		void (*get_ownership)(const struct kobject *kobj, kuid_t *uid, kgid_t *gid);
 123:	};
 124:	
 125:	struct kobj_uevent_env {
 126:		char *argv[3];
 127:		char *envp[UEVENT_NUM_ENVP];
 128:		int envp_idx;
 129:		char buf[UEVENT_BUFFER_SIZE];
 130:		int buflen;
 131:	};
 132:	
 133:	struct kset_uevent_ops {
 134:		int (* const filter)(const struct kobject *kobj);
 135:		const char *(* const name)(const struct kobject *kobj);
 136:		int (* const uevent)(const struct kobject *kobj, struct kobj_uevent_env *env);
 137:	};
 138:	
 139:	struct kobj_attribute {
 140:		struct attribute attr;
 141:		ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,
 142:				char *buf);
 143:		ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,
 144:				 const char *buf, size_t count);
 145:	};
 146:	
 147:	extern const struct sysfs_ops kobj_sysfs_ops;
 148:	
 149:	struct sock;
 150:	
 151:	/**
 152:	 * struct kset - a set of kobjects of a specific type, belonging to a specific subsystem.
 153:	 *
 154:	 * A kset defines a group of kobjects.  They can be individually
 155:	 * different "types" but overall these kobjects all want to be grouped
 156:	 * together and operated on in the same manner.  ksets are used to
 157:	 * define the attribute callbacks and other common events that happen to
 158:	 * a kobject.
 159:	 *
 160:	 * @list: the list of all kobjects for this kset
 161:	 * @list_lock: a lock for iterating over the kobjects
 162:	 * @kobj: the embedded kobject for this kset (recursion, isn't it fun...)
 163:	 * @uevent_ops: the set of uevent operations for this kset.  These are
 164:	 * called whenever a kobject has something happen to it so that the kset
 165:	 * can add new environment variables, or filter out the uevents if so
 166:	 * desired.
 167:	 */
 168:	struct kset {
 169:		struct list_head list;
]

415/2 2026/07/30 13:22 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 94755
							output: 23
							thoughts: 245
						

Thoughts:
**Analyzing a Kernel Memory Corruption Bug**

Okay, let me break this down. First, I need to understand the memory layout. The size of `struct kobj_uevent_env` is calculated as `3 * 8 + 64 * 8 + 4 + 2048 + 4 = 24 + 512 + 8 + 2048 = 2592` bytes. So, that means it's allocated from the `kmalloc-4k` cache. Got it. Now, the bug report... let's see. The buggy address is within an object at `ffff8880270b4000`, which *also* belongs to the `kmalloc-4k` cache. The important bit is that the report says the buggy address is 264 bytes *inside* a freed 4096-byte region, which is the exact size of one block from our `kmalloc-4k` pool. That's a classic heap out-of-bounds write after free!

The question is, what's being corrupted? The report doesn't explicitly state the object type, but let's assume it's `struct go7007` because of previous research. Now I need to figure out the location of something specific in that struct. If we were to assume the corruption originated there, where is `i2c_adapter` within `struct go7007`? I need to use `offsetof(struct go7007, i2c_adapter)` to find its position. That should help me figure out *what* exactly is being overwritten, or how it is related to other data structures in the process.



416/2 2026/07/30 13:22 tool codesearch-struct-layout
0m Args:
map[Name:go7007]

Results:
map[Fields:[map[Name:dev OffsetBits:0 SizeBits:64] map[Name:bus_info OffsetBits:64 SizeBits:256] map[Name:board_info OffsetBits:320 SizeBits:64] map[Name:board_id OffsetBits:384 SizeBits:32] map[Name:tuner_type OffsetBits:416 SizeBits:32] map[Name:channel_number OffsetBits:448 SizeBits:32] map[Name:name OffsetBits:480 SizeBits:512] map[Name:vdev OffsetBits:1024 SizeBits:16064] map[Name:boot_fw OffsetBits:17088 SizeBits:64] map[Name:boot_fw_len OffsetBits:17152 SizeBits:32] map[Name:v4l2_dev OffsetBits:17216 SizeBits:1984] map[Name:hdl OffsetBits:19200 SizeBits:2432] map[Name:mpeg_video_encoding OffsetBits:21632 SizeBits:64] map[Name:mpeg_video_gop_size OffsetBits:21696 SizeBits:64] map[Name:mpeg_video_gop_closure OffsetBits:21760 SizeBits:64] map[Name:mpeg_video_bitrate OffsetBits:21824 SizeBits:64] map[Name:mpeg_video_aspect_ratio OffsetBits:21888 SizeBits:64] map[Name:mpeg_video_b_frames OffsetBits:21952 SizeBits:64] map[Name:mpeg_video_rep_seqheader OffsetBits:22016 SizeBits:64] map[Name:modet_mode OffsetBits:22080 SizeBits:64] map[Name:status OffsetBits:22144 SizeBits:32] map[Name:spinlock OffsetBits:22208 SizeBits:1024] map[Name:hw_lock OffsetBits:23232 SizeBits:1024] map[Name:serialize_lock OffsetBits:24256 SizeBits:1024] map[Name:audio_enabled OffsetBits:25280 SizeBits:32] map[Name:sd_video OffsetBits:25344 SizeBits:64] map[Name:sd_audio OffsetBits:25408 SizeBits:64] map[Name:usb_buf OffsetBits:25472 SizeBits:128] map[Name:input OffsetBits:25600 SizeBits:32] map[Name:aud_input OffsetBits:25632 SizeBits:32] map[Name:standard OffsetBits:25664 SizeBits:32] map[Name:std OffsetBits:25728 SizeBits:64] map[Name:sensor_framerate OffsetBits:25792 SizeBits:32] map[Name:width OffsetBits:25824 SizeBits:32] map[Name:height OffsetBits:25856 SizeBits:32] map[Name:encoder_h_offset OffsetBits:25888 SizeBits:32] map[Name:encoder_v_offset OffsetBits:25920 SizeBits:32] map[Name:encoder_h_halve OffsetBits:25952 SizeBits:1] map[Name:encoder_v_halve OffsetBits:25953 SizeBits:1] map[Name:encoder_subsample OffsetBits:25954 SizeBits:1] map[Name:format OffsetBits:25984 SizeBits:32] map[Name:bitrate OffsetBits:26016 SizeBits:32] map[Name:fps_scale OffsetBits:26048 SizeBits:32] map[Name:pali OffsetBits:26080 SizeBits:32] map[Name:aspect_ratio OffsetBits:26112 SizeBits:32] map[Name:gop_size OffsetBits:26144 SizeBits:32] map[Name:ipb OffsetBits:26176 SizeBits:1] map[Name:closed_gop OffsetBits:26177 SizeBits:1] map[Name:repeat_seqhead OffsetBits:26178 SizeBits:1] map[Name:seq_header_enable OffsetBits:26179 SizeBits:1] map[Name:gop_header_enable OffsetBits:26180 SizeBits:1] map[Name:dvd_mode OffsetBits:26181 SizeBits:1] map[Name:interlace_coding OffsetBits:26182 SizeBits:1] map[Name:modet_enable OffsetBits:26183 SizeBits:1] map[Name:modet OffsetBits:26208 SizeBits:512] map[Name:modet_map OffsetBits:26720 SizeBits:12992] map[Name:active_map OffsetBits:39712 SizeBits:1728] map[Name:modet_event_status OffsetBits:41440 SizeBits:32] map[Name:queue_lock OffsetBits:41472 SizeBits:1024] map[Name:vidq OffsetBits:42496 SizeBits:5568] map[Name:state OffsetBits:48064 SizeBits:32] map[Name:parse_length OffsetBits:48096 SizeBits:32] map[Name:modet_word OffsetBits:48128 SizeBits:16] map[Name:seen_frame OffsetBits:48160 SizeBits:32] map[Name:next_seq OffsetBits:48192 SizeBits:32] map[Name:vidq_active OffsetBits:48256 SizeBits:128] map[Name:frame_waitq OffsetBits:48384 SizeBits:1152] map[Name:active_buf OffsetBits:49536 SizeBits:64] map[Name:audio_deliver OffsetBits:49600 SizeBits:64] map[Name:snd_context OffsetBits:49664 SizeBits:64] map[Name:i2c_adapter_online OffsetBits:49728 SizeBits:32] map[Name:i2c_adapter OffsetBits:49792 SizeBits:17024] map[Name:hpi_ops OffsetBits:66816 SizeBits:64] map[Name:hpi_context OffsetBits:66880 SizeBits:64] map[Name:interrupt_available OffsetBits:66944 SizeBits:32] map[Name:interrupt_waitq OffsetBits:67008 SizeBits:1152] map[Name:interrupt_value OffsetBits:68160 SizeBits:16] map[Name:interrupt_data OffsetBits:68176 SizeBits:16]]]

417/2 2026/07/30 13:22 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 97252
							output: 44
							thoughts: 564
						

Thoughts:
**Debugging a KASAN Slab-Use-After-Free in the I2C Subsystem**

Okay, let's break this down. The initial assumption that `i2c_adapter` might be at a particular offset (6224 bytes) within a larger object is quickly discarded. The buggy address reported (264 bytes into a 4096-byte region) eliminates `struct go7007` as the culprit, since that's much larger (8524 bytes) and would be allocated in a larger kmalloc slab. I see the bug report specifically mentions a `kmalloc-4k` region. This strongly suggests the object involved is *exactly* 4096 bytes.

The clue is the KASAN report pointing directly at `i2c_adapter_lock_bus`. I need to figure out which object, allocated in a 4k slab, contains an element at an offset of 264 bytes that is related to `i2c_adapter_lock_bus`. The buggy address `ffff8880270b4108` confirms this – the offset of 264 bytes is exact. This directly links to the `i2c_adapter_depth` function, which is ultimately calling `i2c_adapter_lock_bus`. It’s likely that I need to investigate the structure and definition, and what is located at an offset of 264 bytes. I’ll need to check the definition of the `i2c_adapter` struct and its members, perhaps with `offsetof` to verify my suspicions.



418/2 2026/07/30 13:22 tool read-file
0m Args:
map[File:drivers/i2c/i2c-core-base.c FirstLine:1230 LineCount:50]

Results:
map[Contents:1230:	
1231:	static void i2c_adapter_dev_release(struct device *dev)
1232:	{
1233:		struct i2c_adapter *adap = to_i2c_adapter(dev);
1234:		complete(&adap->dev_released);
1235:	}
1236:	
1237:	unsigned int i2c_adapter_depth(struct i2c_adapter *adapter)
1238:	{
1239:		unsigned int depth = 0;
1240:		struct device *parent;
1241:	
1242:		for (parent = adapter->dev.parent; parent; parent = parent->parent)
1243:			if (parent->type == &i2c_adapter_type)
1244:				depth++;
1245:	
1246:		WARN_ONCE(depth >= MAX_LOCKDEP_SUBCLASSES,
1247:			  "adapter depth exceeds lockdep subclass limit\n");
1248:	
1249:		return depth;
1250:	}
1251:	EXPORT_SYMBOL_GPL(i2c_adapter_depth);
1252:	
1253:	/*
1254:	 * Let users instantiate I2C devices through sysfs. This can be used when
1255:	 * platform initialization code doesn't contain the proper data for
1256:	 * whatever reason. Also useful for drivers that do device detection and
1257:	 * detection fails, either because the device uses an unexpected address,
1258:	 * or this is a compatible device with different ID register values.
1259:	 *
1260:	 * Parameter checking may look overzealous, but we really don't want
1261:	 * the user to provide incorrect parameters.
1262:	 */
1263:	static ssize_t
1264:	new_device_store(struct device *dev, struct device_attribute *attr,
1265:			 const char *buf, size_t count)
1266:	{
1267:		struct i2c_adapter *adap = to_i2c_adapter(dev);
1268:		struct i2c_board_info info;
1269:		struct i2c_client *client;
1270:		char *blank, end;
1271:		int res;
1272:	
1273:		memset(&info, 0, sizeof(struct i2c_board_info));
1274:	
1275:		blank = strchr(buf, ' ');
1276:		if (!blank) {
1277:			dev_err(dev, "%s: Missing parameters\n", "new_device");
1278:			return -EINVAL;
1279:		}
]

419/2 2026/07/30 13:22 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 98958
							output: 19
							thoughts: 70
						

Thoughts:
**UAF Concerns with I2C Adapter Depth**

Okay, so I'm digging into this code and immediately see a potential problem. The `i2c_adapter_depth` function is accessing `parent->type`. I know that `parent` is ultimately derived from `adapter->dev.parent`. The alarm bells are going off because if `adapter->dev.parent` points to a memory location that's been freed, then that `parent->type` access is going to be a classic Use-After-Free (UAF) vulnerability. We *definitely* don't want that! Time to confirm my suspicion, let's look at the `offsetof(struct device, type)` to make sure I am correct, before I report this.



420/2 2026/07/30 13:22 tool codesearch-struct-layout
0m Args:
map[Name:device]

Results:
map[Fields:[map[Name:kobj OffsetBits:0 SizeBits:512] map[Name:parent OffsetBits:512 SizeBits:64] map[Name:p OffsetBits:576 SizeBits:64] map[Name:init_name OffsetBits:640 SizeBits:64] map[Name:type OffsetBits:704 SizeBits:64] map[Name:bus OffsetBits:768 SizeBits:64] map[Name:driver OffsetBits:832 SizeBits:64] map[Name:platform_data OffsetBits:896 SizeBits:64] map[Name:driver_data OffsetBits:960 SizeBits:64] map[Name:driver_override OffsetBits:1024 SizeBits:1088] map[Name:mutex OffsetBits:2112 SizeBits:1024] map[Name:links OffsetBits:3136 SizeBits:448] map[Name:power OffsetBits:3584 SizeBits:5440] map[Name:pm_domain OffsetBits:9024 SizeBits:64] map[Name:msi OffsetBits:9088 SizeBits:128] map[Name:dma_mask OffsetBits:9216 SizeBits:64] map[Name:coherent_dma_mask OffsetBits:9280 SizeBits:64] map[Name:bus_dma_limit OffsetBits:9344 SizeBits:64] map[Name:dma_range_map OffsetBits:9408 SizeBits:64] map[Name:dma_parms OffsetBits:9472 SizeBits:64] map[Name:dma_pools OffsetBits:9536 SizeBits:128] map[Name:dma_mem OffsetBits:9664 SizeBits:64] map[Name:cma_area OffsetBits:9728 SizeBits:64] map[Name:dma_io_tlb_mem OffsetBits:9792 SizeBits:64] map[Name:archdata OffsetBits:9856 SizeBits:0] map[Name:of_node OffsetBits:9856 SizeBits:64] map[Name:fwnode OffsetBits:9920 SizeBits:64] map[Name:numa_node OffsetBits:9984 SizeBits:32] map[Name:devt OffsetBits:10016 SizeBits:32] map[Name:id OffsetBits:10048 SizeBits:32] map[Name:devres_lock OffsetBits:10112 SizeBits:1024] map[Name:devres_head OffsetBits:11136 SizeBits:128] map[Name:class OffsetBits:11264 SizeBits:64] map[Name:groups OffsetBits:11328 SizeBits:64] map[Name:release OffsetBits:11392 SizeBits:64] map[Name:iommu_group OffsetBits:11456 SizeBits:64] map[Name:iommu OffsetBits:11520 SizeBits:64] map[Name:physical_location OffsetBits:11584 SizeBits:64] map[Name:removable OffsetBits:11648 SizeBits:32] map[Name:flags OffsetBits:11712 SizeBits:64]]]

421/2 2026/07/30 13:22 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 100108
							output: 23
							thoughts: 459
						

Thoughts:
**Analyzing a Potential Use-After-Free Vulnerability**

Okay, let's break this down. My initial observation was that the `type` field I was concerned about was at an offset of 88 bytes, or 704 bits, within a structure. However, the use-after-free (UAF) was happening at offset 264. That didn't make sense. I quickly realized 264 is 0x108. I double-checked the `offsetof` for `struct device.type` just to be sure, and the calculation of offsets seemed sound: `kobj` (64 bytes), `parent` (8 bytes), `p` (8 bytes), and `init_name` (8 bytes) added up correctly to 88.

The potential confusion here involves the `parent` pointer. If `parent` were a `struct usb_interface`, then a read of `parent->type` would indeed be at offset 88. But the UAF is happening at 264. So, this meant `parent` must not be a direct `struct usb_interface`.

I started digging deeper and found that the `parent` is actually accessed via `adapter->dev.parent`. Now it started to click. The relevant code in `go7007` sets `go->i2c_adapter.dev.parent = go->dev`. And `go->dev` is initialized as `&intf->dev`. This means it is the address of an embedded `struct device` within a `struct usb_interface`.

Here's the key: if `go->dev` is a pointer to `intf->dev`, then `intf->dev` is not directly freed. `intf` is freed when the USB device is disconnected. But if `go7007_usb_probe` fails early, the driver does not immediately free the `intf`.

So, the critical piece: if `go` gets freed, and `adapter` is embedded within `go`, then `adapter` is freed as well. This means a subsequent read from `adapter->dev.parent` is a use-after-free! I need to double-check `offsetof(struct i2c_adapter, dev.parent)` to confirm my understanding of the offsets. It looks like `adapter` is the crucial data structure here and it's being corrupted!



422/2 2026/07/30 13:22 tool codesearch-struct-layout
0m Args:
map[Name:i2c_adapter]

Results:
map[Fields:[map[Name:owner OffsetBits:0 SizeBits:64] map[Name:class OffsetBits:64 SizeBits:32] map[Name:algo OffsetBits:128 SizeBits:64] map[Name:algo_data OffsetBits:192 SizeBits:64] map[Name:lock_ops OffsetBits:256 SizeBits:64] map[Name:bus_lock OffsetBits:320 SizeBits:1024] map[Name:mux_lock OffsetBits:1344 SizeBits:1024] map[Name:timeout OffsetBits:2368 SizeBits:32] map[Name:retries OffsetBits:2400 SizeBits:32] map[Name:dev OffsetBits:2432 SizeBits:11776] map[Name:locked_flags OffsetBits:14208 SizeBits:64] map[Name:nr OffsetBits:14272 SizeBits:32] map[Name:name OffsetBits:14304 SizeBits:384] map[Name:dev_released OffsetBits:14720 SizeBits:704] map[Name:userspace_clients_lock OffsetBits:15424 SizeBits:1024] map[Name:userspace_clients OffsetBits:16448 SizeBits:128] map[Name:bus_recovery_info OffsetBits:16576 SizeBits:64] map[Name:quirks OffsetBits:16640 SizeBits:64] map[Name:host_notify_domain OffsetBits:16704 SizeBits:64] map[Name:bus_regulator OffsetBits:16768 SizeBits:64] map[Name:debugfs OffsetBits:16832 SizeBits:64] map[Name:addrs_in_instantiation OffsetBits:16896 SizeBits:128]]]

423/2 2026/07/30 13:22 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 101613
							output: 43
							thoughts: 407
						

Thoughts:
**Analyzing a Potential Use-After-Free Vulnerability**

Okay, first things first, I need to get my bearings. The reported bug indicates a Use-After-Free (UAF) within the `i2c_adapter` structure. My initial thought is to trace the memory layout to see how things are arranged.  Let's start with the provided offsets, and see where they land in memory. So, `dev` is at offset 2432 bits, which is 304 bytes into the `i2c_adapter` struct, and `dev.parent` is 64 bytes further. Interesting, but not immediately relevant.

The UAF is reported at offset 264. I'll need to confirm that. 264 in decimal? That's `0x108` in hex. Now, let's see what data is at that offset of the `struct i2c_adapter`. To get there I need `264 * 8 = 2112` bits. Okay, I'm thinking I've identified something.

Let's see what's nearby.  `bus_lock` is at offset 320 bits, or 40 bytes. And it's a `struct rt_mutex`, which I know is 1024 bits, or 128 bytes, in size. That means `bus_lock` ends at 168 bytes.  Now, `mux_lock` starts at 1344 bits, so 168 bytes! It's another `struct rt_mutex`, so 128 bytes. So `mux_lock` ends at 296 bytes.

Now I see it! Offset 264 is *inside* `mux_lock`! That's a significant detail and likely where the vulnerability lies.

Let's double-check the bug report to confirm the location. `i2c_adapter_depth` and `i2c_adapter_lock_bus`.  I'll want to check the code for `i2c_adapter_lock_bus` to get the context here. Now, I have to look deeper to see what's happening at those addresses.



424/2 2026/07/30 13:22 tool read-file
0m Args:
map[File:drivers/i2c/i2c-core-base.c FirstLine:840 LineCount:50]

Results:
map[Contents: 840:	/**
 841:	 * i2c_adapter_lock_bus - Get exclusive access to an I2C bus segment
 842:	 * @adapter: Target I2C bus segment
 843:	 * @flags: I2C_LOCK_ROOT_ADAPTER locks the root i2c adapter, I2C_LOCK_SEGMENT
 844:	 *	locks only this branch in the adapter tree
 845:	 */
 846:	static void i2c_adapter_lock_bus(struct i2c_adapter *adapter,
 847:					 unsigned int flags)
 848:	{
 849:		rt_mutex_lock_nested(&adapter->bus_lock, i2c_adapter_depth(adapter));
 850:	}
 851:	
 852:	/**
 853:	 * i2c_adapter_trylock_bus - Try to get exclusive access to an I2C bus segment
 854:	 * @adapter: Target I2C bus segment
 855:	 * @flags: I2C_LOCK_ROOT_ADAPTER trylocks the root i2c adapter, I2C_LOCK_SEGMENT
 856:	 *	trylocks only this branch in the adapter tree
 857:	 */
 858:	static int i2c_adapter_trylock_bus(struct i2c_adapter *adapter,
 859:					   unsigned int flags)
 860:	{
 861:		return rt_mutex_trylock(&adapter->bus_lock);
 862:	}
 863:	
 864:	/**
 865:	 * i2c_adapter_unlock_bus - Release exclusive access to an I2C bus segment
 866:	 * @adapter: Target I2C bus segment
 867:	 * @flags: I2C_LOCK_ROOT_ADAPTER unlocks the root i2c adapter, I2C_LOCK_SEGMENT
 868:	 *	unlocks only this branch in the adapter tree
 869:	 */
 870:	static void i2c_adapter_unlock_bus(struct i2c_adapter *adapter,
 871:					   unsigned int flags)
 872:	{
 873:		rt_mutex_unlock(&adapter->bus_lock);
 874:	}
 875:	
 876:	static void i2c_dev_set_name(struct i2c_adapter *adap,
 877:				     struct i2c_client *client,
 878:				     struct i2c_board_info const *info)
 879:	{
 880:		struct acpi_device *adev = ACPI_COMPANION(&client->dev);
 881:	
 882:		if (info && info->dev_name) {
 883:			dev_set_name(&client->dev, "i2c-%s", info->dev_name);
 884:			return;
 885:		}
 886:	
 887:		if (adev) {
 888:			dev_set_name(&client->dev, "i2c-%s", acpi_dev_name(adev));
 889:			return;
]

425/2 2026/07/30 13:22 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 103402
							output: 25
							thoughts: 691
						

Thoughts:
**Debugging a Use-After-Free Vulnerability in I2C Adapter Locking**

Okay, so I'm looking at this KASAN report, a slab-use-after-free in `i2c_adapter_lock_bus`.  The function calls `rt_mutex_lock_nested` with the `adapter->bus_lock` and the result of `i2c_adapter_depth(adapter)`. The first thing that jumps out is that `i2c_adapter_depth` is evaluated *before* the lock is attempted. I'm already spotting a potential race here, but need to follow the data.

My immediate thought is to check `i2c_adapter_depth` again to see what is going on. I can see that this function accesses `adapter->dev.parent`. Now, the initial bug report references an offset of 264 for the use-after-free, while `adapter->dev.parent` is actually at offset 368 in the `i2c_adapter` struct. That doesn't make sense. And, `i2c_adapter_depth` is inlined, so that's another thing I'll need to keep in mind.

I'm thinking, could `adapter` actually be a pointer to something *other* than an `i2c_adapter`? The function signature takes a `struct i2c_adapter *`, so this is key. But what if the `i2c_adapter` structure is embedded within a *different* structure? Yeah, that's it! What if `adapter` is a pointer to the *containing* struct, like `go7007` or something similar?

I look at the `struct go7007`, and yes, there is an `i2c_adapter` embedded within it, called `go->i2c_adapter`. I go to check the offset of `i2c_adapter` within `struct go7007`. Wait... it's a huge offset - 6224 bytes! That object is 8524 bytes in total. That also means that this struct can't be allocated from `kmalloc-4k`. The freed object size is 4096 bytes, but that isn't the struct we are looking at. So, that's not it.

Okay, let's step back. What other object is 4096 bytes and contains an `i2c_adapter`? Hmm, let's check `au0828_dev`. Time to check `offsetof(struct au0828_dev, i2c_adap)`... let's see where that takes me. This looks promising.



426/2 2026/07/30 13:23 tool codesearch-struct-layout
0m Args:
map[Name:au0828_dev]

Results:
map[Fields:[map[Name:mutex OffsetBits:0 SizeBits:1024] map[Name:usbdev OffsetBits:1024 SizeBits:64] map[Name:boardnr OffsetBits:1088 SizeBits:32] map[Name:board OffsetBits:1152 SizeBits:896] map[Name:ctrlmsg OffsetBits:2048 SizeBits:512] map[Name:i2c_adap OffsetBits:2560 SizeBits:17024] map[Name:i2c_algo OffsetBits:19584 SizeBits:448] map[Name:i2c_client OffsetBits:20032 SizeBits:12416] map[Name:i2c_rc OffsetBits:32448 SizeBits:32] map[Name:dvb OffsetBits:32512 SizeBits:24512] map[Name:restart_streaming OffsetBits:57024 SizeBits:576] map[Name:bulk_timeout OffsetBits:57600 SizeBits:640] map[Name:bulk_timeout_running OffsetBits:58240 SizeBits:32] map[Name:v4l2_dev OffsetBits:58304 SizeBits:1984] map[Name:v4l2_ctrl_hdl OffsetBits:60288 SizeBits:2432] map[Name:ir OffsetBits:62720 SizeBits:64] map[Name:vdev OffsetBits:62784 SizeBits:16064] map[Name:vbi_dev OffsetBits:78848 SizeBits:16064] map[Name:vb_vidq OffsetBits:94912 SizeBits:5568] map[Name:vb_vbiq OffsetBits:100480 SizeBits:5568] map[Name:vb_queue_lock OffsetBits:106048 SizeBits:1024] map[Name:vb_vbi_queue_lock OffsetBits:107072 SizeBits:1024] map[Name:frame_count OffsetBits:108096 SizeBits:32] map[Name:vbi_frame_count OffsetBits:108128 SizeBits:32] map[Name:vid_timeout OffsetBits:108160 SizeBits:640] map[Name:vid_timeout_running OffsetBits:108800 SizeBits:32] map[Name:vbi_timeout OffsetBits:108864 SizeBits:640] map[Name:vbi_timeout_running OffsetBits:109504 SizeBits:32] map[Name:users OffsetBits:109536 SizeBits:32] map[Name:streaming_users OffsetBits:109568 SizeBits:32] map[Name:width OffsetBits:109600 SizeBits:32] map[Name:height OffsetBits:109632 SizeBits:32] map[Name:vbi_width OffsetBits:109664 SizeBits:32] map[Name:vbi_height OffsetBits:109696 SizeBits:32] map[Name:vbi_read OffsetBits:109728 SizeBits:32] map[Name:std OffsetBits:109760 SizeBits:64] map[Name:field_size OffsetBits:109824 SizeBits:32] map[Name:frame_size OffsetBits:109856 SizeBits:32] map[Name:bytesperline OffsetBits:109888 SizeBits:32] map[Name:type OffsetBits:109920 SizeBits:32] map[Name:ctrl_ainput OffsetBits:109952 SizeBits:8] map[Name:isoc_in_endpointaddr OffsetBits:109960 SizeBits:8] map[Name:isoc_init_ok OffsetBits:109968 SizeBits:8] map[Name:greenscreen_detected OffsetBits:109984 SizeBits:32] map[Name:ctrl_freq OffsetBits:110016 SizeBits:32] map[Name:input_type OffsetBits:110048 SizeBits:32] map[Name:std_set_in_tuner_core OffsetBits:110080 SizeBits:32] map[Name:ctrl_input OffsetBits:110112 SizeBits:32] map[Name:dev_state OffsetBits:110144 SizeBits:64] map[Name:stream_state OffsetBits:110208 SizeBits:32] map[Name:open OffsetBits:110272 SizeBits:1152] map[Name:lock OffsetBits:111424 SizeBits:1024] map[Name:vidq OffsetBits:112448 SizeBits:192] map[Name:vbiq OffsetBits:112640 SizeBits:192] map[Name:isoc_ctl OffsetBits:112832 SizeBits:704] map[Name:slock OffsetBits:113536 SizeBits:1024] map[Name:alt OffsetBits:114560 SizeBits:32] map[Name:max_pkt_size OffsetBits:114592 SizeBits:32] map[Name:num_alt OffsetBits:114624 SizeBits:32] map[Name:alt_max_pkt_size OffsetBits:114688 SizeBits:64] map[Name:urb OffsetBits:114752 SizeBits:768] map[Name:transfer_buffer OffsetBits:115520 SizeBits:768] map[Name:urb_streaming OffsetBits:116288 SizeBits:8] map[Name:need_urb_start OffsetBits:116296 SizeBits:8] map[Name:urbs OffsetBits:116352 SizeBits:1024] map[Name:dig_transfer_buffer OffsetBits:117376 SizeBits:1024] map[Name:media_dev OffsetBits:118400 SizeBits:64] map[Name:video_pad OffsetBits:118464 SizeBits:512] map[Name:vbi_pad OffsetBits:118976 SizeBits:512] map[Name:decoder OffsetBits:119488 SizeBits:64] map[Name:input_ent OffsetBits:119552 SizeBits:3840] map[Name:input_pad OffsetBits:123392 SizeBits:2048] map[Name:entity_notify OffsetBits:125440 SizeBits:256] map[Name:tuner OffsetBits:125696 SizeBits:64] map[Name:active_link OffsetBits:125760 SizeBits:64] map[Name:active_source OffsetBits:125824 SizeBits:64] map[Name:active_sink OffsetBits:125888 SizeBits:64] map[Name:active_link_owner OffsetBits:125952 SizeBits:64] map[Name:active_link_user OffsetBits:126016 SizeBits:64] map[Name:active_link_user_pipe OffsetBits:126080 SizeBits:64] map[Name:active_link_shared OffsetBits:126144 SizeBits:8]]]

427/2 2026/07/30 13:23 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 106728
							output: 21
							thoughts: 902
						

Thoughts:
**Analyzing a Potential Use-After-Free Vulnerability**

Okay, first things first. The size of `struct au0828_dev` is huge, way bigger than the 4096 bytes being discussed. It's definitely not allocated from a 4k kmalloc cache. So, what *is* allocated in 4096-byte chunks? I remember the bug report mentioning the address `ffff8880270b4000` belonging to a `kmalloc-4k` cache and the problematic offset being 264 bytes into the freed region. The actual buggy address is `ffff8880270b4108`, which confirms the offset.

Now, what object is exactly 4096 bytes? Is it a driver-specific object? My gut says to check the `i2c_adapter` structure. Let's see... `sizeof(struct i2c_adapter)` comes out to 2128 bytes, which, yes, would be allocated from a `kmalloc-4k` region since it's larger than `kmalloc-2k` which is 2048 bytes. Okay, the `i2c_adapter` struct is allocated from `kmalloc-4k`! It can be embedded in things like `go7007` and `au0828_dev`, but what if the driver allocates it dynamically?

So, if `struct i2c_adapter` is allocated from `kmalloc-4k`, then the potential use-after-free (UAF) could be at offset 264 within that structure. Let's check the offsets. The bug refers to the `bus_lock` member of the `i2c_adapter`. Alright, `offsetof(struct i2c_adapter, bus_lock)` is 40 bytes. That's a `rt_mutex`. And an `rt_mutex` is 128 bytes. The memory map of `bus_lock` would then be from offset 40 bytes to 168.

So, what's at offset 264? Let's check `offsetof(struct i2c_adapter, dev.parent)`. The `dev` member starts at offset 304, and `dev.parent` is actually 64 bytes into that, starting at offset 368.

However, the question remains: what's at offset 264? I'm missing something here. Let's look at the `i2c_adapter_lock_bus` function itself. It's using the `bus_lock`, so it's a `rt_mutex_lock_nested`.

The `rt_mutex` has a `wait_lock` (4 bytes), `waiters` (16 bytes), and an `owner` (8 bytes) so it's *not* 128 bytes in size! I need to check the real size of `struct rt_mutex` to be certain.



428/2 2026/07/30 13:23 tool codesearch-struct-layout
0m Args:
map[Name:rt_mutex]

Results:
map[Fields:[map[Name:rtmutex OffsetBits:0 SizeBits:704] map[Name:dep_map OffsetBits:704 SizeBits:320]]]

429/2 2026/07/30 13:23 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 108364
							output: 25
							thoughts: 2165
						

Thoughts:
**Analyzing a KASAN Slab-Use-After-Free Bug**

Okay, so I'm diving into this KASAN report, and my initial thought was that it was an `i2c_adapter` issue. The report points to a slab-use-after-free within `i2c_adapter_lock_bus`. I started by trying to map the structure offsets, thinking I might be able to pinpoint where the erroneous access occurs. I quickly realized `rt_mutex` is 128 bytes (1024 bits), `bus_lock` runs from offset 40-168 and `mux_lock` starts at offset 1344 bits or 168 bytes. I checked the offset 264 and confirmed it falls inside `mux_lock`. But then I realized `i2c_adapter_lock_bus` isn't touching `mux_lock`, which made me pause.

The bug report mentions access to `adapter->dev.parent`. If `dev.parent` is at offset 264, then `dev` itself would be at offset 200, which seemed odd. I wanted to verify this with `offsetof(struct i2c_adapter, dev)`. Previously, in a related query, it was at 304 bytes. Then I remembered that `CONFIG_LOCKDEP` can alter the size of `rt_mutex`, adding `dep_map`. Syzkaller kernels usually have it enabled. I should check the size of `struct i2c_adapter` in the actual kernel configuration.

I started to break down the structure, manually calculating offsets: `owner` (8 bytes), `class` (4), padding (4), `algo` (8), `algo_data` (8), `lock_ops` (8). These totaled 40 bytes before the `bus_lock`. Assuming 32 bytes for `rt_mutex` (without `dep_map`), and another 32 for `mux_lock`, `timeout` (4), `retries` (4), then `dev` might be at offset 104+8=112 bytes and `dev.parent` at 176 bytes which is NOT 264. I even considered if there's padding or a bigger `rt_mutex`. I re-checked, but even with 72 bytes for the `rt_mutex` the offset would not be 264 bytes. If `dev.parent` *is* at 264, `dev` would be at 200, but I don't know why it would be there.

Then, a sudden thought: what if the accessed memory isn't actually an `i2c_adapter`? I checked the allocation trace: it goes through `kmalloc_reserve`, `__alloc_skb`, and so on. Wait a second, this is `sk_buff` data allocation! The size is 4096 bytes. The free trace also confirms this: `skb_kfree_head`, `skb_release_data`, etc. That changes everything!

This is an `sk_buff` buffer! The UAF is happening on a memory region that was used for `sk_buff` data and was *reallocated*. KASAN reports the *last* allocation/free, so the issue must be with the re-use. However, if the memory was reallocated, KASAN would report the *new* allocation, which it does not.

So, the object was allocated, freed, and *then* accessed. An `sk_buff` object was freed, then accessed as an `i2c_adapter`. This means the `i2c_adapter` itself was allocated first, then freed, then the memory was re-allocated as `sk_buff` data, then freed again, and then accessed as `i2c_adapter`.

I'm starting to zero in on a pattern now. The allocation would have to be through `kmalloc-4k`, which makes sense because this is an `sk_buff` buffer. I was previously considering objects that are in the 8k or 16k slabs. Now I need to identify which `kmalloc-4k` object might contain the `i2c_adapter`.



430/2 2026/07/30 13:23 tool codesearch-struct-layout
0m Args:
map[Name:si4713_device]

Results:
map[Fields:[map[Name:sd OffsetBits:0 SizeBits:3072] map[Name:ctrl_handler OffsetBits:3072 SizeBits:2432] map[Name: OffsetBits:5504 SizeBits:1856] map[Name:work OffsetBits:7360 SizeBits:704] map[Name:vdd OffsetBits:8064 SizeBits:64] map[Name:vio OffsetBits:8128 SizeBits:64] map[Name:gpio_reset OffsetBits:8192 SizeBits:64] map[Name:pd OffsetBits:8256 SizeBits:64] map[Name:power_state OffsetBits:8320 SizeBits:32] map[Name:rds_enabled OffsetBits:8352 SizeBits:32] map[Name:frequency OffsetBits:8384 SizeBits:32] map[Name:preemphasis OffsetBits:8416 SizeBits:32] map[Name:stereo OffsetBits:8448 SizeBits:32] map[Name:tune_rnl OffsetBits:8480 SizeBits:32]]]

431/2 2026/07/30 13:23 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 111788
							output: 25
							thoughts: 206
						

Thoughts:
**Analyzing I2C Adapter Memory Allocation**

Okay, so I'm digging into this memory allocation stuff. The `si4713_device`, that's 1060 bytes, right? Yeah, that's definitely landing in either `kmalloc-1k` or `kmalloc-2k`. But wait, what about the `i2c_adapter` struct itself? That's the real key here.

If it's dynamically allocated, which is pretty common, it's usually done with something like `kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL)`. Okay, let me quickly double-check the size... Hold on... 2128 bytes with lockdep! Right. That pushes it into `kmalloc-4k`. Not what I initially expected.

So now, the real question is, which drivers are allocating `i2c_adapter` dynamically and are they potentially leaking it or, even worse, using it after it's been freed (UAF)? Time to track down potential issues! I need to search through the code for those dynamic allocations. Let's see... I'll search for `kzalloc(sizeof(struct i2c_adapter)` or `kzalloc(sizeof(*adapter)`. That should do the trick. Usually, it's embedded in another structure, but I know it's sometimes allocated directly.



432/2 2026/07/30 13:23 tool grepper
0m Error:
log-in to see details

Args:
map[Expression:kzalloc\(sizeof\(struct i2c_adapter]

Results:
map[Output:]

433/2 2026/07/30 13:23 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 112331
							output: 22
							thoughts: 22
						

Thoughts:
Here's my thought process, as if I were considering this search:

**Diving into Kernel Memory Allocation**

Okay, so I need to track down specific instances of kernel memory allocation. My mind immediately goes to `kzalloc`, a key function for zero-initialized allocation. Given that, I want to find where we're allocating memory for some data structure, probably a driver adapter. The `sizeof(*adap` and `sizeof(*adapter` variations should catch most occurrences where we're calculating memory needs. The `*` indicates a pointer dereference, which is the crucial bit. By using `sizeof` with a dereferenced pointer, we calculate the size required for the *structure* pointed to by the adapter pointer. This approach is much safer than just hardcoding a size. This will help me locate all calls to `kzalloc` related to a specific struct type. That seems like a solid search strategy.



434/2 2026/07/30 13:23 tool grepper
0m Args:
map[Expression:kzalloc\(sizeof\(\*adap]

Results:
map[Output:drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c=6571=static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
--
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c-6636-	adapter->msg_enable = DFLT_MSG_ENABLE;
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c:6637:	adapter->mbox_log = kzalloc(sizeof(*adapter->mbox_log) +
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c-6638-				    (sizeof(struct mbox_cmd) *
--
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c=2895=static int cxgb4vf_pci_probe(struct pci_dev *pdev,
--
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c-2946-
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c:2947:	adapter->mbox_log = kzalloc(sizeof(*adapter->mbox_log) +
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c-2948-				    (sizeof(struct mbox_cmd) *
]

435/2 2026/07/30 13:23 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 112948
							output: 24
							thoughts: 35
						

Thoughts:
**Navigating the Driver Landscape**

Okay, hold on a second. I was initially thinking `cxgb4` was related to I2C, but that doesn't seem right. That was a hasty assumption. I need to be more precise in my search. My intuition is telling me that the relevant code will be using something like `kzalloc` which is a good indicator of memory allocation within a kernel driver. So, instead of looking at the initial assumption, I need to focus my search on the I2C bus drivers. Let's start with a focused search within the `drivers/i2c/busses/` directory and see where that leads. That should give me the I2C bus driver and I will then be able to assess the code associated with memory allocation for the driver.



436/2 2026/07/30 13:23 tool grepper
0m Args:
map[Expression:kzalloc.*sizeof.*i2c_adapter]

Results:
map[Output:drivers/i2c/busses/i2c-cbus-gpio.c=210=static int cbus_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-cbus-gpio.c-214-
drivers/i2c/busses/i2c-cbus-gpio.c:215:	adapter = devm_kzalloc(&pdev->dev, sizeof(struct i2c_adapter),
drivers/i2c/busses/i2c-cbus-gpio.c-216-			       GFP_KERNEL);
--
drivers/i2c/busses/i2c-cp2615.c=282=cp2615_i2c_probe(struct usb_interface *usbif, const struct usb_device_id *id)
--
drivers/i2c/busses/i2c-cp2615.c-295-
drivers/i2c/busses/i2c-cp2615.c:296:	adap = devm_kzalloc(&usbif->dev, sizeof(struct i2c_adapter), GFP_KERNEL);
drivers/i2c/busses/i2c-cp2615.c-297-	if (!adap)
]

437/2 2026/07/30 13:23 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 113506
							output: 49
							thoughts: 39
						

Thoughts:
Okay, here's my interpretation of those thoughts, tailored for an expert audience, presented in the first person:

**Initial Assessment: i2c-cp2615 - Ah, a USB I2C Adapter**

Right, so the `i2c-cp2615`… that clicks immediately. It's a USB-to-I2C adapter, probably using the Silicon Labs CP2615 chip, from what I recall of the naming scheme. Always good to quickly identify the hardware in play. Now, let's dive into the details. I need to refresh my memory on the implementation. Let's start with `i2c-cp2615.c`. That should give a good overview of the driver's architecture, register mappings, and interaction with the underlying USB subsystem.



438/2 2026/07/30 13:24 tool read-file
0m Args:
map[File:drivers/i2c/busses/i2c-cp2615.c FirstLine:280 LineCount:100]

Results:
map[Contents: 280:	
 281:	static int
 282:	cp2615_i2c_probe(struct usb_interface *usbif, const struct usb_device_id *id)
 283:	{
 284:		int ret = 0;
 285:		struct i2c_adapter *adap;
 286:		struct usb_device *usbdev = interface_to_usbdev(usbif);
 287:	
 288:		ret = usb_set_interface(usbdev, IOP_IFN, IOP_ALTSETTING);
 289:		if (ret)
 290:			return ret;
 291:	
 292:		ret = cp2615_check_iop(usbif);
 293:		if (ret)
 294:			return ret;
 295:	
 296:		adap = devm_kzalloc(&usbif->dev, sizeof(struct i2c_adapter), GFP_KERNEL);
 297:		if (!adap)
 298:			return -ENOMEM;
 299:	
 300:		if (!usbdev->serial)
 301:			return -EINVAL;
 302:	
 303:		strscpy(adap->name, usbdev->serial, sizeof(adap->name));
 304:		adap->owner = THIS_MODULE;
 305:		adap->dev.parent = &usbif->dev;
 306:		adap->dev.of_node = usbif->dev.of_node;
 307:		adap->timeout = HZ;
 308:		adap->algo = &cp2615_i2c_algo;
 309:		adap->quirks = &cp2615_i2c_quirks;
 310:		adap->algo_data = usbif;
 311:	
 312:		ret = i2c_add_adapter(adap);
 313:		if (ret)
 314:			return ret;
 315:	
 316:		usb_set_intfdata(usbif, adap);
 317:		return 0;
 318:	}
 319:	
 320:	static const struct usb_device_id id_table[] = {
 321:		{ USB_DEVICE_INTERFACE_NUMBER(CP2615_VID, CP2615_PID, IOP_IFN) },
 322:		{ }
 323:	};
 324:	
 325:	MODULE_DEVICE_TABLE(usb, id_table);
 326:	
 327:	static struct usb_driver cp2615_i2c_driver = {
 328:		.name = "i2c-cp2615",
 329:		.probe = cp2615_i2c_probe,
 330:		.disconnect = cp2615_i2c_disconnect,
 331:		.id_table = id_table,
 332:	};
 333:	
 334:	module_usb_driver(cp2615_i2c_driver);
 335:	
 336:	MODULE_AUTHOR("Bence CsΓ³kΓ‘s <bence98@sch.bme.hu>");
 337:	MODULE_DESCRIPTION("CP2615 I2C bus driver");
 338:	MODULE_LICENSE("GPL");
]

439/2 2026/07/30 13:24 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 114698
							output: 48
							thoughts: 82
						

Thoughts:
**Memory Management Considerations in `cp2615_i2c_probe`**

Okay, hold on a second. I'm just looking over this `cp2615_i2c_probe` function, and my immediate thought is "Aha! `devm_kzalloc`!" That's a key detail. The use of `devm_kzalloc` is telling me that the allocated memory is *managed* by the device driver's resource management framework. This has significant implications for its lifecycle. Specifically, if `devm_kzalloc` is used, the allocated memory is automatically freed when the device is unbound. I know this because `devm_kzalloc` ties the memory to the lifetime of the device. That unbinding happens when the `usb_driver.disconnect` callback function returns, and the device is then released.

So, the next logical step here is to confirm this understanding, and to look at `cp2615_i2c_disconnect`. I need to verify that there isn't any redundant or contradictory memory management happening. I'm betting that the framework is handling the cleanup automatically, but I need to confirm this assumption. Let's see what's in there...



440/2 2026/07/30 13:24 tool read-file
0m Args:
map[File:drivers/i2c/busses/i2c-cp2615.c FirstLine:270 LineCount:20]

Results:
map[Contents: 270:		.max_comb_2nd_msg_len = MAX_I2C_SIZE
 271:	};
 272:	
 273:	static void cp2615_i2c_disconnect(struct usb_interface *usbif)
 274:	{
 275:		struct i2c_adapter *adap = usb_get_intfdata(usbif);
 276:	
 277:		usb_set_intfdata(usbif, NULL);
 278:		i2c_del_adapter(adap);
 279:	}
 280:	
 281:	static int
 282:	cp2615_i2c_probe(struct usb_interface *usbif, const struct usb_device_id *id)
 283:	{
 284:		int ret = 0;
 285:		struct i2c_adapter *adap;
 286:		struct usb_device *usbdev = interface_to_usbdev(usbif);
 287:	
 288:		ret = usb_set_interface(usbdev, IOP_IFN, IOP_ALTSETTING);
 289:		if (ret)
]

441/2 2026/07/30 13:24 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 115420
							output: 24
							thoughts: 78
						

Thoughts:
**Debugging the I2C Adapter Unregistration**

Okay, hold on a second. I need to re-evaluate what I just assumed. Looking back at the code, specifically at `cp2615_i2c_disconnect`, I see that it actually *does* call `i2c_del_adapter(adap)`. This means the I2C adapter *is* being unregistered properly before the memory is freed by `devm`. So, my initial hunch about the `cp2615` driver being the culprit is incorrect. That's a relief, but also means I'm back to square one.

Now, let's shift focus. What about the `i2c-diolan-u2c` driver? Could the issue lie there? I need to investigate that code path next.



442/2 2026/07/30 13:24 tool grepper
0m Args:
map[Expression:kzalloc.*sizeof.*i2c_adapter]

Results:
map[Output:drivers/i2c/busses/i2c-cbus-gpio.c=210=static int cbus_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-cbus-gpio.c-214-
drivers/i2c/busses/i2c-cbus-gpio.c:215:	adapter = devm_kzalloc(&pdev->dev, sizeof(struct i2c_adapter),
drivers/i2c/busses/i2c-cbus-gpio.c-216-			       GFP_KERNEL);
--
drivers/i2c/busses/i2c-cp2615.c=282=cp2615_i2c_probe(struct usb_interface *usbif, const struct usb_device_id *id)
--
drivers/i2c/busses/i2c-cp2615.c-295-
drivers/i2c/busses/i2c-cp2615.c:296:	adap = devm_kzalloc(&usbif->dev, sizeof(struct i2c_adapter), GFP_KERNEL);
drivers/i2c/busses/i2c-cp2615.c-297-	if (!adap)
]

443/2 2026/07/30 13:24 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 116028
							output: 23
							thoughts: 4467
						

Thoughts:
**Analyzing a Use-After-Free in the I2C Subsystem**

Okay, so I've got this UAF in the I2C code, specifically within `i2c_adapter_depth`, triggered by `i2c_adapter_lock_bus`. The initial clues are pointing me toward issues with the adapter object. It looks like `i2c_adapter_lock_bus` is indirectly being called from `i2cdev_ioctl_smbus`. That implies this is all coming from user space through an i2c device file.

I initially thought maybe the driver allocates a struct containing `i2c_adapter` as its *first* member, making the object size different than just `i2c_adapter`. But even a slightly larger object (2200 bytes) would still fall into the same `kmalloc-4k` pool. The UAF is specifically on a 4096-byte region. The bug report mentions an offset. The key is that the buggy address (264 bytes into the freed region) is offset from where `dev.parent` is, or where I *think* `dev.parent` is.

The crash is in `i2c_adapter_depth`, accessing `adapter->dev.parent`. Now, the crucial part is understanding what `parent->type` actually points to. The stack trace leads to `rt_mutex_lock_nested` which uses `i2c_adapter_depth`. That's where the problem arises: an access within a locked operation. The UAF must be happening *during* the parent traversal within `i2c_adapter_depth`.

I need to understand the memory layout of `i2c_adapter` and `device` precisely. I need to make sure I get the offset of `dev.parent` right. `dev` is at the offset of the fields before it which add up to around 192 bytes. `dev.parent` is at `192+ 64 = 256` because `kobject` (which is included in `dev`) is 64 bytes if `CONFIG_DEBUG_KOBJECT_RELEASE` is not enabled, and thus `dev.p` is at `192 + 72 = 264`.

The UAF is reported to be at offset 264 of a 4096 byte block. Thus, `dev.p` is being accessed.

The crucial thought comes next. If the access is to `parent->type`, then `parent` is a pointer to another object. If the object being read into `parent` is at 256, and the access is at 264, the read is accessing what should be in the `dev.p` field!

This must be a UAF of the pointer! Something is dereferencing `adapter->dev.parent`, which now contains a dangling pointer, leading to a read at the *reported* offset of 264. Now to figure out how `dev.p` ends up as a pointer to freed memory!

The allocation trace, however, shows that it was originally allocated for `sk_buff` data. That means this is a dangling pointer!

The key is in `i2cdev_ioctl`, which gets the `adapter` from a `client` structure associated with an i2c device file. This structure points to the `i2c_adapter` struct. It looks like it is obtained using `i2c_get_adapter(minor)`. If the `i2c_adapter` gets freed *after* the device file has been opened, but before it is closed, then the UAF can occur.

I now need to identify what 4096-byte object could contain an `i2c_adapter` *and* be freed prematurely.



444/2 2026/07/30 13:24 tool codesearch-struct-layout
0m Args:
map[Name:cx231xx]

Results:
map[Fields:[map[Name:name OffsetBits:0 SizeBits:240] map[Name:model OffsetBits:256 SizeBits:32] map[Name:devno OffsetBits:288 SizeBits:32] map[Name:dev OffsetBits:320 SizeBits:64] map[Name:board OffsetBits:384 SizeBits:1984] map[Name:init_data OffsetBits:2368 SizeBits:448] map[Name:ir_i2c_client OffsetBits:2816 SizeBits:64] map[Name:stream_on OffsetBits:2880 SizeBits:1] map[Name:vbi_stream_on OffsetBits:2881 SizeBits:1] map[Name:has_audio_class OffsetBits:2882 SizeBits:1] map[Name:has_alsa_audio OffsetBits:2883 SizeBits:1] map[Name:i2c_scan_running OffsetBits:2884 SizeBits:1] map[Name:format OffsetBits:2944 SizeBits:64] map[Name:v4l2_dev OffsetBits:3008 SizeBits:1984] map[Name:sd_cx25840 OffsetBits:4992 SizeBits:64] map[Name:sd_tuner OffsetBits:5056 SizeBits:64] map[Name:ctrl_handler OffsetBits:5120 SizeBits:2432] map[Name:radio_ctrl_handler OffsetBits:7552 SizeBits:2432] map[Name:mpeg_ctrl_handler OffsetBits:9984 SizeBits:4672] map[Name:wq_trigger OffsetBits:14656 SizeBits:576] map[Name:stream_started OffsetBits:15232 SizeBits:32] map[Name:devlist OffsetBits:15296 SizeBits:128] map[Name:tuner_type OffsetBits:15424 SizeBits:32] map[Name:tuner_addr OffsetBits:15456 SizeBits:32] map[Name:i2c_bus OffsetBits:15488 SizeBits:51648] map[Name:muxc OffsetBits:67136 SizeBits:64] map[Name:i2c_mux_adap OffsetBits:67200 SizeBits:128] map[Name:xc_fw_load_done OffsetBits:67328 SizeBits:1] map[Name:port_3_switch_enabled OffsetBits:67329 SizeBits:1] map[Name:gpio_i2c_lock OffsetBits:67392 SizeBits:1024] map[Name:i2c_lock OffsetBits:68416 SizeBits:1024] map[Name:users OffsetBits:69440 SizeBits:32] map[Name:vdev OffsetBits:69504 SizeBits:16064] map[Name:norm OffsetBits:85568 SizeBits:64] map[Name:ctl_freq OffsetBits:85632 SizeBits:32] map[Name:ctl_ainput OffsetBits:85664 SizeBits:32] map[Name:width OffsetBits:85696 SizeBits:32] map[Name:height OffsetBits:85728 SizeBits:32] map[Name:interlaced OffsetBits:85760 SizeBits:32] map[Name:size OffsetBits:85792 SizeBits:32] map[Name:adev OffsetBits:85824 SizeBits:2752] map[Name:state OffsetBits:88576 SizeBits:32] map[Name:request_module_wk OffsetBits:88640 SizeBits:576] map[Name:lock OffsetBits:89216 SizeBits:1024] map[Name:ctrl_urb_lock OffsetBits:90240 SizeBits:1024] map[Name:inqueue OffsetBits:91264 SizeBits:128] map[Name:outqueue OffsetBits:91392 SizeBits:128] map[Name:open OffsetBits:91520 SizeBits:1152] map[Name:wait_frame OffsetBits:92672 SizeBits:1152] map[Name:wait_stream OffsetBits:93824 SizeBits:1152] map[Name:vbi_dev OffsetBits:94976 SizeBits:16064] map[Name:radio_dev OffsetBits:111040 SizeBits:16064] map[Name:media_dev OffsetBits:127104 SizeBits:64] map[Name:video_pad OffsetBits:127168 SizeBits:512] map[Name:vbi_pad OffsetBits:127680 SizeBits:512] map[Name:input_ent OffsetBits:128192 SizeBits:3840] map[Name:input_pad OffsetBits:132032 SizeBits:2048] map[Name:vidq OffsetBits:134080 SizeBits:5568] map[Name:vbiq OffsetBits:139648 SizeBits:5568] map[Name:eedata OffsetBits:145216 SizeBits:2048] map[Name:video_mode OffsetBits:147264 SizeBits:4480] map[Name:vbi_mode OffsetBits:151744 SizeBits:4480] map[Name:sliced_cc_mode OffsetBits:156224 SizeBits:4480] map[Name:ts1_mode OffsetBits:160704 SizeBits:4480] map[Name:devlist_count OffsetBits:165184 SizeBits:32] map[Name:udev OffsetBits:165248 SizeBits:64] map[Name:urb_buf OffsetBits:165312 SizeBits:640] map[Name:cx231xx_read_ctrl_reg OffsetBits:165952 SizeBits:64] map[Name:cx231xx_write_ctrl_reg OffsetBits:166016 SizeBits:64] map[Name:cx231xx_send_usb_command OffsetBits:166080 SizeBits:64] map[Name:cx231xx_gpio_i2c_read OffsetBits:166144 SizeBits:64] map[Name:cx231xx_gpio_i2c_write OffsetBits:166208 SizeBits:64] map[Name:cx231xx_set_analog_freq OffsetBits:166272 SizeBits:64] map[Name:cx231xx_reset_analog_tuner OffsetBits:166336 SizeBits:64] map[Name:mode OffsetBits:166400 SizeBits:32] map[Name:dvb OffsetBits:166464 SizeBits:64] map[Name:current_pcb_config OffsetBits:166528 SizeBits:608] map[Name:current_scenario_idx OffsetBits:167136 SizeBits:8] map[Name:interface_count OffsetBits:167144 SizeBits:8] map[Name:max_iad_interface_count OffsetBits:167152 SizeBits:8] map[Name:gpio_dir OffsetBits:167168 SizeBits:32] map[Name:gpio_val OffsetBits:167200 SizeBits:32] map[Name:power_mode OffsetBits:167232 SizeBits:32] map[Name:afe_mode OffsetBits:167264 SizeBits:32] map[Name:afe_ref_count OffsetBits:167296 SizeBits:32] map[Name:video_input OffsetBits:167328 SizeBits:32] map[Name:active_mode OffsetBits:167360 SizeBits:32] map[Name:vbi_or_sliced_cc_mode OffsetBits:167392 SizeBits:8] map[Name:std_mode OffsetBits:167424 SizeBits:32] map[Name:mode_tv OffsetBits:167456 SizeBits:8] map[Name:USE_ISO OffsetBits:167464 SizeBits:8] map[Name:encodernorm OffsetBits:167488 SizeBits:192] map[Name:ts1 OffsetBits:167680 SizeBits:2112] map[Name:ts2 OffsetBits:169792 SizeBits:2112] map[Name:mpegq OffsetBits:171904 SizeBits:5568] map[Name:v4l_device OffsetBits:177472 SizeBits:16064] map[Name:v4l_reader_count OffsetBits:193536 SizeBits:32] map[Name:freq OffsetBits:193568 SizeBits:32] map[Name:input OffsetBits:193600 SizeBits:32] map[Name:cx23417_mailbox OffsetBits:193632 SizeBits:32] map[Name:lmmio OffsetBits:193664 SizeBits:64] map[Name:bmmio OffsetBits:193728 SizeBits:64]]]

445/2 2026/07/30 13:24 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 123895
							output: 37
							thoughts: 3689
						

Thoughts:
**Analyzing the UAF in `i2c_adapter_depth` and `i2c_adapter_lock_bus`**

Okay, so I'm digging into this Use-After-Free (UAF) issue in the I2C core, specifically within `i2c_adapter_depth` and `i2c_adapter_lock_bus`. The crash report points to an 8-byte read at address `0x108` (264) offset, and the goal is to understand what's happening at that specific memory location.

First, I need to figure out what's at offset 264 within the `struct i2c_adapter`. I know that the `struct i2c_adapter` itself, is allocated on the `kmalloc-4k`. I remember that `struct i2c_adapter` is allocated with `kzalloc`, so all members should be initialized. I calculated before that the size of `struct i2c_adapter` is 2128 bytes, which fits within `kmalloc-4k`.

I already calculated that `dev.parent` is at offset 256. But the bug is at offset 264.

I have to carefully consider the layout of `struct i2c_adapter` and how the `dev` member (a `struct device`) is positioned, particularly its `parent` member which is a pointer. If the size of `struct rt_mutex` is altered due to `CONFIG_LOCKDEP` or other factors, the offsets of subsequent members change. The assumption is that `dev.parent` is read, but something else might be going on, like `rt_mutex_lock_nested` also reading something at offset 264.

The code in `i2c_adapter_depth` is crucial: `parent = adapter->dev.parent; parent = parent->parent` and that reads `dev.parent` which is at offset 256. But the UAF is at offset 264. The potential read comes from `parent->type`. If the `parent` points to `&adapter->dev` then it might read the `dev.type`, which is at offset 280. I need to understand how `parent` is being corrupted to point to an invalid memory location or a freed object, leading to the UAF. The key must be in the `parent = adapter->dev.parent` assignment.

It's possible that the UAF isn't a direct read of `adapter->dev.parent`, which is at offset 256. It might be in the subsequent read of `parent->type`. If `adapter` is the freed object, then `adapter->dev.parent` is the address that was freed, and the crash should happen immediately when `parent` is read, since it should be invalid. But the read is not at offset 256, but at 264, which is the key.

Could the UAF be triggered in `rt_mutex_lock_nested` when it accesses the mutex? If so, does `rt_mutex_lock_nested` access offset 264 somehow? The address for bus_lock is at offset 40, so it should not read at offset 264.

I check `offsetof(struct i2c_adapter, dev)` again. It appears that `dev` is at 192, and therefore `dev.parent` is at `192 + 64 = 256`. The UAF occurs when reading at 264, so it's not the `dev.parent` but rather `dev.p`. But there is no field `p` in `dev`.

The important hint is, what is at 264? If `dev.parent` is at 256, is it possible for some other field to be at 264? My current structure calculation points to offset 256 (dev.parent) and a 64 bytes offset from that location. That is the size of `struct kobject`. Since `dev.parent` is actually a pointer to the `struct device` kobject, I now need to think about cases when `struct kobject` size is 72 bytes. The kobject size can be 72 bytes if `CONFIG_DEBUG_KOBJECT_RELEASE` is enabled. If it is, then `dev.parent` is at `192 + 72 = 264`. And that means there's a problem with kobject size calculation.

Now I have to rethink how `struct kobject` is constructed. It can be 64 bytes if `CONFIG_DEBUG_KOBJECT_RELEASE` is not set. Now, the new assumption is


446/2 2026/07/30 13:25 tool read-file
0m Args:
map[File:include/linux/i2c.h FirstLine:700 LineCount:50]

Results:
map[Contents: 700:	struct i2c_adapter_quirks {
 701:		u64 flags;
 702:		int max_num_msgs;
 703:		u16 max_write_len;
 704:		u16 max_read_len;
 705:		u16 max_comb_1st_msg_len;
 706:		u16 max_comb_2nd_msg_len;
 707:	};
 708:	
 709:	/* enforce max_num_msgs = 2 and use max_comb_*_len for length checks */
 710:	#define I2C_AQ_COMB			BIT(0)
 711:	/* first combined message must be write */
 712:	#define I2C_AQ_COMB_WRITE_FIRST		BIT(1)
 713:	/* second combined message must be read */
 714:	#define I2C_AQ_COMB_READ_SECOND		BIT(2)
 715:	/* both combined messages must have the same target address */
 716:	#define I2C_AQ_COMB_SAME_ADDR		BIT(3)
 717:	/* convenience macro for typical write-then read case */
 718:	#define I2C_AQ_COMB_WRITE_THEN_READ	(I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST | \
 719:						 I2C_AQ_COMB_READ_SECOND | I2C_AQ_COMB_SAME_ADDR)
 720:	/* clock stretching is not supported */
 721:	#define I2C_AQ_NO_CLK_STRETCH		BIT(4)
 722:	/* message cannot have length of 0 */
 723:	#define I2C_AQ_NO_ZERO_LEN_READ		BIT(5)
 724:	#define I2C_AQ_NO_ZERO_LEN_WRITE	BIT(6)
 725:	#define I2C_AQ_NO_ZERO_LEN		(I2C_AQ_NO_ZERO_LEN_READ | I2C_AQ_NO_ZERO_LEN_WRITE)
 726:	/* adapter cannot do repeated START */
 727:	#define I2C_AQ_NO_REP_START		BIT(7)
 728:	
 729:	/*
 730:	 * i2c_adapter is the structure used to identify a physical i2c bus along
 731:	 * with the access algorithms necessary to access it.
 732:	 */
 733:	struct i2c_adapter {
 734:		struct module *owner;
 735:		unsigned int class;		  /* classes to allow probing for */
 736:		const struct i2c_algorithm *algo; /* the algorithm to access the bus */
 737:		void *algo_data;
 738:	
 739:		/* data fields that are valid for all devices	*/
 740:		const struct i2c_lock_operations *lock_ops;
 741:		struct rt_mutex bus_lock;
 742:		struct rt_mutex mux_lock;
 743:	
 744:		int timeout;			/* in jiffies */
 745:		int retries;
 746:		struct device dev;		/* the adapter device */
 747:		unsigned long locked_flags;	/* owned by the I2C core */
 748:	#define I2C_ALF_IS_SUSPENDED		0
 749:	#define I2C_ALF_SUSPEND_REPORTED	1
]

447/2 2026/07/30 13:25 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 129606
							output: 26
							thoughts: 2606
						

Thoughts:
**Analyzing the KASAN UAF in i2c_adapter_lock_bus**

Okay, so the initial confusion was about the offset of `dev.parent`. I initially thought it was at 192, but after checking the `codesearch-struct-layout` output for `i2c_adapter`, it’s actually at offset 304, meaning `dev.parent` is at 368. Still, the KASAN report indicates an access at offset 264. That doesn't add up... Now the question is what's at offset 264, or close to it? Digging deeper into `codesearch-struct-layout`,  I found `mux_lock` starts at 168 bytes and is 128 bytes in size, thus, it goes up to 296 bytes. Therefore, offset 264 *is* within `mux_lock`, which is a `rt_mutex`. I need to figure out the layout of `rt_mutex`. It's comprised of a `rt_mutex_base` and a lockdep map, or a `dep_map`. Since `rt_mutex` is 128 bytes, and `rt_mutex_base` is 84 bytes plus some padding, the `dep_map` must begin at offset 88. And `lockdep_map` is made of some pointers and string constants.

Okay, back to the problem: the UAF is at offset 264. I was initially focused on how the `i2c_adapter` itself is structured, but now I'm thinking the bug lies in how the object referenced by `adapter->dev.parent` is structured. The key here is *why* the read is happening at offset 264 *inside* the structure, which is not what `i2c_adapter_lock_bus` should be touching! The code accessing the potentially freed object is in `i2c_adapter_depth`. And there, the code iterates up the device tree via `parent = adapter->dev.parent; parent = parent->parent;`. What's the assumption here? That the `parent` fields are intact. The report says the UAF is at 264, but no fields within i2c_adapter are near 264.

What if *`adapter->dev.parent`* is the freed object, meaning it's been corrupted, or is pointing to a freed object. Then reading into a freed object could generate the KASAN report, but 264 is the mystery. If `adapter->dev.parent` points to the freed object, then `parent` becomes the freed object. If so, and we attempt to read `parent->type`, that's at offset 88, which is not 264. Perhaps it is `parent->parent` at offset 64, this still doesn't explain the 264. The report says the UAF read is at `i2c_adapter_depth` line 1243. The read is `parent = parent->parent` at 64 bytes.

Now I am thinking that `adapter` is not a `struct i2c_adapter` itself. But it is passed to a function that uses fields in a `struct i2c_adapter`. What if `adapter->dev.parent` points to something else? What if it's pointing to the freed object? What is that freed object, and what is *in* it at offset 264?

I know `go7007` is allocated with `kzalloc(sizeof(struct go7007)`, and that is 8522 bytes, so kmalloc-16k, it can not be the object. And `au0828_dev` is allocated with kzalloc as well, and it is also way bigger than 4096.

Could it be that the freed object is `struct i2c_adapter`? I need to look for `kzalloc` of `i2c_adapter` without freeing it properly, but I am finding instances that use `devm_kzalloc`, which should handle the freeing properly!

I need to search more broadly, and specifically for allocation and *use* to track down what this freed object is!



448/2 2026/07/30 13:25 tool grepper
0m Args:
map[Expression:kzalloc.*sizeof.*\b(adapter|adap)\b]

Results:
map[Output:drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c=287=int sun4i_hdmi_i2c_create(struct device *dev, struct sun4i_hdmi *hdmi)
--
drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c-299-
drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c:300:	adap = devm_kzalloc(dev, sizeof(*adap), GFP_KERNEL);
drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c-301-	if (!adap)
--
drivers/i2c/busses/i2c-cht-wc.c=426=static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-cht-wc.c-436-
drivers/i2c/busses/i2c-cht-wc.c:437:	adap = devm_kzalloc(&pdev->dev, sizeof(*adap), GFP_KERNEL);
drivers/i2c/busses/i2c-cht-wc.c-438-	if (!adap)
--
drivers/i2c/busses/i2c-opal.c=196=static int i2c_opal_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-opal.c-211-
drivers/i2c/busses/i2c-opal.c:212:	adapter = devm_kzalloc(&pdev->dev, sizeof(*adapter), GFP_KERNEL);
drivers/i2c/busses/i2c-opal.c-213-	if (!adapter)
--
drivers/media/platform/amlogic/c3/mipi-adapter/c3-mipi-adap.c=762=static int c3_mipi_adap_probe(struct platform_device *pdev)
--
drivers/media/platform/amlogic/c3/mipi-adapter/c3-mipi-adap.c-767-
drivers/media/platform/amlogic/c3/mipi-adapter/c3-mipi-adap.c:768:	adap = devm_kzalloc(dev, sizeof(*adap), GFP_KERNEL);
drivers/media/platform/amlogic/c3/mipi-adapter/c3-mipi-adap.c-769-	if (!adap)
--
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c=6571=static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
--
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c-6636-	adapter->msg_enable = DFLT_MSG_ENABLE;
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c:6637:	adapter->mbox_log = kzalloc(sizeof(*adapter->mbox_log) +
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c-6638-				    (sizeof(struct mbox_cmd) *
--
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c=2895=static int cxgb4vf_pci_probe(struct pci_dev *pdev,
--
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c-2946-
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c:2947:	adapter->mbox_log = kzalloc(sizeof(*adapter->mbox_log) +
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c-2948-				    (sizeof(struct mbox_cmd) *
--
drivers/net/ethernet/ibm/ehea/ehea_main.c=3366=static int ehea_probe_adapter(struct platform_device *dev)
--
drivers/net/ethernet/ibm/ehea/ehea_main.c-3381-
drivers/net/ethernet/ibm/ehea/ehea_main.c:3382:	adapter = devm_kzalloc(&dev->dev, sizeof(*adapter), GFP_KERNEL);
drivers/net/ethernet/ibm/ehea/ehea_main.c-3383-	if (!adapter) {
--
drivers/net/ethernet/ibm/ibmveth.c=2204=static void ibmveth_remove_buffer_from_pool_test(struct kunit *test)
drivers/net/ethernet/ibm/ibmveth.c-2205-{
drivers/net/ethernet/ibm/ibmveth.c:2206:	struct ibmveth_adapter *adapter = kunit_kzalloc(test, sizeof(*adapter), GFP_KERNEL);
drivers/net/ethernet/ibm/ibmveth.c-2207-	struct ibmveth_buff_pool *pool;
--
drivers/net/ethernet/ibm/ibmveth.c=2250=static void ibmveth_rxq_get_buffer_test(struct kunit *test)
drivers/net/ethernet/ibm/ibmveth.c-2251-{
drivers/net/ethernet/ibm/ibmveth.c:2252:	struct ibmveth_adapter *adapter = kunit_kzalloc(test, sizeof(*adapter), GFP_KERNEL);
drivers/net/ethernet/ibm/ibmveth.c-2253-	struct sk_buff *skb = kunit_kzalloc(test, sizeof(*skb), GFP_KERNEL);
--
drivers/usb/misc/usb-ljca.c=753=static int ljca_probe(struct usb_interface *interface,
--
drivers/usb/misc/usb-ljca.c-762-
drivers/usb/misc/usb-ljca.c:763:	adap = devm_kzalloc(dev, sizeof(*adap), GFP_KERNEL);
drivers/usb/misc/usb-ljca.c-764-	if (!adap)
]

449/2 2026/07/30 13:25 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 134754
							output: 40
							thoughts: 28
						

Thoughts:
Okay, here's my take on those thoughts, framed as my own:

**Digging into the `usb-ljca.c` Source**

Alright, hold on a second. It just hit me... doesn't `usb-ljca.c` handle the allocation of the `adap` structure? I need to verify this assumption. Let's fire up the source code for `usb-ljca.c` and make sure my memory is serving me correctly. That's a critical piece of the puzzle, and I need to be absolutely certain before I move forward. Gotta double-check those fundamentals!



450/2 2026/07/30 13:25 tool read-file
0m Args:
map[File:drivers/usb/misc/usb-ljca.c FirstLine:750 LineCount:50]

Results:
map[Contents: 750:		return ret;
 751:	}
 752:	
 753:	static int ljca_probe(struct usb_interface *interface,
 754:			      const struct usb_device_id *id)
 755:	{
 756:		struct usb_device *usb_dev = interface_to_usbdev(interface);
 757:		struct usb_host_interface *alt = interface->cur_altsetting;
 758:		struct usb_endpoint_descriptor *ep_in, *ep_out;
 759:		struct device *dev = &interface->dev;
 760:		struct ljca_adapter *adap;
 761:		int ret;
 762:	
 763:		adap = devm_kzalloc(dev, sizeof(*adap), GFP_KERNEL);
 764:		if (!adap)
 765:			return -ENOMEM;
 766:	
 767:		/* separate tx buffer allocation for alignment */
 768:		adap->tx_buf = devm_kzalloc(dev, LJCA_MAX_PACKET_SIZE, GFP_KERNEL);
 769:		if (!adap->tx_buf)
 770:			return -ENOMEM;
 771:		adap->tx_buf_len = LJCA_MAX_PACKET_SIZE;
 772:	
 773:		mutex_init(&adap->mutex);
 774:		spin_lock_init(&adap->lock);
 775:		init_completion(&adap->cmd_completion);
 776:		INIT_LIST_HEAD(&adap->client_list);
 777:	
 778:		adap->intf = interface;
 779:		adap->usb_dev = usb_dev;
 780:		adap->dev = dev;
 781:	
 782:		/*
 783:		 * find the first bulk in and out endpoints.
 784:		 * ignore any others.
 785:		 */
 786:		ret = usb_find_common_endpoints(alt, &ep_in, &ep_out, NULL, NULL);
 787:		if (ret) {
 788:			dev_err(dev, "bulk endpoints not found\n");
 789:			goto err_destroy_mutex;
 790:		}
 791:		adap->rx_pipe = usb_rcvbulkpipe(usb_dev, usb_endpoint_num(ep_in));
 792:		adap->tx_pipe = usb_sndbulkpipe(usb_dev, usb_endpoint_num(ep_out));
 793:	
 794:		/* setup rx buffer */
 795:		adap->rx_len = usb_endpoint_maxp(ep_in);
 796:		adap->rx_buf = devm_kzalloc(dev, adap->rx_len, GFP_KERNEL);
 797:		if (!adap->rx_buf) {
 798:			ret = -ENOMEM;
 799:			goto err_destroy_mutex;
]

451/2 2026/07/30 13:25 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 135767
							output: 20
							thoughts: 177
						

Thoughts:
**Debugging the `go7007` Driver**

Okay, hold on a second... I was operating under the assumption that `ljca_adapter` and `i2c_adapter` were the same thing. They're not. That's a misdirection. Let's refocus on that `go7007` bug we were looking at. I'm practically certain the problem stems from the `go7007_usb_probe` function. It seems like it's failing during allocation and hitting `allocfail`, which then leads to `go` getting freed *before* the `i2c_adapter` is unregistered. That's a classic race condition and likely memory corruption.

But wait a minute… the size reported by KASAN doesn’t match what I expect! The `go7007` structure is supposed to be 8524 bytes, but KASAN's reporting it as 4096 bytes? Could the `go7007` struct have been split into multiple allocations somehow? No, `go = kzalloc_obj(struct go7007);` explicitly allocates the entire struct in a single call.

Wait, the clue is in `kzalloc_obj`! Let's check that. Perhaps `kzalloc_obj` isn't behaving as I expect. It's time to dive into that function and understand its behavior in detail.



452/2 2026/07/30 13:26 tool grepper
0m Args:
map[Expression:#define kzalloc_obj]

Results:
map[Output:include/linux/slab.h=1070=void *kmalloc_nolock(size_t size, gfp_t gfp_flags, int node);
--
include/linux/slab.h-1151-/* All kzalloc aliases for kmalloc_(obj|objs|flex). */
include/linux/slab.h:1152:#define kzalloc_obj(P, ...) \
include/linux/slab.h-1153-	__alloc_objs(kzalloc, default_gfp(__VA_ARGS__), typeof(P), 1)
include/linux/slab.h:1154:#define kzalloc_objs(P, COUNT, ...) \
include/linux/slab.h-1155-	__alloc_objs(kzalloc, default_gfp(__VA_ARGS__), typeof(P), COUNT)
--
tools/include/linux/slab.h=200=static inline unsigned int kmem_cache_sheaf_size(struct slab_sheaf *sheaf)
--
tools/include/linux/slab.h-210-
tools/include/linux/slab.h:211:#define kzalloc_obj(P, ...) \
tools/include/linux/slab.h-212-	__alloc_objs(kzalloc, default_gfp(__VA_ARGS__), typeof(P), 1)
]

453/2 2026/07/30 13:26 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 136604
							output: 50
							thoughts: 1088
						

Thoughts:
**Debugging a Suspected UAF in USB Driver Code**

Okay, here's what's running through my head. KASAN reported a potential use-after-free issue, and I'm trying to trace it down. First, I'm thinking about the allocation size. `kzalloc_obj(struct go7007)` *should* allocate `sizeof(struct go7007)`, which based on the initial calculation using the interrupt data offset, *should* be 8522 bytes and go into a `kmalloc-16k` slab. But KASAN flagged `kmalloc-4k`, which doesn't make sense.  It is probably not `struct go7007`, or at least not what I initially thought. I need to make sure about the structure size. No `#ifdef` affects `struct go7007` so it should be a constant size, but I need to make sure.

Is it possible it is `struct go7007_usb`? No, that's tiny. What about an `i2c_adapter` allocated by `i2c_add_adapter`? No, `i2c_add_adapter` *doesn't* allocate it, it takes a pointer. And `i2c_client` is also small. Okay, so that's not it.

Let's shift gears. Could the problem be in the `au0828` driver? I'm looking at `au0828_usb_disconnect`. The key here seems to be the conditional flow after `au0828_analog_unregister`. If it returns 1, `v4l2_device_put(&dev->v4l2_dev)` is called. If that drops the last reference, `au0828_usb_v4l2_release` is called, which calls `au0828_usb_release(dev)`. That's the normal path. But what if it *doesn't* drop the last reference? Then `au0828_usb_release(dev)` isn't called, which means `dev` *isn't* freed. However, I think the USB device *is* being disconnected and presumably its resources freed even if `dev` remains. So, there shouldn't be a UAF of `dev`. Now, if `dev` isn't freed, and `dev->usbdev` is set to NULL, and the `i2c_adapter` isn't freed either, there's no UAF of the `i2c_adapter` as well.

But, if `v4l2_device_put` *does* drop the last reference, and `au0828_usb_release(dev)` is called... Then `dev` *is* freed! In `au0828_usb_release` the `au0828_i2c_unregister(dev)` function will get called, and that calls `i2c_del_adapter(&dev->i2c_adap)`. So, the `i2c_adapter` *is* unregistered *before* `dev` is freed. Seems safe. This is good.

So, let me check the `cx231xx` driver just in case. I need to look at `cx231xx_usb_disconnect` to see how it handles things...



454/2 2026/07/30 13:26 tool read-file
0m Args:
map[File:drivers/media/usb/cx231xx/cx231xx-cards.c FirstLine:1800 LineCount:50]

Results:
map[Contents:1800:		dev_dbg(d, "registering interface %d\n", ifnum);
1801:	
1802:		/* save our data pointer in this interface device */
1803:		usb_set_intfdata(interface, dev);
1804:	
1805:		/* Initialize the media controller */
1806:		retval = cx231xx_media_device_init(dev, udev);
1807:		if (retval) {
1808:			dev_err(d, "cx231xx_media_device_init failed\n");
1809:			goto err_media_init;
1810:		}
1811:	
1812:		/* Create v4l2 device */
1813:	#ifdef CONFIG_MEDIA_CONTROLLER
1814:		dev->v4l2_dev.mdev = dev->media_dev;
1815:	#endif
1816:		retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
1817:		if (retval) {
1818:			dev_err(d, "v4l2_device_register failed\n");
1819:			goto err_v4l2;
1820:		}
1821:	
1822:		/* allocate device struct */
1823:		retval = cx231xx_init_dev(dev, udev, nr);
1824:		if (retval)
1825:			goto err_init;
1826:	
1827:		retval = cx231xx_init_v4l2(dev, udev, interface, isoc_pipe);
1828:		if (retval)
1829:			goto err_init;
1830:	
1831:		if (dev->current_pcb_config.ts1_source != 0xff) {
1832:			/* compute alternate max packet sizes for TS1 */
1833:			idx = dev->current_pcb_config.hs_config_info[0].interface_info.ts1_index + 1;
1834:			if (idx >= dev->max_iad_interface_count) {
1835:				dev_err(d, "TS1 PCB interface #%d doesn't exist\n",
1836:					idx);
1837:				retval = -ENODEV;
1838:				goto err_video_alt;
1839:			}
1840:			uif = udev->actconfig->interface[idx];
1841:	
1842:			if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) {
1843:				retval = -ENODEV;
1844:				goto err_video_alt;
1845:			}
1846:	
1847:			dev->ts1_mode.end_point_addr =
1848:			    uif->altsetting[0].endpoint[isoc_pipe].
1849:					desc.bEndpointAddress;
]

455/2 2026/07/30 13:26 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 139313
							output: 22
							thoughts: 229
						

Thoughts:
**Investigating the Memory Footprint of `cx231xx`**

Okay, so I was under the impression that `cx231xx` was a 4096-byte object, but wait a minute, that's not right. The size, 193792 bits, actually translates to a significantly larger 24224 bytes. That's a huge discrepancy! I need to figure out what's going on.

Let's think through this systematically. Could this large object be a `struct i2c_adapter` allocated by `i2c_add_adapter`? No, that's incorrect. `i2c_add_adapter` doesn't allocate the `struct i2c_adapter` itself; it's a different mechanism. Okay, let's consider another common I2C structure. What if the object is a `struct i2c_client`? No, that's too small. The memory footprint wouldn't be this large. Okay... perhaps a `struct i2c_dev`?

Looking at the definition:

```c
struct i2c_dev {
	struct list_head list;
	struct i2c_adapter *adap;
	struct device *dev;
	struct cdev cdev;
};
```

That doesn't seem right either. `i2c_dev` is definitely a small structure. Hmm, what else could it be...wait, what if it's a `struct nsim_dev`? That seems like a reasonable possibility. Let's check the size of `sizeof(struct nsim_dev)` to see if it matches the value I'm seeing for `cx231xx`.



456/2 2026/07/30 13:26 tool codesearch-struct-layout
0m Args:
map[Name:nsim_dev]

Results:
map[Fields:[map[Name:nsim_bus_dev OffsetBits:0 SizeBits:64] map[Name:fib_data OffsetBits:64 SizeBits:64] map[Name:trap_data OffsetBits:128 SizeBits:64] map[Name:ddir OffsetBits:192 SizeBits:64] map[Name:ports_ddir OffsetBits:256 SizeBits:64] map[Name:take_snapshot OffsetBits:320 SizeBits:64] map[Name:nodes_ddir OffsetBits:384 SizeBits:64] map[Name:vfconfigs OffsetBits:448 SizeBits:64] map[Name:bpf_dev OffsetBits:512 SizeBits:64] map[Name:bpf_bind_accept OffsetBits:576 SizeBits:8] map[Name:bpf_bind_verifier_accept OffsetBits:584 SizeBits:8] map[Name:bpf_bind_verifier_delay OffsetBits:608 SizeBits:32] map[Name:ddir_bpf_bound_progs OffsetBits:640 SizeBits:64] map[Name:prog_id_gen OffsetBits:704 SizeBits:32] map[Name:bpf_bound_progs OffsetBits:768 SizeBits:128] map[Name:bpf_bound_maps OffsetBits:896 SizeBits:128] map[Name:progs_list_lock OffsetBits:1024 SizeBits:1024] map[Name:switch_id OffsetBits:2048 SizeBits:264] map[Name:port_list OffsetBits:2368 SizeBits:128] map[Name:fw_update_status OffsetBits:2496 SizeBits:8] map[Name:fw_update_overwrite_mask OffsetBits:2528 SizeBits:32] map[Name:fw_update_flash_chunk_time_ms OffsetBits:2560 SizeBits:32] map[Name:max_macs OffsetBits:2592 SizeBits:32] map[Name:test1 OffsetBits:2624 SizeBits:8] map[Name:test2 OffsetBits:2656 SizeBits:32] map[Name:dont_allow_reload OffsetBits:2688 SizeBits:8] map[Name:fail_reload OffsetBits:2696 SizeBits:8] map[Name:dummy_region OffsetBits:2752 SizeBits:64] map[Name:health OffsetBits:2816 SizeBits:320] map[Name:hwstats OffsetBits:3136 SizeBits:2816] map[Name:fa_cookie OffsetBits:5952 SizeBits:64] map[Name:fa_cookie_lock OffsetBits:6016 SizeBits:1024] map[Name:fail_trap_group_set OffsetBits:7040 SizeBits:8] map[Name:fail_trap_policer_set OffsetBits:7048 SizeBits:8] map[Name:fail_trap_policer_counter_get OffsetBits:7056 SizeBits:8] map[Name:fail_trap_drop_counter_get OffsetBits:7064 SizeBits:8] map[Name:udp_ports OffsetBits:7104 SizeBits:512] map[Name:psample OffsetBits:7616 SizeBits:64] map[Name:esw_mode OffsetBits:7680 SizeBits:16]]]

457/2 2026/07/30 13:26 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 140866
							output: 24
							thoughts: 4224
						

Thoughts:
**Analyzing a Suspected Use-After-Free in the I2C Subsystem**

Okay, so I'm digging into this KASAN report and trying to understand this use-after-free in the I2C subsystem.  First, the memory block size: it's *not* the 4096 bytes I initially thought, it's 962 bytes. But wait, it's a `sk_buff` data allocation, 4096 bytes! This means this memory used to be *sk_buff* data, then freed, and *then* reallocated as something else before being freed again, right? But KASAN only reports the LAST allocation and free.  If it *was* reallocated and then freed, KASAN would report the allocation of the *reallocated* object. Since KASAN reports the `sk_buff` data allocation, the memory wasn't reallocated after all!

The key is a *dangling pointer*. An `i2c_adapter` pointer is somehow accessing memory that was allocated as `sk_buff` data and was subsequently freed.  A `use-after-free` of a struct containing an `i2c_adapter` pointer.  `i2c_adapter_lock_bus` uses `struct i2c_adapter *adapter`. The trace leads to `i2cdev_ioctl`, which gets the `adapter` from `client->adapter` where `client` is `file->private_data`.

If `client->adapter` is pointing to the freed `sk_buff` data, either `client` is corrupted, or it's *itself* in the freed `sk_buff` data! If `client` is in the freed data, then `file->private_data` points to the freed `sk_buff` data. How could that happen? Maybe it's a file descriptor set by *another* driver and passed to `i2cdev_ioctl`? But `i2cdev_ioctl` is specifically for `/dev/i2c-X`, so the file descriptor *must* be valid for an I2C device.

`i2cdev_open` is what sets `file->private_data`, using a `kzalloc`'d `i2c_client`. `sizeof(struct i2c_client)` is small, so it *cannot* be the freed object. Therefore, `client->adapter` *must* be the dangling pointer to the freed `sk_buff` data.  In `i2cdev_open`, `client->adapter` is set to `adap`, which comes from `i2c_get_adapter(minor)`. `i2c_get_adapter` gets the `i2c_adapter` from `i2c_adapter_idr`.

Aha! If the `i2c_adapter` was freed *without* being removed from the `i2c_adapter_idr`, `i2c_get_adapter` would return a dangling pointer!  `i2c_add_adapter` puts it in the IDR.  If a driver frees the adapter *without* calling `i2c_del_adapter`, the dangling pointer remains in the IDR.  When userspace opens `/dev/i2c-X`, `i2c_get_adapter` finds the dangling pointer!

The mutex protection in `i2c_get_adapter` is important. It uses `try_module_get` on `adapter->owner` and then `get_device` to access `adapter->dev.kobj.kref`.  If the freed memory has `NULL` at the `owner` offset, `try_module_get` succeeds! Then `get_device` would be called. If the memory *was* reallocated as `sk_buff`, the `owner` member (at offset 0) would be NULL. But KASAN did *not* catch anything.

The clue here is *when* the memory was freed. It's when `i2c_get_adapter` is *called* that the memory has *not* been freed yet. *Then*, the allocation is `sk_buff` data. The memory allocation trace now makes sense! `i2c_get_adapter` reads the garbage from `sk_buff`, then `get_device` does it's work, which could modify the kref in the freed data! Then the `sk_buff` *is* freed!  `i2cdev_ioctl` then attempts to access the now-freed data.  *That* is the KASAN report!

The key here is that the driver has freed the `i2c_adapter` *without* calling `


458/2 2026/07/30 13:27 tool grepper
0m Error:
log-in to see details

Args:
map[Expression:i2c_add_adapter.*allocfail]

Results:
map[Output:]

459/2 2026/07/30 13:27 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 146153
							output: 28
							thoughts: 24
						

Thoughts:
Okay, here's my interpretation of those thoughts, tailored for an expert audience, and delivered as a first-person summary:

**Digging into I2C Adapter Driver Interactions**

Alright, I'm thinking I need to understand this driver better, specifically how it's managing its resources. I'm going to search for a specific pattern of function calls that are usually good indicators of potential issues or areas for deeper scrutiny. I'm going to look for instances where both `i2c_add_adapter` and `kfree` appear within the *same* function body. The `i2c_add_adapter` is the crucial call that registers the I2C adapter with the kernel, so I'm suspecting that I need to investigate the cleanup process, especially if memory is being allocated, then freed at that point. The use of `kfree` strongly suggests dynamic memory management is in play, so I want to know exactly how they are coupled: is the memory allocated when adding the adapter, and subsequently freed if the adapter is removed? Are there any obvious potential double-free scenarios or memory leaks if, say, the adapter initialization fails and the `i2c_add_adapter` never succeeds? I want to see *how* these two calls interact to find any areas that might warrant a closer look.



460/2 2026/07/30 13:27 tool grepper
0m Error:
log-in to see details

Args:
map[Expression:i2c_add_adapter.*\n.*\n.*kfree]

Results:
map[Output:]

461/2 2026/07/30 13:27 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 146496
							output: 25
							thoughts: 23
						

Thoughts:
Okay, here's my thought process summarized from the prompt, as if it were my own:

**Investigating Potential Code Issues**

Alright, I need to dig into some code. I have a hunch there might be some problematic control flow going on, specifically related to how an I2C adapter is added. My initial instinct is to look for a specific pattern: functions that call `i2c_add_adapter` *and* use `goto` statements within the same scope. The combination of those two elements often suggests a possible issue with resource management, error handling, or overall code clarity. I'm thinking perhaps a `goto` could bypass crucial cleanup steps in the event of an error during adapter addition, or maybe it’s just a symptom of poorly structured logic. Time to get my hands dirty and start searching.



462/2 2026/07/30 13:27 tool grepper
0m Error:
log-in to see details

Args:
map[Expression:i2c_add_adapter.*\n.*goto]

Results:
map[Output:]

463/2 2026/07/30 13:27 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 146730
							output: 33
							thoughts: 104
						

Thoughts:
**Debugging a Kernel Driver I2C Initialization**

Okay, so I'm chasing down this error, and it's got me thinking. `i2c_add_adapter` is supposed to return an error code, right? So the typical pattern I'd expect to see is:

```c
ret = i2c_add_adapter(&dev->i2c_adapter);
if (ret)
	goto err;
```

Pretty standard stuff. But here's the kicker: I'm specifically looking for a `goto` statement that appears *after* `i2c_add_adapter` *succeeds*. That's the unusual part. That's what I need to understand, since this is a kernel issue. It’s got my brain ticking. Let’s not overthink this – let’s go broad. Time to check `drivers/media/usb/` directory. Maybe that module is a reasonable place to start, given the USB context. Let's see what’s going on in those drivers. I’ll bet I can find some clues there.



464/2 2026/07/30 13:27 tool grepper
0m Args:
map[Expression:i2c_add_adapter PathPrefix:drivers/media/usb/]

Results:
map[Output:drivers/media/usb/au0828/au0828-i2c.c=354=int au0828_i2c_register(struct au0828_dev *dev)
--
drivers/media/usb/au0828/au0828-i2c.c-373-#endif
drivers/media/usb/au0828/au0828-i2c.c:374:	i2c_add_adapter(&dev->i2c_adap);
drivers/media/usb/au0828/au0828-i2c.c-375-
--
drivers/media/usb/cx231xx/cx231xx-i2c.c=514=int cx231xx_i2c_register(struct cx231xx_i2c *bus)
--
drivers/media/usb/cx231xx/cx231xx-i2c.c-527-	i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
drivers/media/usb/cx231xx/cx231xx-i2c.c:528:	bus->i2c_rc = i2c_add_adapter(&bus->i2c_adap);
drivers/media/usb/cx231xx/cx231xx-i2c.c-529-
--
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c=56=static int dvb_usbv2_i2c_init(struct dvb_usb_device *d)
--
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c-68-
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c:69:	ret = i2c_add_adapter(&d->i2c_adap);
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c-70-	if (ret < 0) {
--
drivers/media/usb/dvb-usb/dvb-usb-i2c.c=11=int dvb_usb_i2c_init(struct dvb_usb_device *d)
--
drivers/media/usb/dvb-usb/dvb-usb-i2c.c-30-
drivers/media/usb/dvb-usb/dvb-usb-i2c.c:31:	ret = i2c_add_adapter(&d->i2c_adap);
drivers/media/usb/dvb-usb/dvb-usb-i2c.c-32-	if (ret < 0) {
--
drivers/media/usb/em28xx/em28xx-i2c.c=970=int em28xx_i2c_register(struct em28xx *dev, unsigned int bus,
--
drivers/media/usb/em28xx/em28xx-i2c.c-991-
drivers/media/usb/em28xx/em28xx-i2c.c:992:	retval = i2c_add_adapter(&dev->i2c_adap[bus]);
drivers/media/usb/em28xx/em28xx-i2c.c-993-	if (retval < 0) {
drivers/media/usb/em28xx/em28xx-i2c.c-994-		dev_err(&dev->intf->dev,
drivers/media/usb/em28xx/em28xx-i2c.c:995:			"%s: i2c_add_adapter failed! retval [%d]\n",
drivers/media/usb/em28xx/em28xx-i2c.c-996-			__func__, retval);
--
drivers/media/usb/go7007/go7007-i2c.c=204=int go7007_i2c_init(struct go7007 *go)
--
drivers/media/usb/go7007/go7007-i2c.c-209-	i2c_set_adapdata(&go->i2c_adapter, go);
drivers/media/usb/go7007/go7007-i2c.c:210:	if (i2c_add_adapter(&go->i2c_adapter) < 0) {
drivers/media/usb/go7007/go7007-i2c.c-211-		dev_err(go->dev,
drivers/media/usb/go7007/go7007-i2c.c:212:			"go7007-i2c: error: i2c_add_adapter failed\n");
drivers/media/usb/go7007/go7007-i2c.c-213-		return -1;
--
drivers/media/usb/go7007/go7007-usb.c=1040=static int go7007_usb_probe(struct usb_interface *intf,
--
drivers/media/usb/go7007/go7007-usb.c-1171-		i2c_set_adapdata(&go->i2c_adapter, go);
drivers/media/usb/go7007/go7007-usb.c:1172:		if (i2c_add_adapter(&go->i2c_adapter) < 0) {
drivers/media/usb/go7007/go7007-usb.c:1173:			dev_err(go->dev, "error: i2c_add_adapter failed\n");
drivers/media/usb/go7007/go7007-usb.c-1174-			goto allocfail;
--
drivers/media/usb/hdpvr/hdpvr-i2c.c=180=int hdpvr_register_i2c_adapter(struct hdpvr_device *dev)
--
drivers/media/usb/hdpvr/hdpvr-i2c.c-188-
drivers/media/usb/hdpvr/hdpvr-i2c.c:189:	return i2c_add_adapter(&dev->i2c_adapter);
drivers/media/usb/hdpvr/hdpvr-i2c.c-190-}
--
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c=591=void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
--
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c-627-	i2c_set_adapdata(&hdw->i2c_adap, &hdw->v4l2_dev);
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c:628:	i2c_add_adapter(&hdw->i2c_adap);
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c-629-	if (hdw->i2c_func[0x18] == i2c_24xxx_ir) {
--
drivers/media/usb/stk1160/stk1160-i2c.c=247=int stk1160_i2c_register(struct stk1160 *dev)
--
drivers/media/usb/stk1160/stk1160-i2c.c-257-
drivers/media/usb/stk1160/stk1160-i2c.c:258:	rc = i2c_add_adapter(&dev->i2c_adap);
drivers/media/usb/stk1160/stk1160-i2c.c-259-	if (rc < 0) {
--
drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c=1597=static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
--
drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c-1655-
drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c:1656:	result = i2c_add_adapter(&ttusb->i2c_adap);
drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c-1657-	if (result)
]

465/2 2026/07/30 13:27 llm crash-repro-finder
2m Model:
gemini-3.1-pro-preview

Tokens:
							input: 149304
							output: 246
							thoughts: 16398
						

Thoughts:
**The Hunt for the Elusive UAF: A Journey Through USB and I2C**

Alright, buckle up, because I've been chasing a KASAN slab-use-after-free bug, and it's a wild ride. The initial clue points me towards `i2c_adapter_depth` function, which is reading memory it shouldn't. The real problem is likely not in this specific function but in the sequence of events that leads to this access.

First things first, I needed to figure out *which* I2C driver caused this UAF. I began by looking at all of the drivers which register an I2C adapter using `i2c_add_adapter` but potentially free the memory without removing the adapter. Scanning the code, I honed in on `go7007`, a USB-based video capture device. It turns out that `go7007` adds the I2C adapter but has a `goto allocfail` path that *skips* the unregistration of the I2C adapter under certain error conditions. This looks suspicious. It's the perfect setup for a use-after-free!

My next step: confirm that the `go7007` driver is responsible. To do so, I traced the memory allocation and potential free of the driver's struct. I made my calculations, the driver struct should be allocated from kmalloc-4k. I then reviewed KASAN reports and kernel configs. It appeared that, under particular configurations, the struct would indeed fit into a kmalloc-4k slab.

I then dug into the kernel code to find what was being freed after a call to `i2c_add_adapter` and which function was reading from the freed memory. The `go7007` driver calls `i2c_add_adapter` during its USB probe, and this call *succeeds*. After the adapter is registered, it checks for the existence of an endpoint, and if the endpoint is *not* present it frees the memory that contains the I2C adapter without removing it from the I2C subsystem.

From this insight, I put together the pieces to trigger a USB-related error during the `go7007_usb_probe` process. I hypothesized and confirmed that by crafting a specific USB device descriptor that omits an endpoint, I can force the `go7007` driver into the `allocfail` path. Doing so, it allocates an I2C adapter, registers it, and then frees the struct containing the adapter, but the adapter is still present within the I2C system. Then, when a user accesses `/dev/i2c-X` for that device, the UAF would occur when it attempts to call the function `i2c_adapter_depth`. I set out to construct a USB descriptor that would trigger the UAF.

Thus, my plan is to craft the specific USB descriptors that will trigger the bug, so that the I2C adapter remains registered, even though the driver's struct (and with it, the I2C adapter's underlying memory) is freed. Finally, I write a syzkaller program to trigger it. The syzkaller program will first connect the USB device, and then open `/dev/i2c-X` and perform an I2C transfer.

Bingo! That should do the trick! Now to translate this plan into a working testcase.



466/2 2026/07/30 13:29 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, AUTO, &AUTO={0, &AUTO="12010002000000403b0904a10100000000010902200001010080000904000002ff00ff000705840340000107058802400000", 0, 0, &AUTO=[{0x84, &AUTO="0000aa55"}]}, 0)
r1 = syz_open_dev$i2c(&AUTO='/dev/i2c-#\x00', 0, 0)
ioctl$I2C_SMBUS(r1, 0x720, &AUTO={0, 0, 0, &AUTO=""})
 Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

467/2 2026/07/30 13:29 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 166861
							output: 248
							thoughts: 494
						

Thoughts:
**Dissecting the `syz_usb_connect` Call**

Okay, so I'm looking at this `syz_usb_connect` call, and the key here is the `vusb_dev` argument, which is a union. That means I need to specify which union member to use, and it looks like we want the `@generic` option.

Now, let's break down the actual call:

```
r0 = syz_usb_connect(3, AUTO, &AUTO=@generic={0, &AUTO="12010002000000403b0904a10100000000010902200001010080000904000002ff00ff000705840340000107058802400000", 0, 0, &AUTO=[{0x84, &AUTO="0000aa55"}]}, 0)
```

The first thing to do is ensure the correct union field is assigned. Looks like `@generic` is what we want.

I need to map this to the `vusb_dev_generic` structure:

```
type vusb_dev_generic {
	type		const[0, int32]
	descriptors	ptr[in, array[int8]]
	bos_descriptor	ptr[in, array[int8]]
	ep0_responses	ptr[in, array[vusb_ep0_response]]
	ep_responses	ptr[in, array[vusb_ep_response]]
}
```

The `type` field is a `const[0, int32]`. So either `0` or `AUTO` should work, which is being handled in the code above.

The `descriptors` field is a `ptr[in, array[int8]]`. Good, we are using a literal, `&AUTO="1201..."`. That's a valid descriptor setup.

`bos_descriptor` is `ptr[in, array[int8]]`. We're setting that to `0`, which is fine.

`ep0_responses` is `ptr[in, array[vusb_ep0_response]]`. Zeroing it out, also reasonable.

Finally, `ep_responses` is `ptr[in, array[vusb_ep_response]]`. We are using `&AUTO=[{0x84, &AUTO="0000aa55"}]`, which looks like an endpoint response. Good.

I'm feeling confident about this, so I'm going to test the updated call and see how it goes.



468/2 2026/07/30 13:29 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, AUTO, &AUTO=@generic={0, &AUTO="12010002000000403b0904a10100000000010902200001010080000904000002ff00ff000705840340000107058802400000", 0, 0, &AUTO=[{0x84, &AUTO="0000aa55"}]}, 0)
r1 = syz_open_dev$i2c(&AUTO='/dev/i2c-#\x00', 0, 0)
ioctl$I2C_SMBUS(r1, 0x720, &AUTO={0, 0, 0, &AUTO=""})
 Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

469/2 2026/07/30 13:29 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 168413
							output: 19
							thoughts: 40
						

Thoughts:
Here's my thought process, as if I were considering this myself:

**Examining `syz_usb_connect`**

Okay, hold on a second. I have a hunch that the function signature for `syz_usb_connect` that I'm using in my syzlang descriptions might not be quite right. I need to make absolutely sure. The details matter, and a subtle mismatch could throw off my entire analysis or fuzzing strategy.

Right, so where's the canonical definition? I need to go straight to the source. Let me check the `vusb.txt` file. That's where the most up-to-date and accurate description of the `syz_usb_connect` function should be. I'll compare what I have in my descriptions with what's defined in `vusb.txt` to verify the argument types, the return value, and the overall structure. Gotta get this spot on.



470/2 2026/07/30 13:30 tool read-description
0m Args:
map[File:vusb.txt]

Results:
map[Output:# Copyright 2019 syzkaller project authors. All rights reserved.
# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

include <linux/types.h>
include <linux/byteorder/generic.h>

include <uapi/linux/usb/ch9.h>
include <uapi/linux/usb/ch11.h>

include <uapi/linux/usb/midi.h>
include <uapi/linux/usb/audio.h>
include <linux/usb/audio-v2.h>
include <linux/usb/audio-v3.h>
include <uapi/linux/hid.h>
include <linux/hid.h>
include <uapi/linux/usb/cdc.h>
include <uapi/linux/if_ether.h>
include <linux/interrupt.h>
include <linux/usb/cdc_ncm.h>
include <drivers/net/usb/asix.h>

# This is a special fd for USB fuzzing and should only be used with syz_usb_* pseudo-syscalls.
# We don't inherit it from the fd resource, to discourage syzkaller calling raw ioctls on it.
resource fd_usb[int32]: -1

# These are generic pseudo-syscalls for emulating arbitrary USB devices.
# They are mostly targeted to cover the enumeration process.
syz_usb_connect(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io(fd fd_usb, descs ptr[in, vusb_descriptors], resps ptr[in, vusb_responses]) (timeout[300], remote_cover)
syz_usb_ep_write(fd fd_usb, ep int8, len len[data], data ptr[in, array[int8, 0:256]]) (timeout[300], remote_cover)
syz_usb_ep_read(fd fd_usb, ep int8, len len[data], data buffer[out]) (timeout[300], remote_cover)
syz_usb_disconnect(fd fd_usb) (timeout[300], remote_cover)

usb_device_speed = USB_SPEED_UNKNOWN, USB_SPEED_LOW, USB_SPEED_FULL, USB_SPEED_HIGH, USB_SPEED_WIRELESS, USB_SPEED_SUPER, USB_SPEED_SUPER_PLUS

# TODO: consider patching idVendor and idProduct for all class specific descriptions in Go code to cover more drivers.
# TODO: custom syz_usb_ep_write() descriptions for all class specific descriptions.
# TODO: consider adding custom vusb_connect_descriptors definitions to all class specific descriptions.

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

type usb_device_descriptor_verbose_t[USB, CLASS, SUBCLASS, PROTOCOL, PACKET, VENDOR, PRODUCT, DEVICE, CFS] {
	bLength			const[USB_DT_DEVICE_SIZE, int8]
	bDescriptorType		const[USB_DT_DEVICE, int8]

	bcdUSB			USB
	bDeviceClass		const[CLASS, int8]
	bDeviceSubClass		const[SUBCLASS, int8]
	bDeviceProtocol		const[PROTOCOL, int8]
	bMaxPacketSize0		PACKET
	idVendor		const[VENDOR, int16]
	idProduct		const[PRODUCT, int16]
	bcdDevice		const[DEVICE, int16]
	iManufacturer		const[1, int8]
	iProduct		const[2, int8]
	iSerialNumber		const[3, int8]
	bNumConfigurations	len[configs, int8]

	configs			CFS
} [packed]

type usb_device_descriptor_t[CLASS, SUBCLASS, PROTOCOL, VENDOR, PRODUCT, DEVICE, CFS] usb_device_descriptor_verbose_t[flags[usb_versions, int16], CLASS, SUBCLASS, PROTOCOL, flags[usb_device_max_packet_sizes, int8], VENDOR, PRODUCT, DEVICE, CFS]
type usb_device_descriptor_fixed_t[USB, CLASS, SUBCLASS, PROTOCOL, PACKET, VENDOR, PRODUCT, DEVICE, CFS] usb_device_descriptor_verbose_t[const[USB, int16], CLASS, SUBCLASS, PROTOCOL, const[PACKET, int8], VENDOR, PRODUCT, DEVICE, CFS]

usb_versions = 0x110, 0x200, 0x201, 0x250, 0x300, 0x310

# https://elixir.bootlin.com/linux/v5.1.7/source/drivers/usb/core/hub.c#L4661
usb_device_max_packet_sizes = 8, 16, 32, 64, 255

type usb_config_descriptor_verbose_t[NUM, IFSNUM, ICONFIG, ATTRS, POWER, EXTRA, IFS] {
	bLength			const[USB_DT_CONFIG_SIZE, int8]
	bDescriptorType		const[USB_DT_CONFIG, int8]

	wTotalLength		len[parent, int16]
	bNumInterfaces		IFSNUM
	bConfigurationValue	NUM
	iConfiguration		ICONFIG
	bmAttributes		ATTRS
	bMaxPower		POWER

	extra			EXTRA
	interfaces		IFS
} [packed]

type usb_config_descriptor_t[NUM, IFSNUM, IFS] usb_config_descriptor_verbose_t[NUM, IFSNUM, int8, flags[usb_config_attributes, int8], int8, void, IFS]
type usb_config_descriptor_ifaces_array_t[NUM, IFS] usb_config_descriptor_t[NUM, len[interfaces, int8], IFS]
type usb_config_descriptor_fixed_t[NUM, IFSNUM, ATTRS, POWER, IFS] usb_config_descriptor_verbose_t[const[NUM, int8], const[IFSNUM, int8], const[0, int8], const[ATTRS, int8], const[POWER, int8], void, IFS]
type usb_config_descriptor_extra_t[NUM, IFSNUM, EXTRA, IFS] usb_config_descriptor_verbose_t[NUM, IFSNUM, int8, flags[usb_config_attributes, int8], int8, EXTRA, IFS]

type usb_interface_descriptor_verbose_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, IIF, EXTRA, EPS] {
	bLength			const[USB_DT_INTERFACE_SIZE, int8]
	bDescriptorType		const[USB_DT_INTERFACE, int8]

	bInterfaceNumber	IFNUM
	bAlternateSetting	ALTNUM
	bNumEndpoints		EPSNUM
	bInterfaceClass		CLASS
	bInterfaceSubClass	SUBCLASS
	bInterfaceProtocol	PROTOCOL
	iInterface		IIF

	extra			EXTRA
	endpoints		EPS
} [packed]

type usb_interface_descriptor_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS] usb_interface_descriptor_verbose_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, int8, EXTRA, EPS]
type usb_interface_descriptor_eps_array_t[IFNUM, ALTNUM, CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS] usb_interface_descriptor_t[IFNUM, ALTNUM, len[endpoints, int8], CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS]
type usb_interface_descriptor_fixed_t[IFNUM, ALTNUM, EPSNUM, CLASS, SUBCLASS, PROTOCOL, EXTRA, EPS] usb_interface_descriptor_verbose_t[const[IFNUM, int8], const[ALTNUM, int8], const[EPSNUM, int8], const[CLASS, int8], const[SUBCLASS, int8], const[PROTOCOL, int8], const[0, int8], EXTRA, EPS]

# TODO: non-audio endpoints have USB_DT_ENDPOINT_SIZE.
type usb_endpoint_descriptor_verbose_t[ADDR, ATTRS, PACKET, INTERVAL, REFRESH, SYNCH, EXTRA] {
	bLength			const[USB_DT_ENDPOINT_AUDIO_SIZE, int8]
	bDescriptorType		const[USB_DT_ENDPOINT, int8]

	bEndpointAddress	ADDR
	bmAttributes		ATTRS
	wMaxPacketSize		PACKET
	bInterval		INTERVAL

	bRefresh		REFRESH
	bSynchAddress		SYNCH

	extra			EXTRA
} [packed]

type usb_endpoint_descriptor_t[ADDR, ATTRS, EXTRA] usb_endpoint_descriptor_verbose_t[ADDR, ATTRS, flags[usb_endpoint_max_packet_sizes, int16], int8, int8, int8, EXTRA]
type usb_endpoint_descriptor_fixed_t[ADDR, ATTRS, PACKET, INTERVAL, EXTRA] usb_endpoint_descriptor_verbose_t[const[ADDR, int8], const[ATTRS, int8], const[PACKET, int16], const[INTERVAL, int8], const[0, int8], const[0, int8], EXTRA]

# TODO: dummy driver has complex requirements for packet sizes, account for those:
# https://elixir.bootlin.com/linux/v5.3.6/source/drivers/usb/gadget/udc/dummy_hcd.c#L497
usb_endpoint_max_packet_sizes = 8, 16, 32, 64, 512, 1023, 1024

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Generic USB device, configuration, interface and endpoint descriptors.

# We only support one configuration per device.
# bDeviceClass, bDeviceSubClass, bDeviceProtocol, idVendor, idProduct
# and bcdDevice are patched by Go code, see sys/linux/init_vusb.go.
usb_device_descriptor {
	inner	usb_device_descriptor_t[0, 0, 0, 0, 0, 0, array[usb_config_descriptor, 1]]
} [packed]

usb_config_descriptor {
	inner	usb_config_descriptor_ifaces_array_t[int8, array[usb_interface_descriptor, 1:4]]
} [packed]

usb_config_attributes = USB_CONFIG_ATT_ONE, USB_CONFIG_ATT_SELFPOWER, USB_CONFIG_ATT_WAKEUP, USB_CONFIG_ATT_BATTERY

# bInterfaceNumber, bInterfaceClass, bInterfaceSubClass and bInterfaceProtocol
# are patched by Go code, see sys/linux/init_vusb.go.
usb_interface_descriptor {
	inner	usb_interface_descriptor_eps_array_t[int8, int8, const[0, int8], const[0, int8], const[0, int8], array[usb_interface_extra_descriptor, 0:2], array[usb_endpoint_descriptor, 0:16]]
} [packed]

usb_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], flags[usb_endpoint_attributes, int8], array[usb_endpoint_extra_descriptor, 0:2]]
} [packed]

usb_endpoint_addresses = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, USB_DIR_OUT, USB_DIR_IN

usb_endpoint_attributes = USB_ENDPOINT_XFER_CONTROL, USB_ENDPOINT_XFER_ISOC, USB_ENDPOINT_XFER_BULK, USB_ENDPOINT_XFER_INT, USB_ENDPOINT_INTR_PERIODIC, USB_ENDPOINT_INTR_NOTIFICATION, USB_ENDPOINT_SYNC_NONE, USB_ENDPOINT_SYNC_ASYNC, USB_ENDPOINT_SYNC_ADAPTIVE, USB_ENDPOINT_SYNC_SYNC, USB_ENDPOINT_USAGE_DATA, USB_ENDPOINT_USAGE_FEEDBACK, USB_ENDPOINT_USAGE_FEEDBACK

vusb_connect_descriptors {
	qual_len	len[qual, int32]
	qual		ptr[in, usb_qualifier_descriptor]
	bos_len		len[bos, int32]
	bos		ptr[in, usb_bos_descriptor]
	strs_len	len[strs, int32]
	strs		array[vusb_connect_string_descriptor]
} [packed]

vusb_connect_string_descriptor {
	len	len[str, int32]
	str	ptr[in, usb_string_descriptor]
} [packed]

vusb_descriptors {
	len	len[parent, int32]
	generic	ptr[in, vusb_descriptor_generic]

	string	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
	bos	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_BOS, usb_bos_descriptor]]

	hub_hs	ptr[in, vusb_descriptor_t[USB_TYPE_CLASS, USB_DT_HUB, usb_hub_descriptor_hs]]
	hub_ss	ptr[in, vusb_descriptor_t[USB_TYPE_CLASS, USB_DT_SS_HUB, usb_hub_descriptor_ss]]
} [packed]

vusb_descriptor_generic {
	req_type	flags[usb_request_types, int8]
	desc_type	flags[usb_descriptor_types, int8]
	len		bytesize[data, int32]
	data		usb_generic_descriptor
} [packed]

usb_request_types = USB_TYPE_STANDARD, USB_TYPE_CLASS, USB_TYPE_VENDOR

type vusb_descriptor_t[CLASS, REQ, DATA] {
	type	const[CLASS, int8]
	req	const[REQ, int8]
	len	bytesize[data, int32]
	data	DATA
} [packed]

# TODO: consider doing lookups based on USB_RECIP values.
vusb_responses {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	get_interface			ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	get_configuration		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

# TODO: move these into custom descriptions for hub class when they are added.
	hub_USB_REQ_GET_STATUS_hub	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_REQ_GET_STATUS, usb_hub_status]]
	hub_USB_REQ_GET_STATUS_port	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_REQ_GET_STATUS, usb_port_status]]

# TODO: move these into custom descriptions for asix driver when they are added.
	asix_AX_CMD_READ_MII_REG	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_MII_REG, int16]]
	asix_AX_CMD_STATMNGSTS_REG	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_STATMNGSTS_REG, int8]]
	asix_AX_CMD_READ_EEPROM		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_EEPROM, array[int8, 2]]]
	asix_AX_CMD_READ_RX_CTL		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_RX_CTL, int16]]
	asix_AX_CMD_READ_NODE_ID	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_NODE_ID, mac_addr]]
	asix_AX88172_CMD_READ_NODE_ID	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX88172_CMD_READ_NODE_ID, mac_addr]]
	asix_AX_CMD_READ_PHY_ID		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_PHY_ID, array[int8, 2]]]
	asix_AX_CMD_READ_MEDIUM_STATUS	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_MEDIUM_STATUS, int16]]
	asix_AX_CMD_READ_MONITOR_MODE	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_MONITOR_MODE, int8]]
	asix_AX_CMD_READ_GPIOS		ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_READ_GPIOS, int8]]
	asix_AX_CMD_SW_PHY_STATUS	ptr[in, vusb_response_t[USB_TYPE_VENDOR, AX_CMD_SW_PHY_STATUS, int8]]
} [packed]

vusb_response_generic {
	type	flags[usb_request_types, int8]
	req	flags[usb_requests, int8]
	len	bytesize[data, int32]
	data	array[int8, 0:256]
} [packed]

usb_requests = USB_REQ_GET_STATUS, USB_REQ_CLEAR_FEATURE, USB_REQ_SET_FEATURE, USB_REQ_SET_ADDRESS, USB_REQ_GET_DESCRIPTOR, USB_REQ_SET_DESCRIPTOR, USB_REQ_GET_CONFIGURATION, USB_REQ_SET_CONFIGURATION, USB_REQ_GET_INTERFACE, USB_REQ_SET_INTERFACE, USB_REQ_SYNCH_FRAME, USB_REQ_SET_SEL, USB_REQ_SET_ISOCH_DELAY, USB_REQ_SET_ENCRYPTION, USB_REQ_GET_ENCRYPTION, USB_REQ_RPIPE_ABORT, USB_REQ_SET_HANDSHAKE, USB_REQ_RPIPE_RESET, USB_REQ_GET_HANDSHAKE, USB_REQ_SET_CONNECTION, USB_REQ_SET_SECURITY_DATA, USB_REQ_GET_SECURITY_DATA, USB_REQ_SET_WUSB_DATA, USB_REQ_LOOPBACK_DATA_WRITE, USB_REQ_LOOPBACK_DATA_READ, USB_REQ_SET_INTERFACE_DS, USB_REQ_GET_PARTNER_PDO, USB_REQ_GET_BATTERY_STATUS, USB_REQ_SET_PDO, USB_REQ_GET_VDM, USB_REQ_SEND_VDM

type vusb_response_t[CLASS, REQ, DATA] {
	type	const[CLASS, int8]
	req	const[REQ, int8]
	len	bytesize[data, int32]
	data	DATA
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# USB descriptors requested by the kernel before the SET_CONFIGURATION request.

# TODO: figure out when is the USB_DT_OTG descriptor used.
# TODO: figure out when is the USB_DT_INTERFACE_ASSOCIATION descriptor used.
# TODO: figure out when is the USB_DT_BOS descriptor used.

type usb_string_descriptor_t[DATA] {
	bLength		len[parent, int8]
	bDescriptorType	const[USB_DT_STRING, int8]

	data		DATA
} [packed]

usb_string_descriptor [
	lang_id	usb_string_descriptor_t[flags[usb_lang_ids, int16]]
	string	usb_string_descriptor_t[array[int8, 0:256]]
] [varlen]

usb_lang_ids = 0x436, 0x41c, 0x401, 0x801, 0xc01, 0x1001, 0x1401, 0x1801, 0x1c01, 0x2001, 0x2401, 0x2801, 0x2c01, 0x3001, 0x3401, 0x3801, 0x3c01, 0x4001, 0x42b, 0x44d, 0x42c, 0x82c, 0x42d, 0x423, 0x445, 0x402, 0x455, 0x403, 0x404, 0x804, 0xc04, 0x1004, 0x1404, 0x41a, 0x405, 0x406, 0x413, 0x813, 0x409, 0x809, 0xc09, 0x1009, 0x1409, 0x1809, 0x1c09, 0x2009, 0x2409, 0x2809, 0x2c09, 0x3009, 0x3409, 0x425, 0x438, 0x429, 0x40b, 0x40c, 0x80c, 0xc0c, 0x100c, 0x140c, 0x180c, 0x437, 0x407, 0x807, 0xc07, 0x1007, 0x1407, 0x408, 0x447, 0x40d, 0x439, 0x40e, 0x40f, 0x421, 0x410, 0x810, 0x411, 0x44b, 0x860, 0x43f, 0x457, 0x412, 0x812, 0x426, 0x427, 0x827, 0x42f, 0x43e, 0x83e, 0x44c, 0x458, 0x44e, 0x861, 0x414, 0x814, 0x448, 0x415, 0x416, 0x816, 0x446, 0x418, 0x419, 0x44f, 0xc1a, 0x81a, 0x459, 0x41b, 0x424, 0x40a, 0x80a, 0xc0a, 0x100a, 0x140a, 0x180a, 0x1c0a, 0x200a, 0x240a, 0x280a, 0x2c0a, 0x300a, 0x340a, 0x380a, 0x3c0a, 0x400a, 0x440a, 0x480a, 0x4c0a, 0x500a, 0x430, 0x441, 0x41d, 0x81d, 0x449, 0x444, 0x44a, 0x41e, 0x41f, 0x422, 0x420, 0x820, 0x443, 0x843, 0x42a, 0x4ff, 0xf0ff, 0xf4ff, 0xf8ff, 0xfcff

usb_qualifier_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_QUALIFIER, int8]

	bcdUSB			flags[usb_versions, int16]
	bDeviceClass		int8
	bDeviceSubClass		int8
	bDeviceProtocol		int8
	bMaxPacketSize0		flags[usb_device_max_packet_sizes, int8]
	bNumConfigurations	int8
	bRESERVED		const[0, int8]
} [packed]

usb_bos_descriptor {
	bLength		const[USB_DT_BOS_SIZE, int8]
	bDescriptorType	const[USB_DT_BOS, int8]

	wTotalLength	len[parent, int16]
	bNumDeviceCaps	len[caps, int8]

	caps		array[usb_dev_cap, 0:6]
} [packed]

usb_dev_cap [
	generic		usb_generic_cap_descriptor
	wireless	usb_wireless_cap_descriptor
	ext_cap		usb_ext_cap_descriptor
	ss_cap		usb_ss_cap_descriptor
	ss_container_id	usb_ss_container_id_descriptor
	ssp_cap		usb_ssp_cap_descriptor
	ptm_cap		usb_ptm_cap_descriptor
] [varlen]

usb_generic_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	flags[usb_capability_types, int8]

	data			array[int8, 0:256]
} [packed]

usb_capability_types = USB_CAP_TYPE_WIRELESS_USB, USB_CAP_TYPE_EXT, USB_SS_CAP_TYPE, USB_SSP_CAP_TYPE, CONTAINER_ID_TYPE, USB_PTM_CAP_TYPE

usb_wireless_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_CAP_TYPE_WIRELESS_USB, int8]

	bmAttributes		flags[usb_wireless_cap_attributes, int8]
	wPHYRates		flags[usb_wireless_cap_phyrates, int16]
	bmTFITXPowerInfo	int8
	bmFFITXPowerInfo	int8
	bmBandGroup		int16
	bReserved		int8
} [packed]

usb_wireless_cap_attributes = USB_WIRELESS_P2P_DRD, USB_WIRELESS_BEACON_MASK, USB_WIRELESS_BEACON_SELF, USB_WIRELESS_BEACON_DIRECTED, USB_WIRELESS_BEACON_NONE

usb_wireless_cap_phyrates = USB_WIRELESS_PHY_53, USB_WIRELESS_PHY_80, USB_WIRELESS_PHY_107, USB_WIRELESS_PHY_160, USB_WIRELESS_PHY_200, USB_WIRELESS_PHY_320, USB_WIRELESS_PHY_400, USB_WIRELESS_PHY_480

usb_ext_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_CAP_TYPE_EXT, int8]

	bmAttributes1		flags[usb_ext_cap_attributes, int32:8]
	bmAttributes2		int32:4
	bmAttributes3		int32:4
	bmAttributes4		int32:16
} [packed]

usb_ext_cap_attributes = USB_LPM_SUPPORT, USB_BESL_SUPPORT, USB_BESL_BASELINE_VALID, USB_BESL_DEEP_VALID

usb_ss_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_SS_CAP_TYPE, int8]

	bmAttributes		flags[usb_ss_cap_attributes, int8]
	wSpeedSupported		flags[usb_ss_cap_speed, int16]
	bFunctionalitySupport	int8
	bU1devExitLat		int8
	bU2DevExitLat		int16
} [packed]

usb_ss_cap_attributes = USB_LTM_SUPPORT

usb_ss_cap_speed = USB_LOW_SPEED_OPERATION, USB_FULL_SPEED_OPERATION, USB_HIGH_SPEED_OPERATION, USB_5GBPS_OPERATION

usb_ss_container_id_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[CONTAINER_ID_TYPE, int8]

	bReserved		int8
	ContainerID		array[int8, 16]
} [packed]

usb_ssp_cap_descriptor {
	bLength				len[parent, int8]
	bDescriptorType			const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType		const[USB_SSP_CAP_TYPE, int8]

	bReserved			int8
	bmAttributesSublinkSpeeds	len[bmSublinkSpeedAttr, int32:5]
	bmAttributesSpeedIDs		int32:27
	wFunctionalitySupport		flags[usb_ssp_cap_funcs, int16]
	wReserved			int16
	bmSublinkSpeedAttr		array[flags[usb_ssp_cap_sublink_speeds, int32], 0:6]
} [packed]

usb_ssp_cap_funcs = USB_SSP_MIN_SUBLINK_SPEED_ATTRIBUTE_ID, USB_SSP_MIN_RX_LANE_COUNT, USB_SSP_MIN_TX_LANE_COUNT

usb_ssp_cap_sublink_speeds = USB_SSP_SUBLINK_SPEED_SSID, USB_SSP_SUBLINK_SPEED_LSE, USB_SSP_SUBLINK_SPEED_ST, USB_SSP_SUBLINK_SPEED_RSVD, USB_SSP_SUBLINK_SPEED_LP, USB_SSP_SUBLINK_SPEED_LSM

usb_ptm_cap_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_DEVICE_CAPABILITY, int8]
	bDevCapabilityType	const[USB_PTM_CAP_TYPE, int8]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Extra USB descriptors that come after an interface or an endpoint descriptor.

# TODO: consider removing class specific descriptors here for described classes.
usb_interface_extra_descriptor [
	generic		usb_generic_descriptor
	hid_hid		usb_hid_descriptor_hid
	cdc_ecm		usb_cdc_header_ecm
	cdc_ncm		usb_cdc_header_ncm
	uac_control	uac_control_iface_extra_descriptors
	uac_as		uac_as_iface_extra_descriptors
] [varlen]

usb_endpoint_extra_descriptor [
	generic	usb_generic_descriptor
	uac_iso	uac_iso_endpoint_descriptor
] [varlen]

usb_generic_descriptor {
	bLength		len[parent, int8]
	bDescriptorType	flags[usb_descriptor_types, int8]

	data		array[int8, 0:256]
} [packed]

usb_descriptor_types = USB_DT_DEVICE, USB_DT_CONFIG, USB_DT_STRING, USB_DT_INTERFACE, USB_DT_ENDPOINT, USB_DT_DEVICE_QUALIFIER, USB_DT_OTHER_SPEED_CONFIG, USB_DT_INTERFACE_POWER, USB_DT_OTG, USB_DT_DEBUG, USB_DT_INTERFACE_ASSOCIATION, USB_DT_SECURITY, USB_DT_KEY, USB_DT_ENCRYPTION_TYPE, USB_DT_BOS, USB_DT_DEVICE_CAPABILITY, USB_DT_WIRELESS_ENDPOINT_COMP, USB_DT_WIRE_ADAPTER, USB_DT_RPIPE, USB_DT_CS_RADIO_CONTROL, USB_DT_PIPE_USAGE, USB_DT_SS_ENDPOINT_COMP, USB_DT_SSP_ISOC_ENDPOINT_COMP, HID_DT_HID, HID_DT_REPORT, HID_DT_PHYSICAL

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# USB descriptors requested after the SET_CONFIGURATION request.

usb_hub_descriptor_hs {
	bDescLength		len[parent, int8]
	bDescriptorType		const[USB_DT_HUB, int8]

	bNbrPorts		int8
	wHubCharacteristics	flags[usb_hub_characteristics, int16]
	bPwrOn2PwrGood		int8
	bHubContrCurrent	int8

	DeviceRemovable		array[int8, USB_HUB_PORTS_BITS]
	PortPwrCtrlMask		array[int8, USB_HUB_PORTS_BITS]
} [packed]

usb_hub_descriptor_ss {
	bDescLength		len[parent, int8]
	bDescriptorType		const[USB_DT_SS_HUB, int8]

	bNbrPorts		int8
	wHubCharacteristics	flags[usb_hub_characteristics, int16]
	bPwrOn2PwrGood		int8
	bHubContrCurrent	int8

	bHubHdrDecLat		int8
	wHubDelay		int16
	DeviceRemovable		int16
} [packed]

define USB_HUB_PORTS_BITS	((USB_MAXCHILDREN + 1 + 7) / 8)

usb_hub_characteristics = HUB_CHAR_LPSM, HUB_CHAR_COMMON_LPSM, HUB_CHAR_INDV_PORT_LPSM, HUB_CHAR_NO_LPSM, HUB_CHAR_COMPOUND, HUB_CHAR_OCPM, HUB_CHAR_COMMON_OCPM, HUB_CHAR_INDV_PORT_OCPM, HUB_CHAR_NO_OCPM, HUB_CHAR_TTTT, HUB_CHAR_PORTIND

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Replies to USB control requests requested after the SET_CONFIGURATION request.

usb_port_status {
	wPortStatus	flags[usb_port_status_flags, int16]
	wPortChange	flags[usb_port_change_flags, int16]
	dwExtPortStatus	array[flags[usb_ext_port_status_flags, int32], 0:1]
} [packed]

usb_port_status_flags = USB_PORT_STAT_CONNECTION, USB_PORT_STAT_ENABLE, USB_PORT_STAT_SUSPEND, USB_PORT_STAT_OVERCURRENT, USB_PORT_STAT_RESET, USB_PORT_STAT_L1, USB_PORT_STAT_POWER, USB_PORT_STAT_LOW_SPEED, USB_PORT_STAT_HIGH_SPEED, USB_PORT_STAT_TEST, USB_PORT_STAT_INDICATOR, USB_PORT_STAT_LINK_STATE, USB_SS_PORT_STAT_POWER, USB_SS_PORT_STAT_SPEED, USB_PORT_STAT_SPEED_5GBPS, USB_SS_PORT_LS_U0, USB_SS_PORT_LS_U1, USB_SS_PORT_LS_U2, USB_SS_PORT_LS_U3, USB_SS_PORT_LS_SS_DISABLED, USB_SS_PORT_LS_RX_DETECT, USB_SS_PORT_LS_SS_INACTIVE, USB_SS_PORT_LS_POLLING, USB_SS_PORT_LS_RECOVERY, USB_SS_PORT_LS_HOT_RESET, USB_SS_PORT_LS_COMP_MOD, USB_SS_PORT_LS_LOOPBACK

usb_port_change_flags = USB_PORT_STAT_C_CONNECTION, USB_PORT_STAT_C_ENABLE, USB_PORT_STAT_C_SUSPEND, USB_PORT_STAT_C_OVERCURRENT, USB_PORT_STAT_C_RESET, USB_PORT_STAT_C_L1, USB_PORT_STAT_C_BH_RESET, USB_PORT_STAT_C_LINK_STATE, USB_PORT_STAT_C_CONFIG_ERROR

usb_ext_port_status_flags = USB_EXT_PORT_STAT_RX_SPEED_ID, USB_EXT_PORT_STAT_TX_SPEED_ID, USB_EXT_PORT_STAT_RX_LANES, USB_EXT_PORT_STAT_TX_LANES

usb_hub_status {
	wHubStatus	flags[usb_hub_status_flags, int16]
	wHubChange	flags[usb_hub_change_flags, int16]
} [packed]

usb_hub_status_flags = HUB_STATUS_LOCAL_POWER, HUB_STATUS_OVERCURRENT

usb_hub_change_flags = HUB_CHANGE_LOCAL_POWER, HUB_CHANGE_OVERCURRENT

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# HID device class specific descriptions.
# https://www.usb.org/sites/default/files/documents/hid1_11.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/hid/usbhid/hid-core.c
# https://elixir.bootlin.com/linux/latest/source/drivers/hid/hid-core.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/hid.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_hid.c

# Connected HID devices are known to create the following /dev/ files:
# /dev/hidraw#, /dev/usb/hiddev# and /dev/input/event#.

resource fd_usb_hid[fd_usb]

syz_usb_connect$hid(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_hid], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_hid (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$hid(fd fd_usb_hid, descs ptr[in, vusb_descriptors_hid], resps ptr[in, vusb_responses_hid]) (timeout[300], remote_cover)

# idVendor and idProduct are patched by Go code, see sys/linux/init_vusb.go.
usb_device_descriptor_hid {
	inner	usb_device_descriptor_t[0, 0, 0, 0, 0, 64, array[usb_config_descriptor_hid, 1]]
} [packed]

usb_config_descriptor_hid {
	inner	usb_config_descriptor_ifaces_array_t[const[1, int8], array[usb_interface_descriptor_hid, 1]]
} [packed]

usb_interface_descriptor_hid {
	inner	usb_interface_descriptor_t[const[0, int8], int8, int8[1:2], const[USB_CLASS_HID, int8], const[USB_INTERFACE_SUBCLASS_BOOT, int8], flags[usb_hid_protocols, int8], usb_hid_descriptor_hid, usb_endpoint_descriptors_hid]
} [packed]

usb_hid_protocols = USB_INTERFACE_PROTOCOL_KEYBOARD, USB_INTERFACE_PROTOCOL_MOUSE

usb_endpoint_descriptors_hid {
	in	usb_endpoint_descriptor_hid_in
	out	array[usb_endpoint_descriptor_hid_out, 0:1]
} [packed]

usb_endpoint_descriptor_hid_in {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_HID_IN_ADDRESS, int8], const[USB_ENDPOINT_HID_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_hid_out {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_HID_OUT_ADDRESS, int8], const[USB_ENDPOINT_HID_ATTRIBUTES, int8], void]
} [packed]

define USB_ENDPOINT_HID_ATTRIBUTES	(USB_ENDPOINT_XFER_INT)
define USB_ENDPOINT_HID_IN_ADDRESS	(1 | USB_DIR_IN)
define USB_ENDPOINT_HID_OUT_ADDRESS	(2)

vusb_descriptors_hid {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]

# For unknown reasons these are requested as USB_TYPE_STANDARD and not as USB_TYPE_CLASS.
# Linux doesn't request HID_DT_HID, but some hosts might do that.
	HID_DT_REPORT	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, HID_DT_REPORT, hid_descriptor_report]]
	HID_DT_HID	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, HID_DT_HID, usb_hid_descriptor_hid]]
} [packed]

vusb_responses_hid {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	HID_REQ_GET_REPORT		ptr[in, vusb_response_t[USB_TYPE_CLASS, HID_REQ_GET_REPORT, array[int8, 0:256]]]
	HID_REQ_GET_PROTOCOL		ptr[in, vusb_response_t[USB_TYPE_CLASS, HID_REQ_GET_PROTOCOL, int8]]
} [packed]

# USB HID specifications allows for multiple report and physical descriptors
# to be present, but I don't see any support for them in the Linux kernel,
# except for a single report descriptor.
usb_hid_descriptor_hid {
	bLength		len[parent, int8]
	bDescriptorType	const[HID_DT_HID, int8]

	bcdHID		int16
	bCountryCode	int8
	bNumDescriptors	const[1, int8]

	report_desc	usb_hid_class_descriptor_report
} [packed]

usb_hid_class_descriptor_report {
	bDescriptorType		const[HID_DT_REPORT, int8]
	wDescriptorLength	int16[0:HID_MAX_DESCRIPTOR_SIZE]
} [packed]

# TODO: it's hard to describe the REPORT descriptor structure via syzkaller
# descriptions, so consider generating it in Go code.
# TODO: the length of REPORT descriptor must match the value in HID descriptor.
# TODO: there are vendor specific REPORT descriptor formats (Logitech HID++).

# Linux HID stack doesn't support long items.
hid_descriptor_report {
	items	array[hid_report_item_short]
} [packed]

type hid_report_item_short_012_t[TYPE, TAGS] {
	bSize	len[data, int8:2]
	bType	const[TYPE, int8:2]
	bTag	flags[TAGS, int8:4]
	data	array[int8, 0:2]
} [packed]

type hid_report_item_short_4_t[TYPE, TAGS] {
	bSize	const[3, int8:2]
	bType	const[TYPE, int8:2]
	bTag	flags[TAGS, int8:4]
	data	array[int8, 4]
} [packed]

type hid_report_item_short_t[TYPE, TAGS] [
	item_012	hid_report_item_short_012_t[TYPE, TAGS]
	item_4		hid_report_item_short_4_t[TYPE, TAGS]
] [varlen]

hid_report_item_short [
	main	hid_report_item_short_t[HID_ITEM_TYPE_MAIN, hid_report_item_main_tags]
	global	hid_report_item_short_t[HID_ITEM_TYPE_GLOBAL, hid_report_item_global_tags]
	local	hid_report_item_short_t[HID_ITEM_TYPE_LOCAL, hid_report_item_local_tags]
] [varlen]

hid_report_item_main_tags = HID_MAIN_ITEM_TAG_INPUT, HID_MAIN_ITEM_TAG_OUTPUT, HID_MAIN_ITEM_TAG_FEATURE, HID_MAIN_ITEM_TAG_BEGIN_COLLECTION, HID_MAIN_ITEM_TAG_END_COLLECTION
hid_report_item_global_tags = HID_GLOBAL_ITEM_TAG_USAGE_PAGE, HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM, HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM, HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM, HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM, HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT, HID_GLOBAL_ITEM_TAG_UNIT, HID_GLOBAL_ITEM_TAG_REPORT_SIZE, HID_GLOBAL_ITEM_TAG_REPORT_ID, HID_GLOBAL_ITEM_TAG_REPORT_COUNT, HID_GLOBAL_ITEM_TAG_PUSH, HID_GLOBAL_ITEM_TAG_POP
hid_report_item_local_tags = HID_LOCAL_ITEM_TAG_USAGE, HID_LOCAL_ITEM_TAG_USAGE_MINIMUM, HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM, HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX, HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM, HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM, HID_LOCAL_ITEM_TAG_STRING_INDEX, HID_LOCAL_ITEM_TAG_STRING_MINIMUM, HID_LOCAL_ITEM_TAG_STRING_MAXIMUM, HID_LOCAL_ITEM_TAG_DELIMITER

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# PRINTER device class specific descriptions.
# https://www.usb.org/sites/default/files/usbprint11a021811.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/class/usblp.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/printer.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_printer.c

# Connected PRINTER devices are known to create the following /dev/ files:
# /dev/usb/lp#.
# TODO: write descriptions for those.

# drivers/usb/class/usblp.c
define USBLP_REQ_GET_ID	0x00
define USBLP_REQ_GET_STATUS	0x01
define USBLP_REQ_RESET	0x02
define USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST	0x00
define USBLP_FIRST_PROTOCOL	1
define USBLP_LAST_PROTOCOL	3

resource fd_usb_printer[fd_usb]

syz_usb_connect$printer(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_printer], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_printer (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$printer(fd fd_usb_printer, descs ptr[in, vusb_descriptors_printer], resps ptr[in, vusb_responses_printer]) (timeout[300], remote_cover)

usb_device_descriptor_printer {
	inner	usb_device_descriptor_t[0, 0, 0, 0x525, 0xa4a8, 64, array[usb_config_descriptor_printer, 1]]
} [packed]

usb_config_descriptor_printer {
	inner	usb_config_descriptor_ifaces_array_t[const[1, int8], array[usb_interface_descriptor_printer, 1]]
} [packed]

usb_interface_descriptor_printer {
	inner	usb_interface_descriptor_t[const[0, int8], int8, int8[1:2], const[USB_CLASS_PRINTER, int8], const[1, int8], int8[USBLP_FIRST_PROTOCOL:USBLP_LAST_PROTOCOL], void, usb_endpoint_descriptors_printer]
} [packed]

usb_endpoint_descriptors_printer {
	in	usb_endpoint_descriptor_printer_out
	out	array[usb_endpoint_descriptor_printer_in, 0:1]
} [packed]

usb_endpoint_descriptor_printer_out {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_PRINTER_OUT_ADDRESS, int8], const[USB_ENDPOINT_PRINTER_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_printer_in {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_PRINTER_IN_ADDRESS, int8], const[USB_ENDPOINT_PRINTER_ATTRIBUTES, int8], void]
} [packed]

define USB_ENDPOINT_PRINTER_ATTRIBUTES	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_PRINTER_OUT_ADDRESS	(1)
define USB_ENDPOINT_PRINTER_IN_ADDRESS	(2 | USB_DIR_IN)

vusb_descriptors_printer {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_printer {
	len					len[parent, int32]
	generic					ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE			ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	USBLP_REQ_GET_ID			ptr[in, vusb_response_t[USB_TYPE_CLASS, USBLP_REQ_GET_ID, usb_printer_get_id_response]]
	USBLP_REQ_GET_STATUS			ptr[in, vusb_response_t[USB_TYPE_CLASS, USBLP_REQ_GET_STATUS, int8]]
	USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST	ptr[in, vusb_response_t[USB_TYPE_CLASS, USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST, int8]]
} [packed]

usb_printer_get_id_response {
	length	len[id, int16be]
	id	array[int8, 0:256]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# CDC ECM (Ethernet) device class specific descriptions.
# https://www.usb.org/document-library/class-definitions-communication-devices-12
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/cdc_ether.c
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/usbnet.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/ether.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_ecm.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/u_ether.c

# Connected CDC ECM devices are known to create usbN network interfaces.
# TODO: write descriptions for those.

resource fd_usb_cdc_ecm[fd_usb]

syz_usb_connect$cdc_ecm(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_cdc_ecm], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_cdc_ecm (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$cdc_ecm(fd fd_usb_cdc_ecm, descs ptr[in, vusb_descriptors_cdc_ecm], resps ptr[in, vusb_responses_cdc_ecm]) (timeout[300], remote_cover)

usb_device_descriptor_cdc_ecm {
	inner	usb_device_descriptor_t[USB_CLASS_COMM, 0, 0, 0x525, 0xa4a1, 64, array[usb_config_descriptor_cdc_ecm, 1]]
} [packed]

usb_config_descriptor_cdc_ecm {
	inner	usb_config_descriptor_ifaces_array_t[const[1, int8], array[usb_interface_descriptor_cdc_ecm, 1]]
} [packed]

# Per specification CDC ECM devices have two interfaces (control and data),
# but here we're merging them into one for simplicity since Linux supports that.
usb_interface_descriptor_cdc_ecm {
	inner	usb_interface_descriptor_t[const[0, int8], int8, int8[2:3], const[USB_CLASS_COMM, int8], const[USB_CDC_SUBCLASS_ETHERNET, int8], const[USB_CDC_PROTO_NONE, int8], usb_cdc_header_ecm, usb_endpoint_descriptors_cdc_ecm]
} [packed]

usb_endpoint_descriptors_cdc_ecm {
	notify	array[usb_endpoint_descriptor_cdc_ecm_notify, 0:1]
	in	usb_endpoint_descriptor_cdc_ecm_in
	out	usb_endpoint_descriptor_cdc_ecm_out
} [packed]

usb_endpoint_descriptor_cdc_ecm_notify {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_CDC_ECM_NOTIFY_ADDRESS, int8], const[USB_ENDPOINT_CDC_ECM_NOTIFY_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_cdc_ecm_in {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_CDC_ECM_IN_ADDRESS, int8], const[USB_ENDPOINT_CDC_ECM_DATA_ATTRIBUTES, int8], void]
} [packed]

usb_endpoint_descriptor_cdc_ecm_out {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_CDC_ECM_OUT_ADDRESS, int8], const[USB_ENDPOINT_CDC_ECM_DATA_ATTRIBUTES, int8], void]
} [packed]

define USB_ENDPOINT_CDC_ECM_NOTIFY_ATTRIBUTES	(USB_ENDPOINT_XFER_INT)
define USB_ENDPOINT_CDC_ECM_DATA_ATTRIBUTES	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_CDC_ECM_NOTIFY_ADDRESS	(1 | USB_DIR_IN)
define USB_ENDPOINT_CDC_ECM_IN_ADDRESS	(2 | USB_DIR_IN)
define USB_ENDPOINT_CDC_ECM_OUT_ADDRESS	(3)

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/usb/core/message.c#L2137
# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/cdc_ether.c#L155
usb_cdc_header_ecm {
	union	usb_cdc_union_desc_t[0, 0]
	header	usb_cdc_header_desc
	ether	usb_cdc_ether_desc

	other	array[usb_cdc_header_ecm_other, 0:6]
} [packed]

usb_cdc_header_ecm_other [
	call_mgmt		usb_cdc_call_mgmt_descriptor
	acm			usb_cdc_acm_descriptor
	country_functional	usb_cdc_country_functional_desc
	network_terminal	usb_cdc_network_terminal_desc
	dmm			usb_cdc_dmm_desc
	mdlm			usb_cdc_mdlm_desc
	mdlm_detail		usb_cdc_mdlm_detail_desc
	obex			usb_cdc_obex_desc
	ncm			usb_cdc_ncm_desc
	mbim			usb_cdc_mbim_desc
	mbim_extended		usb_cdc_mbim_extended_desc
] [varlen]

usb_cdc_header_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_HEADER_TYPE, int8]

	bcdCDC			int16
} [packed]

usb_cdc_call_mgmt_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_CALL_MANAGEMENT_TYPE, int8]

	bmCapabilities		flags[usb_cdc_call_mgmt_caps, int8]
	bDataInterface		int8
} [packed]

usb_cdc_call_mgmt_caps = USB_CDC_CALL_MGMT_CAP_CALL_MGMT, USB_CDC_CALL_MGMT_CAP_DATA_INTF

usb_cdc_acm_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_ACM_TYPE, int8]

	bmCapabilities		flags[usb_cdc_acm_caps, int8]
} [packed]

usb_cdc_acm_caps = USB_CDC_COMM_FEATURE, USB_CDC_CAP_LINE, USB_CDC_CAP_BRK, USB_CDC_CAP_NOTIFY

type usb_cdc_union_desc_t[MASTER, SLAVE] {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_UNION_TYPE, int8]

	bMasterInterface0	const[MASTER, int8]
	bSlaveInterface0	const[SLAVE, int8]
	slave_interfaces	array[int8, 0:6]
} [packed]

usb_cdc_country_functional_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_COUNTRY_TYPE, int8]

	iCountryCodeRelDate	int8
	wCountyCode0		int16
	country_codes		array[int16, 0:6]
} [packed]

usb_cdc_network_terminal_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_NETWORK_TERMINAL_TYPE, int8]

	bEntityId		int8
	iName			int8
	bChannelIndex		int8
	bPhysicalInterface	int8
} [packed]

usb_cdc_ether_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_ETHERNET_TYPE, int8]

	iMACAddress		const[1, int8]
	bmEthernetStatistics	int32
	wMaxSegmentSize		int16
	wNumberMCFilters	int16
	bNumberPowerFilters	int8
} [packed]

usb_cdc_dmm_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_DMM_TYPE, int8]

	bcdVersion		int16
	wMaxCommand		int16
} [packed]

usb_cdc_mdlm_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_MDLM_TYPE, int8]

	bcdVersion		int16
	bGUID			usb_cdc_ecm_mbm_guid
} [packed]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/cdc_ether.c#L61
usb_cdc_ecm_mbm_guid {
	id0	const[0x14f5e048ba817a3, int64]
	id1	const[0x2a397ecbffc007a6, int64]
} [packed]

usb_cdc_mdlm_detail_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_MDLM_DETAIL_TYPE, int8]

	bGuidDescriptorType	int8
	bDetailData		array[int8, 0:256]
} [packed]

usb_cdc_obex_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_OBEX_TYPE, int8]

	bcdVersion		int16
} [packed]

usb_cdc_ncm_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_NCM_TYPE, int8]

	bcdNcmVersion		int16
	bmNetworkCapabilities	flags[usb_cdc_ncm_ncaps, int8]
} [packed]

usb_cdc_ncm_ncaps = USB_CDC_NCM_NCAP_ETH_FILTER, USB_CDC_NCM_NCAP_NET_ADDRESS, USB_CDC_NCM_NCAP_ENCAP_COMMAND, USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE, USB_CDC_NCM_NCAP_CRC_MODE, USB_CDC_NCM_NCAP_NTB_INPUT_SIZE

usb_cdc_mbim_desc {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[USB_CDC_MBIM_TYPE, int8]

	bcdMBIMVersion		int16
	wMaxControlMessage	int16
	bNumberFilters		int8
	bMaxFilterSize		int8
	wMaxSegmentSize		int16
	bmNetworkCapabilities	int8
} [packed]

usb_cdc_mbim_extended_desc {
	bLength				len[parent, int8]
	bDescriptorType			const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType		const[USB_CDC_MBIM_EXTENDED_TYPE, int8]

	bcdMBIMExtendedVersion		int16
	bMaxOutstandingCommandMessages	int8
	wMTU				int16
} [packed]

vusb_descriptors_cdc_ecm {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/usbnet.c#L147
	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor_t[usb_cdc_ecm_mac]]]
} [packed]

usb_cdc_ecm_mac {
# This is a UTF16 encoded string "424242424242".
	data0	const[0x3400320034003200, int64be]
	data1	const[0x3400320034003200, int64be]
	data2	const[0x3400320034003200, int64be]
} [packed]

vusb_responses_cdc_ecm {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# CDC NCM class specific descriptions.
# CDC NCM is based on CDC ECM, so some of the descriptions are reused.
# https://www.usb.org/document-library/network-control-model-devices-specification-v10-and-errata-and-adopters-agreement
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/cdc_ncm.c
# https://elixir.bootlin.com/linux/latest/source/drivers/net/usb/usbnet.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/ncm.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_ncm.c

resource fd_usb_cdc_ncm[fd_usb]

syz_usb_connect$cdc_ncm(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_cdc_ncm], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_cdc_ncm (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$cdc_ncm(fd fd_usb_cdc_ncm, descs ptr[in, vusb_descriptors_cdc_ncm], resps ptr[in, vusb_responses_cdc_ncm]) (timeout[300], remote_cover)

usb_device_descriptor_cdc_ncm {
	inner	usb_device_descriptor_t[USB_CLASS_COMM, 0, 0, 0x525, 0xa4a1, 64, array[usb_config_descriptor_cdc_ncm, 1]]
} [packed]

usb_config_descriptor_cdc_ncm {
	inner	usb_config_descriptor_t[const[1, int8], const[2, int8], usb_interface_descriptors_cdc_ncm]
} [packed]

usb_interface_descriptors_cdc_ncm {
	control		usb_interface_descriptor_fixed_t[0, CDC_NCM_COMM_ALTSETTING_NCM, 1, USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE, usb_cdc_header_ncm, usb_endpoint_descriptor_cdc_ecm_notify]
	data_nop	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE, void, void]
	data		usb_interface_descriptor_fixed_t[1, CDC_NCM_DATA_ALTSETTING_NCM, 2, USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE, void, usb_endpoint_descriptors_cdc_ncm_data]
} [packed]

usb_endpoint_descriptors_cdc_ncm_data {
	in	usb_endpoint_descriptor_cdc_ecm_in
	out	usb_endpoint_descriptor_cdc_ecm_out
} [packed]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/usb/core/message.c#L2137
# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/cdc_ncm.c#L798
usb_cdc_header_ncm {
	union	usb_cdc_union_desc_t[0, 1]
	header	usb_cdc_header_desc
	ether	usb_cdc_ether_desc
	ncm	usb_cdc_ncm_desc

	other	array[usb_cdc_header_ncm_other, 0:6]
} [packed]

usb_cdc_header_ncm_other [
	call_mgmt		usb_cdc_call_mgmt_descriptor
	acm			usb_cdc_acm_descriptor
	country_functional	usb_cdc_country_functional_desc
	network_terminal	usb_cdc_network_terminal_desc
	dmm			usb_cdc_dmm_desc
	mdlm			usb_cdc_mdlm_desc
	mdlm_detail		usb_cdc_mdlm_detail_desc
	obex			usb_cdc_obex_desc
	mbim			usb_cdc_mbim_desc
	mbim_extended		usb_cdc_mbim_extended_desc
] [varlen]

vusb_descriptors_cdc_ncm {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

# https://elixir.bootlin.com/linux/v5.2.7/source/drivers/net/usb/usbnet.c#L147
	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor_t[usb_cdc_ecm_mac]]]
} [packed]

vusb_responses_cdc_ncm {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	USB_CDC_GET_NTB_PARAMETERS	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_NTB_PARAMETERS, usb_cdc_ncm_ntb_parameters]]
	USB_CDC_GET_NTB_INPUT_SIZE	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_NTB_INPUT_SIZE, int32]]
	USB_CDC_GET_NTB_FORMAT		ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_NTB_FORMAT, int16[0:1]]]
	USB_CDC_GET_MAX_DATAGRAM_SIZE	ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_MAX_DATAGRAM_SIZE, int16]]
	USB_CDC_GET_CRC_MODE		ptr[in, vusb_response_t[USB_TYPE_CLASS, USB_CDC_GET_CRC_MODE, int16[0:1]]]
} [packed]

usb_cdc_ncm_ntb_parameters {
	wLength			int16
	bmNtbFormatsSupported	int16
	dwNtbInMaxSize		int32
	wNdpInDivisor		int16
	wNdpInPayloadRemainder	int16
	wNdpInAlignment		int16
	wPadding1		int16
	dwNtbOutMaxSize		int32
	wNdpOutDivisor		int16
	wNdpOutPayloadRemainder	int16
	wNdpOutAlignment	int16
	wNtbOutMaxDatagrams	int16
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC1 device class specific descriptions.
# https://www.usb.org/sites/default/files/audio10.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/audio.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac1.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac1_legacy.c
# https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/usb/audio.h

# TODO: find out which /dev/ files are created by connected UAC1 devices and add descriptions for those.

resource fd_usb_uac1[fd_usb]

syz_usb_connect$uac1(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_uac1], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_uac1 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$uac1(fd fd_usb_uac1, descs ptr[in, vusb_descriptors_uac1], resps ptr[in, vusb_responses_uac1]) (timeout[300], remote_cover)

usb_device_descriptor_uac1 {
	inner	usb_device_descriptor_t[0, 0, 0, 0x1d6b, 0x101, 64, array[usb_config_descriptor_uac1, 1]]
} [packed]

usb_config_descriptor_uac1 {
	inner	usb_config_descriptor_t[const[1, int8], const[3, int8], usb_interface_descriptors_uac1]
} [packed]

# TODO: control interface might have and optional interrupt endpoint.
usb_interface_descriptors_uac1 {
	inner	usb_interface_descriptors_uac1_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_uac1_inner {
	control		usb_interface_descriptor_fixed_t[0, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOCONTROL, 0, uac_control_iface_extra_descriptors, void]
	as_out_alt_0	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, void, void]
	as_out_alt_1	usb_interface_descriptor_fixed_t[1, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, uac_as_iface_extra_descriptors, uac_as_out_endpoint_descriptor]
	as_in_alt_0	usb_interface_descriptor_fixed_t[2, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, void, void]
	as_in_alt_1	usb_interface_descriptor_fixed_t[2, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, 0, uac_as_iface_extra_descriptors, uac_as_in_endpoint_descriptor]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC uses IDs to make it possible for terminals and units to refer to each other.
# We don't have a way to describe this, so just use a limited number of ids.
type uac_id int8[1:6]

uac_control_iface_extra_descriptors {
	header	uac1_ac_header_descriptor
	others	array[uac_control_iface_extra_descriptor, 0:6]
} [packed]

uac1_ac_header_descriptor {
	bLength			const[UAC_DT_AC_HEADER_LENGTH, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_HEADER, int8]

	bcdADC			int16
	wTotalLength		len[uac_control_iface_extra_descriptors, int16]
	bInCollection		const[F_AUDIO_NUM_INTERFACES, int8]

# These must match interfaces numbers.
	baInterfaceNr0		const[1, int8]
	baInterfaceNr1		const[2, int8]
} [packed]

uac_control_iface_extra_descriptor [
	input_terminal	uac_input_terminal_descriptor
	output_terminal	uac1_output_terminal_descriptor
	mixer_unit	uac_mixer_unit_descriptor
	selector_unit	uac_selector_unit_descriptor
	feature_unit	uac_feature_unit_descriptor
	processing_unit	uac_processing_unit_descriptor
	extension_unit	uac_extension_unit_descriptor
] [varlen]

define F_AUDIO_NUM_INTERFACES	2
define UAC_DT_AC_HEADER_LENGTH	UAC_DT_AC_HEADER_SIZE(F_AUDIO_NUM_INTERFACES)

uac_input_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_INPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_input_terminal_types, int16]
	bAssocTerminal		uac_id
	bNrChannels		int8
	wChannelConfig		int16
	iChannelNames		int8
	iTerminal		int8
} [packed]

# The following list contains input terminal types and inout terminal types.
uac_input_terminal_types = UAC_TERMINAL_UNDEFINED, UAC_TERMINAL_STREAMING, UAC_TERMINAL_VENDOR_SPEC, UAC_INPUT_TERMINAL_UNDEFINED, UAC_INPUT_TERMINAL_MICROPHONE, UAC_INPUT_TERMINAL_DESKTOP_MICROPHONE, UAC_INPUT_TERMINAL_PERSONAL_MICROPHONE, UAC_INPUT_TERMINAL_OMNI_DIR_MICROPHONE, UAC_INPUT_TERMINAL_MICROPHONE_ARRAY, UAC_INPUT_TERMINAL_PROC_MICROPHONE_ARRAY, UAC_BIDIR_TERMINAL_UNDEFINED, UAC_BIDIR_TERMINAL_HANDSET, UAC_BIDIR_TERMINAL_HEADSET, UAC_BIDIR_TERMINAL_SPEAKER_PHONE, UAC_BIDIR_TERMINAL_ECHO_SUPPRESSING, UAC_BIDIR_TERMINAL_ECHO_CANCELING
# The following list contains output terminal types and inout terminal types.
uac_output_terminal_types = UAC_TERMINAL_UNDEFINED, UAC_TERMINAL_STREAMING, UAC_TERMINAL_VENDOR_SPEC, UAC_OUTPUT_TERMINAL_UNDEFINED, UAC_OUTPUT_TERMINAL_SPEAKER, UAC_OUTPUT_TERMINAL_HEADPHONES, UAC_OUTPUT_TERMINAL_HEAD_MOUNTED_DISPLAY_AUDIO, UAC_OUTPUT_TERMINAL_DESKTOP_SPEAKER, UAC_OUTPUT_TERMINAL_ROOM_SPEAKER, UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER, UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER, UAC_BIDIR_TERMINAL_UNDEFINED, UAC_BIDIR_TERMINAL_HANDSET, UAC_BIDIR_TERMINAL_HEADSET, UAC_BIDIR_TERMINAL_SPEAKER_PHONE, UAC_BIDIR_TERMINAL_ECHO_SUPPRESSING, UAC_BIDIR_TERMINAL_ECHO_CANCELING

uac1_output_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_OUTPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_output_terminal_types, int16]
	bAssocTerminal		uac_id
	bSourceID		uac_id
	iTerminal		int8
} [packed]

uac_mixer_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIXER_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac_selector_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_SELECTOR_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac_feature_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FEATURE_UNIT, int8]

	bUnitID			uac_id
	bSourceID		uac_id
	bControlSize		len[bmaControls, int8]
	bmaControls		array[flags[uac_feature_unit_controls, int16], 1:6]
	iFeature		int8
} [packed]

uac_feature_unit_controls = UAC_FU_MUTE, UAC_FU_VOLUME, UAC_FU_BASS, UAC_FU_MID, UAC_FU_TREBLE, UAC_FU_GRAPHIC_EQUALIZER, UAC_FU_AUTOMATIC_GAIN, UAC_FU_DELAY, UAC_FU_BASS_BOOST, UAC_FU_LOUDNESS

uac_processing_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC1_PROCESSING_UNIT, int8]

	bUnitID			uac_id
	wProcessType		flags[uac_processing_unit_types, int16]
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac_processing_unit_types = UAC_PROCESS_UNDEFINED, UAC_PROCESS_UP_DOWNMIX, UAC_PROCESS_DOLBY_PROLOGIC, UAC_PROCESS_STEREO_EXTENDER, UAC_PROCESS_REVERB, UAC_PROCESS_CHORUS, UAC_PROCESS_DYN_RANGE_COMP

uac_extension_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC1_EXTENSION_UNIT, int8]

	bUnitID			uac_id
	wProcessType		int16
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac_as_iface_extra_descriptors {
	others	array[uac_as_iface_extra_descriptor, 0:6]
} [packed]

uac_as_iface_extra_descriptor [
	as_header			uac1_as_header_descriptor
	format_type_i_continuous	uac_format_type_i_continuous_descriptor
	format_type_i_discrete		uac_format_type_i_discrete_descriptor
	format_type_ii_discrete		uac_format_type_ii_discrete_descriptor
	format_type_ii_ext		uac_format_type_ii_ext_descriptor
	format_type_i_ext		uac_format_type_i_ext_descriptor
] [varlen]

uac1_as_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_AS_GENERAL, int8]

	bTerminalLink		int8
	bDelay			int8
	wFormatTag		flags[uac_format_tags, int16]
} [packed]

uac_format_tags = UAC_FORMAT_TYPE_I_UNDEFINED, UAC_FORMAT_TYPE_I_PCM, UAC_FORMAT_TYPE_I_PCM8, UAC_FORMAT_TYPE_I_IEEE_FLOAT, UAC_FORMAT_TYPE_I_ALAW, UAC_FORMAT_TYPE_I_MULAW, UAC_FORMAT_TYPE_II_MPEG, UAC_FORMAT_TYPE_II_AC3
uac_usb_format_types_i = UAC_FORMAT_TYPE_I, UAC_FORMAT_TYPE_II, UAC_FORMAT_TYPE_III, UAC_FORMAT_TYPE_UNDEFINED

uac_format_type_i_continuous_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bNrChannels		int8
	bSubframeSize		int8[1:4]
	bBitResolution		int8
	bSamFreqType		int8
	tLowerSamFreq		array[int8, 0:3]
	tUpperSamFreq		array[int8, 0:3]
} [packed]

uac_format_type_i_discrete_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bNrChannels		int8
	bSubframeSize		int8[1:4]
	bBitResolution		int8
	bSamFreqType		int8
	tSamFreq		array[int8, 0:9]
} [packed]

uac_format_type_ii_discrete_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_II, int8]
	wMaxBitRate		int16
	wSamplesPerFrame	int16
	bSamFreqType		int8
	tSamFreq		array[int8, 0:9]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac_as_out_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac_iso_endpoint_descriptor]
} [packed]

uac_as_in_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_IN_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac_iso_endpoint_descriptor]
} [packed]

define USB_ENDPOINT_UAC1_AS_OUT_ADDRESS	(1 | USB_DIR_OUT)
define USB_ENDPOINT_UAC1_AS_IN_ADDRESS	(2 | USB_DIR_IN)
define USB_ENDPOINT_UAC1_AS_ATTRIBUTES	(USB_ENDPOINT_SYNC_ADAPTIVE | USB_ENDPOINT_XFER_ISOC)

uac_iso_ep_attributes = USB_ENDPOINT_SYNCTYPE, USB_ENDPOINT_SYNC_NONE, USB_ENDPOINT_SYNC_ASYNC, USB_ENDPOINT_SYNC_ADAPTIVE, USB_ENDPOINT_SYNC_SYNC

uac_iso_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubType	const[UAC_EP_GENERAL, int8]

	bmAttributes		flags[uac_iso_ep_attributes, int8]
	bLockDelayUnits		int8
	wLockDelay		int16
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

vusb_descriptors_uac1 {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_uac1 {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	audio_UAC_GET_CUR		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_CUR, array[int8, 1:3]]]
	audio_UAC_GET_MIN		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_MIN, array[int8, 1:3]]]
	audio_UAC_GET_MAX		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_MAX, array[int8, 1:3]]]
	audio_UAC_GET_RES		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_RES, array[int8, 1:4]]]
	audio_UAC_GET_MEM		ptr[in, vusb_response_t[USB_TYPE_CLASS, UAC_GET_MEM, array[int8, 3]]]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC2 device class specific descriptions.
# https://www.usb.org/sites/default/files/audio10.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/audio.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac2.c
# https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/usb/audio.h

resource fd_usb_uac2[fd_usb]

syz_usb_connect$uac2(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_uac2], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_uac2 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$uac2(fd fd_usb_uac2, descs ptr[in, vusb_descriptors_uac1], resps ptr[in, vusb_responses_uac1]) (timeout[300], remote_cover)

usb_device_descriptor_uac2 {
	inner	usb_device_descriptor_t[0, 0, 0, 0x41e, 0x3000, 64, array[usb_config_descriptor_uac2, 1]]
} [packed]

usb_config_descriptor_uac2 {
	inner	usb_config_descriptor_extra_t[const[1, int8], const[3, int8], uac2_interface_assoc_descriptor, usb_interface_descriptors_uac2]
} [packed]

uac2_interface_assoc_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_INTERFACE_ASSOCIATION, int8]

	bFirstInterface		int8[0:2]
	bInterfaceCount		int8[0:2]
	bFunctionClass		const[USB_CLASS_AUDIO, int8]
	bFunctionSubClass	flags[audio_function_category_types, int8]
	bFunctionProtocol	const[UAC_VERSION_2, int8]
	iFunction		int8
} [packed]

audio_function_category_types = UAC2_FUNCTION_SUBCLASS_UNDEFINED, UAC2_FUNCTION_DESKTOP_SPEAKER, UAC2_FUNCTION_HOME_THEATER, UAC2_FUNCTION_MICROPHONE, UAC2_FUNCTION_HEADSET, UAC2_FUNCTION_TELEPHONE, UAC2_FUNCTION_CONVERTER, UAC2_FUNCTION_SOUND_RECORDER, UAC2_FUNCTION_IO_BOX, UAC2_FUNCTION_MUSICAL_INSTRUMENT, UAC2_FUNCTION_PRO_AUDIO, UAC2_FUNCTION_AUDIO_VIDEO, UAC2_FUNCTION_CONTROL_PANEL, UAC2_FUNCTION_OTHER

usb_interface_descriptors_uac2 {
	inner	usb_interface_descriptors_uac2_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_uac2_inner {
	control		usb_interface_descriptor_fixed_t[0, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOCONTROL, UAC_VERSION_2, uac2_control_iface_extra_descriptors, void]
	as_out_alt_0	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, void, void]
	as_out_alt_1	usb_interface_descriptor_fixed_t[1, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, uac2_as_iface_extra_descriptors, uac2_as_out_endpoint_descriptor]
	as_in_alt_0	usb_interface_descriptor_fixed_t[2, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, void, void]
	as_in_alt_1	usb_interface_descriptor_fixed_t[2, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_2, uac2_as_iface_extra_descriptors, uac2_as_in_endpoint_descriptor]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac2_control_iface_extra_descriptors {
	header	uac2_ac_header_descriptor
	others	array[uac2_control_iface_extra_descriptor, 0:6]
} [packed]

uac2_ac_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MS_HEADER, int8]
	bcdADC			int16
	bCategory		flags[uac2_feature_unit_controls, int8]
	wTotalLength		len[uac2_control_iface_extra_descriptors, int16]
	bmControls		int8
} [packed]

uac2_feature_unit_controls = UAC2_FUNCTION_SUBCLASS_UNDEFINED, UAC2_FUNCTION_DESKTOP_SPEAKER, UAC2_FUNCTION_HOME_THEATER, UAC2_FUNCTION_MICROPHONE, UAC2_FUNCTION_HEADSET, UAC2_FUNCTION_TELEPHONE, UAC2_FUNCTION_CONVERTER, UAC2_FUNCTION_SOUND_RECORDER, UAC2_FUNCTION_IO_BOX, UAC2_FUNCTION_MUSICAL_INSTRUMENT, UAC2_FUNCTION_PRO_AUDIO, UAC2_FUNCTION_AUDIO_VIDEO, UAC2_FUNCTION_CONTROL_PANEL, UAC2_FUNCTION_OTHER, uac_feature_unit_controls

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac2_as_iface_extra_descriptors {
	others	array[uac2_as_iface_extra_descriptor, 0:6]
} [packed]

uac2_as_iface_extra_descriptor [
	as_header			uac2_as_header_descriptor
	format_type_i_descriptor	uac2_format_type_i_descriptor
	format_type_i_continuous	uac_format_type_i_continuous_descriptor
	format_type_i_discrete		uac_format_type_i_discrete_descriptor
	format_type_ii_discrete		uac_format_type_ii_discrete_descriptor
	format_type_i_ext		uac2_format_type_i_ext_descriptor
	format_type_ii_ext		uac_format_type_ii_ext_descriptor
] [varlen]

uac2_as_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_AS_GENERAL, int8]
	bTerminalLink		int8
	bmControls		int8
	bFormatType		flags[uac_usb_format_types_i, int8]
	bmFormats		flags[uac_format_tags, int32]
	bNrChannels		int8
	bmChannelConfig		int32
	iChannelNames		int8
} [packed]

b_sub_slot_sizes = 1, 2, 3, 4

uac2_format_type_i_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]
	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bSubslotSize		flags[b_sub_slot_sizes, int8]
	bBitResolution		int8
} [packed]

uac2_format_type_i_ext_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]

	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bSubslotSize		int8
	bBitResolution		int8
	bHeaderLength		int8
	bControlSize		int8
	bSideBandProtocol	int8
} [packed]

uac_format_type_ii_ext_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]
	bFormatType		const[UAC_FORMAT_TYPE_II, int8]
	wMaxBitRate		int16
	wSamplesPerFrame	int16
	bHeaderLength		int8
	bSideBandProtocol	int8
} [packed]

uac_format_type_i_ext_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_FORMAT_TYPE, int8]
	bFormatType		const[UAC_FORMAT_TYPE_I, int8]
	bSubslotSize		int8
	bBitResolution		int8
	bHeaderLength		int8
	bControlSize		int8
	bSideBandProtocol	int8
} [packed]

uac2_as_out_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac2_iso_endpoint_descriptor]
} [packed]

uac2_as_in_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_IN_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac2_iso_endpoint_descriptor]
} [packed]

uac2_iso_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubtype	const[UAC_EP_GENERAL, int8]

	bmAttributes		flags[csep_bm_attributes, int8]
	bmControls		flags[csep_bm_controls, int8]
	bLockDelayUnits		int8
	wLockDelay		int16
} [packed]

csep_bm_attributes = UAC_EP_CS_ATTR_SAMPLE_RATE, UAC_EP_CS_ATTR_PITCH_CONTROL, UAC_EP_CS_ATTR_FILL_MAX
csep_bm_controls = UAC2_CONTROL_PITCH, UAC2_CONTROL_DATA_OVERRUN, UAC2_CONTROL_DATA_UNDERRUN

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac2_control_iface_extra_descriptor [
	input_terminal	uac2_input_terminal_descriptor
	output_terminal	uac2_output_terminal_descriptor
	mixer_unit	uac2_mixer_unit_descriptor
	selector_unit	uac2_clock_selector_descriptor

	feature_unit	uac2_feature_unit_descriptor
	processing_unit	uac2_processing_unit_descriptor
	extension_unit	uac2_extension_unit_descriptor

	effect_unit	uac2_effect_unit_descriptor
	sample_rate	uac2_sample_rate_descriptor
	source_unit	uac2_clock_source_descriptor
	multiply_unit	uac2_clock_multiplier_descriptor
] [varlen]

uac2_input_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_INPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_input_terminal_types, int16]
	bAssocTerminal		uac_id
	bCSourceID		int8
	bNrChannels		int8
	bmChannelConfig		int32
	iChannelNames		int8
	bmControls		int8
	iTerminal		int8
} [packed]

uac2_output_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_OUTPUT_TERMINAL, int8]
	bTerminalID		uac_id
	wTerminalType		flags[uac_output_terminal_types, int16]
	bAssocTerminal		int8
	bSourceID		uac_id
	bCSourceID		int8
	bmControls		int16
	iTerminal		int8
} [packed]

uac2_mixer_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIXER_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

# TODO: Figure out if bmControls and iClockSelector should be a part of this structure.
uac2_clock_selector_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_CLOCK_SELECTOR, int8]
	bClockID		int8
	bNrInPins		len[baCSourceID, int8]
	baCSourceID		array[int8, 0:8]
} [packed]

# TODO: Verify coverage.
uac2_processing_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC2_PROCESSING_UNIT_V2, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac2_processing_unit_types, int16], 1:6]
} [packed]

uac2_processing_unit_types = UAC2_PROCESS_UNDEFINED, UAC2_PROCESS_UP_DOWNMIX, UAC2_PROCESS_DOLBY_PROLOCIC, UAC2_PROCESS_STEREO_EXTENDER

uac2_extension_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_EXTENSION_UNIT_V2, int8]

	bUnitID			uac_id
	wProcessType		int16
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

# TODO: Verify coverage.
uac2_effect_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC2_EFFECT_UNIT, int8]
	bUnitID			uac_id
	wEffectType		flags[uac2_effect_unit_types, int16]
	bSourceID		uac_id
	bmaControls		array[flags[uac2_processing_unit_types, int16], 1:6]
} [packed]

uac2_effect_unit_types = UAC2_EFFECT_UNDEFINED, UAC2_EFFECT_PARAM_EQ, UAC2_EFFECT_REVERB, UAC2_EFFECT_MOD_DELAY, UAC2_EFFECT_DYN_RANGE_COMP

uac2_sample_rate_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC2_SAMPLE_RATE_CONVERTER, int8]
	bUnitID			uac_id
	wProcessType		flags[uac2_processing_unit_types, int16]
	bSourceID		uac_id
	bmaControls		array[flags[uac2_processing_unit_types, int16], 1:6]
} [packed]

uac2_feature_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_FEATURE_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac2_feature_unit_controls, int16], 1:6]
} [packed]

uac2_clock_source_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_CLOCK_SOURCE, int8]
	bClockID		int8
	bmAttributes		flags[uac2_clock_bmattribute_types, int8]
	bmControls		int8
	bAssocTerminal		int8
	iClockSource		flags[uac2_clock_source_types, int8]
} [packed]

uac2_clock_bmattribute_types = UAC_CLOCK_SOURCE_TYPE_EXT, UAC_CLOCK_SOURCE_TYPE_INT_FIXED, UAC_CLOCK_SOURCE_TYPE_INT_VAR, UAC_CLOCK_SOURCE_TYPE_INT_PROG, UAC_CLOCK_SOURCE_SYNCED_TO_SOF
uac2_clock_source_types = UAC_CLOCK_SOURCE_TYPE_EXT, UAC_CLOCK_SOURCE_TYPE_INT_FIXED, UAC_CLOCK_SOURCE_TYPE_INT_VAR, UAC_CLOCK_SOURCE_TYPE_INT_PROG, UAC_CLOCK_SOURCE_SYNCED_TO_SOF

uac2_clock_multiplier_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC2_CLOCK_MULTIPLIER, int8]
	bClockID		int8
	bCSourceID		int8
	bmControls		int8
	iClockMultiplier	int8
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# UAC3 device class specific descriptions.
# https://www.usb.org/sites/default/files/audio10.pdf
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/legacy/audio.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_uac3.c
# https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/usb/audio.h

resource fd_usb_uac3[fd_usb]

syz_usb_connect$uac3(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_uac3], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb_uac3 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$uac3(fd fd_usb_uac3, descs ptr[in, vusb_descriptors_uac1], resps ptr[in, vusb_responses_uac1]) (timeout[300], remote_cover)

usb_device_descriptor_uac3 {
	inner	usb_device_descriptor_t[0, 0, 0, 0x582, 0x582, 64, array[usb_config_descriptor_uac3, 1]]
} [packed]

usb_config_descriptor_uac3 {
	inner	usb_config_descriptor_extra_t[const[1, int8], const[3, int8], uac3_interface_assoc_descriptor, usb_interface_descriptors_uac3]
} [packed]

uac3_interface_assoc_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_INTERFACE_ASSOCIATION, int8]

	bFirstInterface		int8[0:2]
	bInterfaceCount		int8[0:2]
	bFunctionClass		const[USB_CLASS_AUDIO, int8]
	bFunctionSubClass	flags[uac3_all_subclasses, int8]
	bFunctionProtocol	const[UAC_VERSION_3, int8]
	iFunction		int8
} [packed]

usb_interface_descriptors_uac3 {
	inner	usb_interface_descriptors_uac3_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_uac3_inner {
	control		usb_interface_descriptor_fixed_t[0, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOCONTROL, UAC_VERSION_3, uac3_control_iface_extra_descriptors, void]
	as_out_alt_0	usb_interface_descriptor_fixed_t[1, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, void, void]
	as_out_alt_1	usb_interface_descriptor_fixed_t[1, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, uac3_as_iface_extra_descriptors, uac3_as_out_endpoint_descriptor]
	as_in_alt_0	usb_interface_descriptor_fixed_t[2, 0, 0, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, void, void]
	as_in_alt_1	usb_interface_descriptor_fixed_t[2, 1, 1, USB_CLASS_AUDIO, USB_SUBCLASS_AUDIOSTREAMING, UAC_VERSION_3, uac3_as_iface_extra_descriptors, uac3_as_in_endpoint_descriptor]
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac3_control_iface_extra_descriptors {
	header	uac3_ac_header_descriptor
	others	array[uac3_control_iface_extra_descriptor, 0:6]
} [packed]

uac3_ac_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MS_HEADER, int8]

	bCategory		flags[uac3_feature_unit_controls, int8]
	wTotalLength		len[uac3_control_iface_extra_descriptors, int16]
	bmControls		int32
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac3_as_iface_extra_descriptors {
	others	array[uac3_as_iface_extra_descriptor, 0:6]
} [packed]

uac3_as_iface_extra_descriptor [
	as_header			uac3_as_header_descriptor
	format_type_i_descriptor	uac2_format_type_i_descriptor
	format_type_i_continuous	uac_format_type_i_continuous_descriptor
	format_type_i_discrete		uac_format_type_i_discrete_descriptor
	format_type_ii_discrete		uac_format_type_ii_discrete_descriptor
	format_type_i_ext		uac2_format_type_i_ext_descriptor
	format_type_ii_ext		uac_format_type_ii_ext_descriptor
] [varlen]

# TODO: Figure out how wClusterDescrID is used in the kernel.
uac3_as_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_AS_GENERAL, int8]
	bTerminalLink		int8

	bmControls		int32
	wClusterDescrID		int16

	bmFormats		flags[uac_format_tags, int64]

	bSubslotSize		int8
	bBitResolution		int8
	bmAuxProtocols		int16
	bControlSize		int8
} [packed]

uac3_as_out_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac3_iso_endpoint_descriptor]
} [packed]

uac3_as_in_endpoint_descriptor {
	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_IN_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac3_iso_endpoint_descriptor]
} [packed]

uac3_iso_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubType	const[UAC3_CS_ENDPOINT, int8]
	bmControls		int32
	bLockDelayUnits		int8
	wLockDelay		int16
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

uac3_control_iface_extra_descriptor [
	input_terminal		uac3_input_terminal_descriptor
	output_terminal		uac3_output_terminal_descriptor
	mixer_unit		uac3_mixer_unit_descriptor
	selector_unit		uac3_clock_selector_descriptor
	source_unit		uac3_clock_source_descriptor
	multiply_unit		uac3_clock_multiplier_descriptor
	feature_unit		uac3_feature_unit_descriptor
	processing_unit		uac3_processing_unit_descriptor
	extension_unit		uac3_extension_unit_descriptor
	power_domain		uac3_power_domain_descriptor
	cluster_info_segment	uac3_cluster_information_segment_descriptor
# Only cluster information segment is currently used in the kernel.See: sound/usb/stream.c
# cluster_segment 		uac3_cluster_segment_descriptor
# cluster_end_segment		uac3_cluster_end_segment_descriptor
# The following units are not yet supported by the kernel.
# See audio_validators[] in sound/usb/validate.c:
#	effect_unit 		uac3_effect_unit_descriptor
#	sample_rate			uac3_sample_rate_descriptor
#	connectors_unit		uac3_connectors_unit_descriptor
#	extended_term_unit	uac3_extended_terminal_unit
] [varlen]

uac3_input_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_INPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_input_terminal_types, int16]
	bAssocTerminal		uac_id
	bCSourceID		int8

	bmControls		int32
	wClusterDescrID		int16
	wExTerminalDescrID	int16
	wConnectorsDescrID	int16
	wTerminalDescrStr	int16
} [packed]

uac3_output_terminal_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC_OUTPUT_TERMINAL, int8]

	bTerminalID		uac_id
	wTerminalType		flags[uac_output_terminal_types, int16]
	bAssocTerminal		uac_id
	bSourceID		uac_id
	bCSourceID		int8

	bmControls		int32
	wExTerminalDescrID	int16
	wConnectorsDescrID	int16
	wTerminalDescrStr	int16
} [packed]

uac3_mixer_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_MIXER_UNIT, int8]

	bUnitID			uac_id
	bNrInPins		int8
	baSourceID		array[int8, 0:6]
} [packed]

uac3_clock_selector_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_CLOCK_SELECTOR, int8]
	bClockID		int8
	bNrInPins		len[baCSourceID, int8]
	baCSourceID		array[int8, 0:8]
} [packed]

uac3_clock_source_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_CLOCK_SOURCE, int8]
	bClockID		int8
	bmAttributes		flags[uac3_clock_bmattribute_types, int8]
	bmControls		int32
	bReferenceTerminal	int8
	wClockSourceStr		int16
} [packed]

uac3_clock_bmattribute_types = UAC3_CLOCK_SOURCE_TYPE_EXT, UAC3_CLOCK_SOURCE_TYPE_INT, UAC3_CLOCK_SOURCE_ASYNC, UAC3_CLOCK_SOURCE_SYNCED_TO_SOF

uac3_clock_multiplier_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_CLOCK_MULTIPLIER, int8]
	bClockID		int8
	bCSourceID		int8
	bmControls		int32
	wCMultiplierDescrStr	int16
} [packed]

uac3_feature_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC3_FEATURE_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac3_feature_unit_controls, int32], 1:6]
} [packed]

uac3_processing_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC3_PROCESSING_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac3_processing_unit_types, int32], 1:6]
} [packed]

uac3_processing_unit_types = UAC3_PROCESS_UNDEFINED, UAC3_PROCESS_UP_DOWNMIX, UAC3_PROCESS_STEREO_EXTENDER, UAC3_PROCESS_MULTI_FUNCTION

uac3_extension_unit_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubtype	const[UAC3_EXTENSION_UNIT, int8]
	bUnitID			uac_id
	bSourceID		uac_id
	bmaControls		array[flags[uac3_processing_unit_types, int32], 1:6]
} [packed]

uac3_power_domain_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC3_POWER_DOMAIN, int8]

	bPowerDomainID		int8
	waRecoveryTime1		int16
	waRecoveryTime2		int16
	bNrEntities		int8
	baEntityID		array[int8, 0:8]
} [packed]

uac3_cluster_information_segment_descriptor {
	bLength		len[parent, int16]
	bSegmentType	const[UAC3_CHANNEL_INFORMATION, int8]
	bChPurpose	flags[uac3_cluster_channel_purposes, int8]
	bChRelationship	flags[uac3_cluster_channel_relationships, int8]
	bChGroupID	int8
} [packed]

uac3_cluster_channel_purposes = UAC3_PURPOSE_UNDEFINED, UAC3_PURPOSE_GENERIC_AUDIO, UAC3_PURPOSE_VOICE, UAC3_PURPOSE_SPEECH, UAC3_PURPOSE_AMBIENT, UAC3_PURPOSE_REFERENCE, UAC3_PURPOSE_ULTRASONIC, UAC3_PURPOSE_VIBROKINETIC, UAC3_PURPOSE_NON_AUDIO
uac3_cluster_channel_relationships = UAC3_CH_RELATIONSHIP_UNDEFINED, UAC3_CH_MONO, UAC3_CH_LEFT, UAC3_CH_RIGHT, UAC3_CH_ARRAY, UAC3_CH_PATTERN_X, UAC3_CH_PATTERN_Y, UAC3_CH_PATTERN_A, UAC3_CH_PATTERN_B, UAC3_CH_PATTERN_M, UAC3_CH_PATTERN_S, UAC3_CH_FRONT_LEFT, UAC3_CH_FRONT_RIGHT, UAC3_CH_FRONT_CENTER, UAC3_CH_FRONT_LEFT_OF_CENTER, UAC3_CH_FRONT_RIGHT_OF_CENTER, UAC3_CH_FRONT_WIDE_LEFT, UAC3_CH_FRONT_WIDE_RIGHT, UAC3_CH_SIDE_LEFT, UAC3_CH_SIDE_RIGHT, UAC3_CH_SURROUND_ARRAY_LEFT, UAC3_CH_SURROUND_ARRAY_RIGHT, UAC3_CH_BACK_LEFT, UAC3_CH_BACK_RIGHT, UAC3_CH_BACK_CENTER, UAC3_CH_BACK_LEFT_OF_CENTER, UAC3_CH_BACK_RIGHT_OF_CENTER, UAC3_CH_BACK_WIDE_LEFT, UAC3_CH_BACK_WIDE_RIGHT, UAC3_CH_TOP_CENTER, UAC3_CH_TOP_FRONT_LEFT, UAC3_CH_TOP_FRONT_RIGHT, UAC3_CH_TOP_FRONT_CENTER, UAC3_CH_TOP_FRONT_LOC, UAC3_CH_TOP_FRONT_ROC, UAC3_CH_TOP_FRONT_WIDE_LEFT, UAC3_CH_TOP_FRONT_WIDE_RIGHT, UAC3_CH_TOP_SIDE_LEFT, UAC3_CH_TOP_SIDE_RIGHT, UAC3_CH_TOP_SURR_ARRAY_LEFT, UAC3_CH_TOP_SURR_ARRAY_RIGHT, UAC3_CH_TOP_BACK_LEFT, UAC3_CH_TOP_BACK_RIGHT, UAC3_CH_TOP_BACK_CENTER, UAC3_CH_TOP_BACK_LOC, UAC3_CH_TOP_BACK_ROC, UAC3_CH_TOP_BACK_WIDE_LEFT, UAC3_CH_TOP_BACK_WIDE_RIGHT, UAC3_CH_BOTTOM_CENTER, UAC3_CH_BOTTOM_FRONT_LEFT, UAC3_CH_BOTTOM_FRONT_RIGHT, UAC3_CH_BOTTOM_FRONT_CENTER, UAC3_CH_BOTTOM_FRONT_LOC, UAC3_CH_BOTTOM_FRONT_ROC, UAC3_CH_BOTTOM_FRONT_WIDE_LEFT, UAC3_CH_BOTTOM_FRONT_WIDE_RIGHT, UAC3_CH_BOTTOM_SIDE_LEFT, UAC3_CH_BOTTOM_SIDE_RIGHT, UAC3_CH_BOTTOM_SURR_ARRAY_LEFT, UAC3_CH_BOTTOM_SURR_ARRAY_RIGHT, UAC3_CH_BOTTOM_BACK_LEFT, UAC3_CH_BOTTOM_BACK_RIGHT, UAC3_CH_BOTTOM_BACK_CENTER, UAC3_CH_BOTTOM_BACK_LOC, UAC3_CH_BOTTOM_BACK_ROC, UAC3_CH_BOTTOM_BACK_WIDE_LEFT, UAC3_CH_BOTTOM_BACK_WIDE_RIGHT, UAC3_CH_LOW_FREQUENCY_EFFECTS, UAC3_CH_LFE_LEFT, UAC3_CH_LFE_RIGHT, UAC3_CH_HEADPHONE_LEFT, UAC3_CH_HEADPHONE_RIGHT

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# This list consists of uac3_func_subclasses + uac3_badd_classes.
uac3_all_subclasses = UAC3_FUNCTION_SUBCLASS_UNDEFINED, UAC3_FUNCTION_SUBCLASS_FULL_ADC_3_0, UAC3_FUNCTION_SUBCLASS_GENERIC_IO, UAC3_FUNCTION_SUBCLASS_HEADPHONE, UAC3_FUNCTION_SUBCLASS_SPEAKER, UAC3_FUNCTION_SUBCLASS_MICROPHONE, UAC3_FUNCTION_SUBCLASS_HEADSET, UAC3_FUNCTION_SUBCLASS_HEADSET_ADAPTER, UAC3_FUNCTION_SUBCLASS_SPEAKERPHONE

uac3_feature_unit_controls = UAC3_FUNCTION_SUBCLASS_UNDEFINED, UAC3_FUNCTION_DESKTOP_SPEAKER, UAC3_FUNCTION_HOME_THEATER, UAC3_FUNCTION_MICROPHONE, UAC3_FUNCTION_HEADSET, UAC3_FUNCTION_TELEPHONE, UAC3_FUNCTION_CONVERTER, UAC3_FUNCTION_SOUND_RECORDER, UAC3_FUNCTION_IO_BOX, UAC3_FUNCTION_MUSICAL_INSTRUMENT, UAC3_FUNCTION_PRO_AUDIO, UAC3_FUNCTION_AUDIO_VIDEO, UAC3_FUNCTION_CONTROL_PANEL, UAC3_FUNCTION_HEADPHONE, UAC3_FUNCTION_GENERIC_SPEAKER, UAC3_FUNCTION_HEADSET_ADAPTER, UAC3_FUNCTION_SPEAKERPHONE, UAC3_FUNCTION_OTHER

# TODO: Support uac3 badd profiles. See sound/usb/mixer.c: snd_usb_mixer_controls_badd()
# uac3_badd_endpoint_descriptor {
# 	inner	usb_endpoint_descriptor_t[const[USB_ENDPOINT_UAC1_AS_OUT_ADDRESS, int8], const[USB_ENDPOINT_UAC1_AS_ATTRIBUTES, int8], uac3_iso_endpoint_descriptor]
# } [packed]

#uac3_badd_maxsizes = UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16,UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16,UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24,UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24,UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16,UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16,UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24,UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# MIDI device class specific descriptions.
# https://www.usb.org/sites/default/files/midi10.pdf
# https://elixir.bootlin.com/linux/latest/source/sound/usb/midi.c
# https://elixir.bootlin.com/linux/latest/source/drivers/usb/gadget/function/f_midi.c

syz_usb_connect$midi(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_midi], conn_descs ptr[in, vusb_connect_descriptors]) fd_usb (timeout[3000], prog_timeout[3000], remote_cover)

usb_device_descriptor_midi {
	inner	usb_device_descriptor_t[0, 0, 0, 0x1430, 0x474b, 64, array[usb_config_descriptor_midi, 1]]
} [packed]

usb_config_descriptor_midi {
	inner	usb_config_descriptor_t[const[1, int8], const[1, int8], usb_interface_descriptors_midi]
} [packed]

usb_interface_descriptors_midi {
	inner	usb_interface_descriptors_midi_inner
} [packed]

# Define folded-in structure to match layout expected by USB ID patching code.
usb_interface_descriptors_midi_inner {
	control	usb_interface_descriptor_eps_array_t[const[0, int8], const[0, int8], const[USB_CLASS_AUDIO, int8], const[USB_SUBCLASS_MIDISTREAMING, int8], flags[uac_version_types, int8], array[usb_midi_iface_extra], array[usb_endpoint_descriptor_midi, 0:8]]
} [packed]

usb_endpoint_descriptor_midi {
	inner	usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], flags[usb_endpoint_attributes, int8], usb_ms_endpoint_descriptor]
} [packed]

midi_jack_type = USB_MS_EMBEDDED, USB_MS_EXTERNAL
uac_version_types = UAC_VERSION_1, UAC_VERSION_2, UAC_VERSION_3

usb_ms_endpoint_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_ENDPOINT, int8]
	bDescriptorSubType	const[USB_MS_GENERAL, int8]
	bNumEmbMIDIJack		len[baAssocJackID, int8]
	baAssocJackID		array[int8, 0:16]
} [packed]

usb_midi_iface_extra [
	ms_header	usb_ms_header_descriptor
	midi_in_jack	usb_midi_in_jack_descriptor
	midi_out_jack	usb_midi_out_jack_descriptor
] [varlen]

usb_ms_header_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_HEADER, int8]
	bcdMSC			int16
	wTotalLength		len[parent, int16]
} [packed]

usb_midi_in_jack_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIDI_IN_JACK, int8]
	bJackType		flags[midi_jack_type, int8]
	bJackID			int8
	iJack			int8
} [packed]

usb_midi_out_jack_descriptor {
	bLength			len[parent, int8]
	bDescriptorType		const[USB_DT_CS_INTERFACE, int8]
	bDescriptorSubType	const[UAC_MIDI_OUT_JACK, int8]
	bJackType		flags[midi_jack_type, int8]
	bJackID			int8
	bNrInputPins		len[pins, int8]
	pins			array[usb_midi_source_pin]
	iJack			int8
} [packed]

usb_midi_source_pin {
	baSourceID	int8
	baSourcePin	int8
} [packed]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# ath9k driver specific descriptions.

include <drivers/net/wireless/ath/ath9k/htc_hst.h>
include <drivers/net/wireless/ath/ath9k/hif_usb.h>

define USB_ENDPOINT_ATH9K_BULK_OUT_ADDRESS	(1)
define USB_ENDPOINT_ATH9K_BULK_IN_ADDRESS	(2 | USB_DIR_IN)
define USB_ENDPOINT_ATH9K_INT_IN_ADDRESS	(3 | USB_DIR_IN)
define USB_ENDPOINT_ATH9K_INT_OUT_ADDRESS	(4)
define USB_ENDPOINT_ATH9K_BULK_EXTRA1_ADDRESS	(5)
define USB_ENDPOINT_ATH9K_BULK_EXTRA2_ADDRESS	(6)

resource fd_usb_ath9k[fd_usb]

syz_usb_connect_ath9k(speed const[USB_SPEED_HIGH], dev_len len[dev], dev ptr[in, usb_device_descriptor_ath9k], conn_descs const[0]) fd_usb_ath9k (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_ep_write$ath9k_ep1(fd fd_usb_ath9k, ep const[USB_ENDPOINT_ATH9K_BULK_IN_ADDRESS], len bytesize[data], data ptr[in, ath9k_bulk_frame]) (timeout[300], remote_cover)
syz_usb_ep_write$ath9k_ep2(fd fd_usb_ath9k, ep const[USB_ENDPOINT_ATH9K_INT_IN_ADDRESS], len bytesize[data], data ptr[in, htc_frame]) (timeout[300], remote_cover)

usb_device_descriptor_ath9k {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0xcf3, 0x9271, 0x108, array[usb_config_descriptor_ath9k, 1]]
} [packed]

usb_config_descriptor_ath9k {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_ath9k]
} [packed]

usb_interface_descriptor_ath9k {
	iface	usb_interface_descriptor_fixed_t[0, 0, 6, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_ath9k]
} [packed]

usb_endpoint_descriptors_ath9k {
	bulk_out	usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_OUT_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
	bulk_in		usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_IN_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
	int_in		usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_INT_IN_ADDRESS, USB_ENDPOINT_ATH9K_INT_ATTRIBUTES, 64, 1, void]
	int_out		usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_INT_OUT_ADDRESS, USB_ENDPOINT_ATH9K_INT_ATTRIBUTES, 64, 1, void]
	bulk_extra1	usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_EXTRA1_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
	bulk_extra2	usb_endpoint_descriptor_fixed_t[USB_ENDPOINT_ATH9K_BULK_EXTRA2_ADDRESS, USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES, 512, 0, void]
} [packed]

define USB_ENDPOINT_ATH9K_BULK_ATTRIBUTES	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_ATH9K_INT_ATTRIBUTES	(USB_ENDPOINT_XFER_INT)

ath9k_bulk_frame {
	packets	array[ath9k_bulk_packet]
} [packed]

ath9k_bulk_packet {
	pkt_len	len[data, int16]
	pkt_tag	const[ATH_USB_RX_STREAM_MODE_TAG, int16]
	data	array[int8]
} [packed, align[4]]

htc_frame [
	ready		htc_ready_frame
	conn_svc_rsp	htc_conn_svc_rsp_frame
	generic		htc_generic_frame
] [varlen]

# This is actually wrong, as the driver is buggy and doesn't skip the header
# before processing the frame payload, but let's leave it like thise for now.
htc_ready_frame {
	endpoint_id	const[0, int8]
	flags		const[0, int8]
	payload_len	len[payload, int16be]
	control		array[int8, 4]
	payload		htc_ready_msg
} [packed]

htc_ready_msg {
	message_id	const[HTC_MSG_READY_ID, int16be]
	credits		int16be
	credit_size	int16be
	max_endpoints	int8
	pad		int8
} [packed]

htc_conn_svc_rsp_frame {
	endpoint_id	const[0, int8]
	flags		const[0, int8]
	payload_len	len[payload, int16be]
	control		array[int8, 4]
	payload		htc_conn_svc_rspmsg
} [packed]

htc_conn_svc_rspmsg {
	message_id	const[HTC_MSG_CONNECT_SERVICE_RESPONSE_ID, int16be]
	service_id	flags[htc_svcs, int16be]
	status		const[HTC_SERVICE_SUCCESS, int8]
	endpoint_id	int8
	max_msg_len	int16be
	svc_meta_len	int8
	pad		int8
} [packed]

htc_svcs = HTC_CTRL_RSVD_SVC, HTC_LOOPBACK_RSVD_SVC, WMI_CONTROL_SVC, WMI_BEACON_SVC, WMI_CAB_SVC, WMI_UAPSD_SVC, WMI_MGMT_SVC, WMI_DATA_VO_SVC, WMI_DATA_VI_SVC, WMI_DATA_BE_SVC, WMI_DATA_BE_SVC

htc_generic_frame {
	endpoint_id	int8[0:8]
	flags		flags[htc_frame_flags, int8]
	payload_len	len[payload, int16be]
	control		array[int8, 4]
	payload		array[int8, 0:256]
} [packed]

htc_frame_flags = HTC_FLAGS_RECV_TRAILER

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Assorted driver-specific descriptions of generic syz_* calls' variants.

# Generic calls such as syz_usb_connect() and syz_usb_control_io() should be enough
# (in theory) to emulate a proper device and finish driver probes without a hitch.
# However, there are cases when syzkaller fails to come up with correct inputs to achieve it.
# Use fixed descriptors to quickly pass through probe() to access select drivers' post-probe functionality.

# It is important to note that, one way or another, drivers in question require multiple control requests
# between a driver and a device processed during probe(). Descriptions below do not deal with specific
# CTRL requests as such (except for basic information included in vusb_responses_XXX). Instead, rely on
# seeds, created both manually and with syzkaller's help. For examples, see sys/linux/test/vusb_XXX.

# Common constants for endpoint descriptors.
define USB_ENDPOINT_BULK_ATTR	(USB_ENDPOINT_XFER_BULK)
define USB_ENDPOINT_INT_ATTR	(USB_ENDPOINT_XFER_INT)

define USB_FIXED_ENDPOINT_BULK_IN_ADDR	(1 | USB_DIR_IN)
define USB_FIXED_ENDPOINT_BULK_OUT_ADDR	(2)
define USB_FIXED_ENDPOINT_INT_IN_ADDR	(3 | USB_DIR_IN)

define USB_RECIP_DEVICE	0x00

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# rtl8150 driver specific descriptions.

resource fd_usb_rtl8150[fd_usb]

syz_usb_connect$rtl8150(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_rtl8150], conn_descs const[0]) fd_usb_rtl8150 (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$rtl8150(fd fd_usb_rtl8150, descs ptr[in, vusb_descriptors_rtl8150], resps ptr[in, vusb_responses_rtl8150]) (timeout[300], remote_cover)

usb_device_descriptor_rtl8150 {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0xbda, 0x8150, 0, array[usb_config_descriptor_rtl8150, 1]]
} [packed]

usb_config_descriptor_rtl8150 {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_rtl8150]
} [packed]

usb_interface_descriptor_rtl8150 {
	iface	usb_interface_descriptor_fixed_t[0, 0, 3, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_rtl8150]
} [packed]

usb_endpoint_descriptors_rtl8150 {
	bulk_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_IN_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	bulk_out	usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_OUT_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	int_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_INT_IN_ADDR, USB_ENDPOINT_INT_ATTR, 64, 1, void]
} [packed]

vusb_descriptors_rtl8150 {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_rtl8150 {
	len				len[parent, int32]
	generic				ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION	ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	RTL8150_REQ_GET_REGS		ptr[in, vusb_response_t[RTL8150_REQT_READ, RTL8150_REQ_GET_REGS, array[int8, 0:6]]]
	RTL8150_REQ_SET_REGS		ptr[in, vusb_response_t[RTL8150_REQT_WRITE, RTL8150_REQ_SET_REGS, array[int8, 0:6]]]
} [packed]

define RTL8150_REQ_GET_REGS	0x05
define RTL8150_REQ_SET_REGS	0x05
define RTL8150_REQT_READ	0xc0
define RTL8150_REQT_WRITE	0x40

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# sierra_net driver specific descriptions.

resource fd_usb_sierra_net[fd_usb]

syz_usb_connect$sierra_net(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_sierra_net], conn_descs const[0]) fd_usb_sierra_net (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$sierra_net(fd fd_usb_sierra_net, descs ptr[in, vusb_descriptors_sierra_net], resps ptr[in, vusb_responses_sierra_net]) (timeout[300], remote_cover)

usb_device_descriptor_sierra_net {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0x1199, 0x68a3, 0, array[usb_config_descriptor_sierra_net, 1]]
} [packed]

usb_config_descriptor_sierra_net {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_sierra_net]
} [packed]

usb_interface_descriptor_sierra_net {
	iface	usb_interface_descriptor_fixed_t[7, 0, 3, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_sierra_net]
} [packed]

# sierra_net driver does not expect fixed ep addresses, so refrain from being too specific here.
# As long as we ensure there are 3 endpoints, 2 bulk and 1 int, syzkaller should figure it out.
usb_endpoint_descriptors_sierra_net {
	bulk_in		usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], const[USB_ENDPOINT_BULK_ATTR, int8], void]
	bulk_out	usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], const[USB_ENDPOINT_BULK_ATTR, int8], void]
	status		usb_endpoint_descriptor_t[flags[usb_endpoint_addresses, int8], const[USB_ENDPOINT_INT_ATTR, int8], void]
} [packed]

vusb_descriptors_sierra_net {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_sierra_net {
	len					len[parent, int32]
	generic					ptr[in, vusb_response_generic]

	USB_CDC_GET_ENCAPSULATED_RESPONSE	ptr[in, vusb_response_t[SIERRA_CMD_TYPE_IN, USB_CDC_GET_ENCAPSULATED_RESPONSE, array[int8, 1024]]]
	USB_CDC_SEND_ENCAPSULATED_COMMANDT	ptr[in, vusb_response_t[SIERRA_CMD_TYPE_OUT, USB_CDC_SEND_ENCAPSULATED_COMMAND, array[int8, 0:4]]]
} [packed]

define SIERRA_CMD_TYPE_IN	(USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)
define SIERRA_CMD_TYPE_OUT	(USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# lan78xx driver specific descriptions.
# While these syz_* variants noticably help with the probe() process, they are not enough.
# This is due to a high number of control requests expected between the driver and the device.

include <drivers/net/usb/smsc95xx.h>

resource fd_usb_lan78xx[fd_usb]

syz_usb_connect$lan78xx(speed flags[usb_device_speed], dev_len len[dev], dev ptr[in, usb_device_descriptor_lan78xx], conn_descs const[0]) fd_usb_lan78xx (timeout[3000], prog_timeout[3000], remote_cover)
syz_usb_control_io$lan78xx(fd fd_usb_lan78xx, descs ptr[in, vusb_descriptors_lan78xx], resps ptr[in, vusb_responses_lan78xx]) (timeout[300], remote_cover)

usb_device_descriptor_lan78xx {
	inner	usb_device_descriptor_fixed_t[0x200, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff, 64, 0x424, 0x7850, 0, array[usb_config_descriptor_lan78xx, 1]]
} [packed]

usb_config_descriptor_lan78xx {
	inner	usb_config_descriptor_fixed_t[1, 1, USB_CONFIG_ATT_ONE, 250, usb_interface_descriptor_lan78xx]
} [packed]

usb_interface_descriptor_lan78xx {
	iface	usb_interface_descriptor_fixed_t[0, 0, 3, USB_CLASS_VENDOR_SPEC, 0, 0, void, usb_endpoint_descriptors_lan78xx]
} [packed]

usb_endpoint_descriptors_lan78xx {
	bulk_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_IN_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	bulk_out	usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_BULK_OUT_ADDR, USB_ENDPOINT_BULK_ATTR, 512, 0, void]
	int_in		usb_endpoint_descriptor_fixed_t[USB_FIXED_ENDPOINT_INT_IN_ADDR, USB_ENDPOINT_INT_ATTR, 64, 1, void]
} [packed]

vusb_descriptors_lan78xx {
	len		len[parent, int32]
	generic		ptr[in, vusb_descriptor_generic]

	USB_DT_STRING	ptr[in, vusb_descriptor_t[USB_TYPE_STANDARD, USB_DT_STRING, usb_string_descriptor]]
} [packed]

vusb_responses_lan78xx {
	len					len[parent, int32]
	generic					ptr[in, vusb_response_generic]

	USB_REQ_GET_INTERFACE			ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_INTERFACE, int8]]
	USB_REQ_GET_CONFIGURATION		ptr[in, vusb_response_t[USB_TYPE_STANDARD, USB_REQ_GET_CONFIGURATION, int8]]

	USB_VENDOR_REQUEST_READ_REGISTER	ptr[in, vusb_response_t[LAN78XX_REG_TYPE_IN, USB_VENDOR_REQUEST_READ_REGISTER, int32]]
	USB_VENDOR_REQUEST_WRITE_REGISTER	ptr[in, vusb_response_t[LAN78XX_REG_TYPE_OUT, USB_VENDOR_REQUEST_WRITE_REGISTER, int32]]
	USB_VENDOR_REQUEST_GET_STATS		ptr[in, vusb_response_t[LAN78XX_REG_TYPE_IN, USB_VENDOR_REQUEST_GET_STATS, array[int8, 47]]]
} [packed]

define LAN78XX_REG_TYPE_IN	(USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
define LAN78XX_REG_TYPE_OUT	(USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
]

471/2 2026/07/30 13:30 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 208833
							output: 253
							thoughts: 2092
						

Thoughts:
**USB Device Enumeration and Endpoint Communication Strategy**

Okay, so I'm looking at how to interact with a USB device in this fuzzing environment. The key function here is `syz_usb_connect`.  I initially thought I needed to deal with a `vusb_dev` structure, but it looks like `syz_usb_connect` actually takes a `usb_device_descriptor`. The problem is, this descriptor is strongly typed, and I need flexibility to craft custom descriptors, possibly with missing or differently sized endpoints.  The underlying implementation in `executor/common_usb.h` suggests I can bypass the type checker by using `ANY` and providing a raw byte blob for the descriptor.

To construct this, it looks like:

1.  `r0 = syz_usb_connect(3, AUTO, &AUTO=ANY=[@ANYBLOB="<descriptor_bytes>"], 0)`  is the correct approach.

However, the initial thought of using `syz_usb_control_io` to provide `ep_responses` is slightly misleading. `syz_usb_connect` itself needs this to enumerate.

Now, endpoint interaction seems to involve `syz_usb_ep_write`.  This is used to write data to a specific endpoint.  I've got the idea!

So the plan is:

1.  Connect the device with a custom descriptor using `syz_usb_connect`.  This should return a file descriptor (`fd_usb`).
2.  Write data to endpoint 0x84 using `syz_usb_ep_write` immediately after the device is connected.  Something like `syz_usb_ep_write(r0, 0x84, AUTO, &AUTO="0000aa55")`.
3. Then proceed to the subsequent device interaction (`i2c` in this case).

The critical part is the timing. It looks like `syz_usb_connect` does *not* block indefinitely waiting for the probe to complete.  It returns immediately after the device is configured, and the driver's `probe` function is then run, possibly concurrently.  This means I *can* call `syz_usb_ep_write` sequentially. So no need for `async` to avoid deadlock, it's a synchronous operation to interact after device configuration!



472/2 2026/07/30 13:31 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, AUTO, &AUTO=ANY=[@ANYBLOB="12010002000000403b0904a10100000000010902200001010080000904000002ff00ff000705840340000107058802400000"], 0)
syz_usb_ep_write(r0, 0x84, AUTO, &AUTO="0000aa55")
r1 = syz_open_dev$i2c(&AUTO='/dev/i2c-#\x00', 0, 0)
ioctl$I2C_SMBUS(r1, 0x720, &AUTO={0, 0, 0, &AUTO=""})
 Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

473/2 2026/07/30 13:31 llm crash-repro-finder-compressor
0m Model:
gemini-3.5-flash

Reply:
### 1. Approaches Tried and Results

*   **Direct Device Opening**:
    *   Attempted opening `/dev/video0` and `/dev/i2c-0` directly using `syz_open_dev$video` and `syz_open_dev$I2C`.
    *   *Result*: Failed with syntax errors; syzkaller requires exact template strings like `"/dev/i2c-#\x00"`.
*   **Generic HID Emulation**:
    *   Used `syz_usb_connect$hid` to connect generic HID device.
    *   *Result*: Target drivers (`si4713`, `au0828`, `go7007`) did not bind because syzkaller patches vendor/product IDs to match generic HID drivers.
*   **Custom USB Descriptor Construction via Structs**:
    *   Attempted constructing custom `usb_device_descriptor` for `syz_usb_connect` to emulate `si4713` (Vendor `0x10c4`, Product `0x8244`, Class `USB_CLASS_HID`).
    *   *Result*: Failed due to syntax constraints (e.g., `AUTO` cannot be used for `FlagsType` or `ArrayType` fields, `void` fields must be `""`, and `bInterfaceClass` is hardcoded to `0` in generic definitions).
*   **USB Emulation via Raw `ANY` Blobs**:
    *   Passed raw byte array for device descriptor using `&AUTO=ANY=[@ANYBLOB="..."]`.
    *   *Result*: Succeeded in bypassing struct constraints and forcing specific vendor/product IDs.
*   **Target Driver Investigation**:
    *   **`si4713`**: Requires complex control message handshakes during `si4713_send_startup_command`. Handshake failure causes probe to fail before `si4713_register_i2c_adapter` is called. Dead-end.
    *   **`au0828`**: Checked `au0828_usb_disconnect` early-return bug. However, `au0828_usb_release` correctly calls `au0828_i2c_unregister` which calls `i2c_del_adapter`. Safe.
    *   **`go7007`**: Confirmed buggy. `go7007_usb_probe` registers `i2c_adapter` via `i2c_add_adapter`. If probe fails later (e.g., due to missing `ep_in[6]`), it jumps to `allocfail`, calls `go7007_usb_release(go)` and `kfree(go)` without calling `i2c_del_adapter`.

### 2. Current Hypotheses & Active Lines of Investigation

*   **`go7007` I2C Adapter Leak & UAF**:
    *   `go7007_usb_probe` registers `i2c_adapter` embedded in `struct go7007`.
    *   If probe fails after registration, `go` is freed but `i2c_adapter` remains registered in `i2c_adapter_idr`.
    *   The freed memory block is reallocated (e.g., as `sk_buff` data) and then freed again.
    *   Userspace opens `/dev/i2c-X`, causing `i2c_get_adapter` to retrieve the dangling pointer from `i2c_adapter_idr`.
    *   Userspace calls `ioctl$I2C_SMBUS`, invoking `i2c_adapter_lock_bus` -> `i2c_adapter_depth`, which dereferences `adapter->dev.parent` (offset 264/368 depending on lockdep/debug configs) of the freed block, triggering the KASAN UAF.
*   **Triggering Probe Failure**:
    *   Emulate `GO7007_BOARDID_PX_TV402U` (Vendor `0x093b`, Product `0xa104`, `bcdDevice = 0x0001`).
    *   Provide endpoints `0x84` (Interrupt IN) and `0x88` (Bulk IN), but omit `ep_in[6]` (Bulk IN for video).
    *   Provide a USB response for interrupt endpoint `0x84` returning `00 00 aa 55` to satisfy `go7007_read_interrupt` during `go7007_boot_encoder`.
    *   This allows `i2c_add_adapter` to succeed, but forces probe to fail at `if (!usb->usbdev->ep_in[6]) goto allocfail;`, triggering the leak.

### 3. Critical Code and Configuration Values

*   **`go7007_usb_probe` Error Path (`drivers/media/usb/go7007/go7007-usb.c`)**:
    ```c
    allocfail:
    	go7007_usb_release(go);
    	kfree(go);
    	return -ENOMEM;
    ```
*   **`go7007_usb_release` (`drivers/media/usb/go7007/go7007-usb.c`)**:
    ```c
    static void go7007_usb_release(struct go7007 *go)
    {
    	struct go7007_usb *usb = go->hpi_context;
    	struct urb *vurb, *aurb;
    	int i;

    	if (usb->intr_urb) {
    		usb_kill_urb(usb->intr_urb);
    		kfree(usb->intr_urb->transfer_buffer);
    		usb_free_urb(usb->intr_urb);
    	}

    	/* Free USB-related structs */
    	for (i = 0; i < 8; ++i) {
    		vurb = usb->video_urbs[i];
    		if (vurb) {
    			usb_kill_urb(vurb);
    			kfree(vurb->transfer_buffer);
    			usb_free_urb(vurb);
    		}
    		aurb = usb->audio_urbs[i];
    		if (aurb) {
    			usb_kill_urb(aurb);
    			kfree(aurb->transfer_buffer);
    			usb_free_urb(aurb);
    		}
    	}

    	kfree(go->hpi_context);
    }
    ```
*   **Syzkaller Reproducer**:
    ```
    r0 = syz_usb_connect(3, AUTO, &AUTO=@generic={0, &AUTO="12010002000000403b0904a10100000000010902200001010080000904000002ff00ff000705840340000107058802400000", 0, 0, &AUTO=[{0x84, &AUTO="0000aa55"}]}, 0)
    r1 = syz_open_dev$i2c(&AUTO='/dev/i2c-#\x00', 0, 0)
    ioctl$I2C_SMBUS(r1, 0x720, &AUTO={0, 0, 0, &AUTO=""})
    ```

### 4. Potential Reasoning Loops & Repetitive Tool Calls

*   **`sk_buff` Allocation Trace**: Do not assume the bug is in `netdevsim` or network subsystem because of the `sk_buff` allocation/free trace. KASAN reports the last owner of the physical page; the memory was simply reallocated as `sk_buff` data after `go7007` freed it, and then freed again before the dangling pointer was accessed.
*   **`struct go7007` Size**: Do not assume `sizeof(struct go7007)` is always > 4096 bytes. Without debug options (like lockdep, spinlock debugging, media controller), the struct size is ~3988 bytes, which fits in `kmalloc-4k` and matches the KASAN report.

Tokens:
							input: 232289
							output: 1948
							thoughts: 2877
						

474/2 2026/07/30 13:32 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 23657
							output: 22
							thoughts: 34
						

Thoughts:
Okay, here's my interpretation of those thoughts, tailored for an expert audience:

**Debugging Device Driver Naming Conventions**

Right, that `syz_open_dev$i2c` name... something doesn't feel quite right about it. I need to verify that it aligns with the expected naming conventions for i2c device interactions. Let me double-check the authoritative source on this – the `dev_i2c.txt` file. I'm hoping that will offer the definitive answer regarding the proper format and potentially expose a simple typo, or suggest a more appropriate and consistent naming convention for this particular interaction. It's crucial to ensure our tooling, and the fuzzing process itself, is leveraging the right identifiers, or we're just chasing shadows.



475/2 2026/07/30 13:32 tool read-description
0m Args:
map[File:dev_i2c.txt]

Results:
map[Output:# Copyright 2018 syzkaller project authors. All rights reserved.
# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

include <uapi/linux/i2c-dev.h>
include <uapi/linux/i2c.h>

define I2C_MAX_BLOCK_1	(I2C_SMBUS_BLOCK_MAX + 1)
define I2C_MAX_BLOCK_2	(I2C_SMBUS_BLOCK_MAX + 2)

resource fd_i2c[fd]

syz_open_dev$I2C(dev ptr[in, string["/dev/i2c-#"]], id intptr, flags flags[open_flags]) fd_i2c

ioctl$I2C_RETRIES(fd fd_i2c, cmd const[I2C_RETRIES], arg intptr)
ioctl$I2C_TIMEOUT(fd fd_i2c, cmd const[I2C_TIMEOUT], arg intptr)
ioctl$I2C_SLAVE(fd fd_i2c, cmd const[I2C_SLAVE], arg intptr[0:0x3ff])
ioctl$I2C_SLAVE_FORCE(fd fd_i2c, cmd const[I2C_SLAVE_FORCE], arg intptr[0:0x3ff])
ioctl$I2C_TENBIT(fd fd_i2c, cmd const[I2C_TENBIT], arg boolptr)
ioctl$I2C_PEC(fd fd_i2c, cmd const[I2C_PEC], arg intptr)

ioctl$I2C_FUNCS(fd fd_i2c, cmd const[I2C_FUNCS], arg ptr[in, intptr])
ioctl$I2C_RDWR(fd fd_i2c, cmd const[I2C_RDWR], arg ptr[in, i2c_rdwr_ioctl_data])
ioctl$I2C_SMBUS(fd fd_i2c, cmd const[I2C_SMBUS], arg ptr[in, i2c_smbus_ioctl_data])

i2c_smbus_ioctl_data {
	read_write	bool8
	command		int8
	size		int32[I2C_SMBUS_QUICK:I2C_SMBUS_I2C_BLOCK_DATA]
	data		ptr[in, i2c_smbus_data]
}

i2c_smbus_data {
	size	int8[0:I2C_MAX_BLOCK_2]
	block	array[int8, I2C_MAX_BLOCK_1]
}

i2c_rdwr_ioctl_data {
	msgs	ptr[in, array[i2c_msg]]
	nmsgs	len[msgs, int32]
}

i2c_msg {
	addr	int16
	flags	flags[i2c_msg_flags, int16]
	len	len[buf, int16]
	buf	ptr[in, array[int8]]
}

i2c_msg_flags = I2C_M_RD, I2C_M_TEN, I2C_M_DMA_SAFE, I2C_M_RECV_LEN, I2C_M_NO_RD_ACK, I2C_M_IGNORE_NAK, I2C_M_REV_DIR_ADDR, I2C_M_NOSTART, I2C_M_STOP
]

476/2 2026/07/30 13:32 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 24715
							output: 253
							thoughts: 15
						

Thoughts:
Okay, here's my interpretation of that thought as if it were my own, assuming I'm an expert:

**Identifying the Syzkaller Primitive**

Alright, the initial piece of the puzzle is clear: `syz_open_dev$I2C`. That's the key. This immediately tells me we're dealing with a syzkaller syscall wrapper, specifically targeting the `open()` system call, but specialized for an I2C device. Knowing this narrows down the scope considerably. We're not just looking at a generic `open()` issue, but something related to I2C device access. My focus needs to be on the interactions, configurations, or data passed *specifically* when opening an I2C device through this syzkaller-generated function. This informs my search terms and what I need to look for, to see if there is something specific to open I2C device that may be a problem. My investigation will be guided by my understanding of I2C device interaction at the kernel level, keeping in mind the typical structures and data exchanged during an `open()` call in this context.



477/2 2026/07/30 13:32 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, AUTO, &AUTO=ANY=[@ANYBLOB="12010002000000403b0904a10100000000010902200001010080000904000002ff00ff000705840340000107058802400000"], 0)
syz_usb_ep_write(r0, 0x84, AUTO, &AUTO="0000aa55")
r1 = syz_open_dev$I2C(&AUTO='/dev/i2c-#\x00', 0, 0)
ioctl$I2C_SMBUS(r1, 0x720, &AUTO={0, 0, 0, &AUTO=""})
 Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

478/2 2026/07/30 13:32 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 25282
							output: 256
							thoughts: 85
						

Thoughts:
Okay, here's my interpretation of that thought process, tailored for an expert audience:

**Analyzing the I2C SMBus Data Structure**

Right, so I'm looking at this `i2c_smbus_data` structure. It's crucial to remember that it *is* a structure, a data container, and not some character string as I might've initially glossed over. I've got to unpack it properly.

Looking at the definition, it's pretty standard for SMBus transfers. We have a `size` field, which I'm inferring is an 8-bit integer array. The array ranges from 0 up to `I2C_MAX_BLOCK_2`, which probably sets an upper limit on the size of the block data. Then, and this is the core of the data payload, there is `block` which is an array of `int8` with a size given by `I2C_MAX_BLOCK_1`.

With this understanding, if I'm thinking about how to initialize it in a way that represents an "automatic" or default state, then `&AUTO={0, []}` becomes the obvious choice. I can set the `size` to 0, which likely indicates an empty block, and initialize the `block` array with an empty array.



479/2 2026/07/30 13:32 tool reproduce-crash
0m Error:
log-in to see details

Args:
map[ReproSyz:r0 = syz_usb_connect(3, AUTO, &AUTO=ANY=[@ANYBLOB="12010002000000403b0904a10100000000010902200001010080000904000002ff00ff000705840340000107058802400000"], 0)
syz_usb_ep_write(r0, 0x84, AUTO, &AUTO="0000aa55")
r1 = syz_open_dev$I2C(&AUTO='/dev/i2c-#\x00', 0, 0)
ioctl$I2C_SMBUS(r1, 0x720, &AUTO={0, 0, 0, &AUTO={0, []}})
 Sandbox:none]

Results:
map[ExecutionCachedID: ReproducedBugTitle: ReproducedCrashReport:]

480/2 2026/07/30 13:32 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 25978
							output: 252
							thoughts: 203
						

Thoughts:
**Reasoning Through I2C SMBus Data Structure Initialization**

Okay, so I'm looking at this `array[int8, I2C_MAX_BLOCK_1]`. Right, that's a fixed-size array within a struct. I remember, `I2C_MAX_BLOCK_1` is derived from `I2C_SMBUS_BLOCK_MAX + 1`, and that max value is 32, so this array holds 33 `int8` elements. Got it.

Now, the question is how to initialize this. I could either use `AUTO` for the entire struct, which *should* handle the nested array correctly, or I could explicitly provide all 33 zeroes. Hmmm, the zero initialization approach seems a bit clunky.

Maybe I can use `&AUTO={0, [0]}`. Wait, a fixed-size array within a struct will need all elements or `AUTO`?

But, wait a minute... If I use `&AUTO` *for the pointer* to `i2c_smbus_data`, then syzkaller will automatically generate the appropriate values, right? That seems cleaner and simpler. So, let's go with that. The final call should then look like this:

```
ioctl$I2C_SMBUS(r1, 0x720, &AUTO={0, 0, 0, &AUTO})
```

That should work. Using `&AUTO` for the pointer to the `i2c_smbus_data` and let syzkaller figure it out.



481/2 2026/07/30 13:32 tool reproduce-crash
2m Args:
map[ReproSyz:r0 = syz_usb_connect(3, AUTO, &AUTO=ANY=[@ANYBLOB="12010002000000403b0904a10100000000010902200001010080000904000002ff00ff000705840340000107058802400000"], 0)
syz_usb_ep_write(r0, 0x84, AUTO, &AUTO="0000aa55")
r1 = syz_open_dev$I2C(&AUTO='/dev/i2c-#\x00', 0, 0)
ioctl$I2C_SMBUS(r1, 0x720, &AUTO={0, 0, 0, &AUTO})
 Sandbox:none]

Results:
map[ExecutionCachedID:repro/d8ccde7fb7ff9cebb915310c53ed585bd30b0654 ReproducedBugTitle: ReproducedCrashReport:]

482/2 2026/07/30 13:34 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 26843
							output: 83
							thoughts: 54
						

Thoughts:
Okay, here's my take on those thoughts, framed as my own:

**Initial Assessment and Targeted Verification**

Well, that's a relief, it didn't crash. My immediate thought is to zero in on what *did* happen, or rather, *didn't* happen. Let's dig into that `go7007-usb.c` file and, specifically, I need to verify a couple of key points. First, was `go7007_usb_probe` even invoked? If it wasn't called, then the problem lies upstream, and I am looking in the wrong place. Assuming it *was* called, I need to confirm whether the function reached `ep_in[6]`. If `ep_in[6]` has been hit, then it's a very targeted problem, and I'll know where to start looking.



483/2 2026/07/30 13:34 tool get-file-coverage
0m Error:
log-in to see details

Args:
map[ExecutionCachedID:repro/d8ccde7fb7ff9cebb915310c53ed585bd30b0654 Filename:drivers/media/usb/go7007/go7007-usb.c Functions:[]]

Results:
map[CoveredFunctions:<nil> Snippets:<nil>]

484/2 2026/07/30 13:34 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 27211
							output: 56
							thoughts: 82
						

Thoughts:
**Missing Piece: The go7007-usb.c Module**

Hold on a second, I don't recall seeing anything specific about `go7007-usb.c` in the material! That seems like a pretty significant oversight. Why did that get skipped? I need to understand this. Okay, let's see... the vendor ID is `0x093b` and the product ID is `0xa104`. Right, right. Time to dive into the code. I'll need to check the `go7007_usb_id_table` within `drivers/media/usb/go7007/go7007-usb.c`. That's where the relevant device identifiers should be. Let's see what's in there.



485/2 2026/07/30 13:35 tool codesearch-definition-source
0m Args:
map[ContextFile:drivers/media/usb/go7007/go7007-usb.c Name:go7007_usb_id_table]

Results:
map[SourceCode: 506:	static const struct usb_device_id go7007_usb_id_table[] = {
 507:		{
 508:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
 509:						USB_DEVICE_ID_MATCH_INT_INFO,
 510:			.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
 511:			.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
 512:			.bcdDevice_lo	= 0x200,   /* Revision number of XMen */
 513:			.bcdDevice_hi	= 0x200,
 514:			.bInterfaceClass	= 255,
 515:			.bInterfaceSubClass	= 0,
 516:			.bInterfaceProtocol	= 255,
 517:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_XMEN,
 518:		},
 519:		{
 520:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
 521:			.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
 522:			.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
 523:			.bcdDevice_lo	= 0x202,   /* Revision number of Matrix II */
 524:			.bcdDevice_hi	= 0x202,
 525:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_MATRIX_II,
 526:		},
 527:		{
 528:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
 529:			.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
 530:			.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
 531:			.bcdDevice_lo	= 0x204,   /* Revision number of Matrix */
 532:			.bcdDevice_hi	= 0x204,   /*     Reloaded */
 533:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_MATRIX_RELOAD,
 534:		},
 535:		{
 536:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
 537:						USB_DEVICE_ID_MATCH_INT_INFO,
 538:			.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
 539:			.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
 540:			.bcdDevice_lo	= 0x205,   /* Revision number of XMen-II */
 541:			.bcdDevice_hi	= 0x205,
 542:			.bInterfaceClass	= 255,
 543:			.bInterfaceSubClass	= 0,
 544:			.bInterfaceProtocol	= 255,
 545:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_XMEN_II,
 546:		},
 547:		{
 548:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
 549:			.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
 550:			.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
 551:			.bcdDevice_lo	= 0x208,   /* Revision number of Star Trek */
 552:			.bcdDevice_hi	= 0x208,
 553:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_STAR_TREK,
 554:		},
 555:		{
 556:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
 557:						USB_DEVICE_ID_MATCH_INT_INFO,
 558:			.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
 559:			.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
 560:			.bcdDevice_lo	= 0x209,   /* Revision number of XMen-III */
 561:			.bcdDevice_hi	= 0x209,
 562:			.bInterfaceClass	= 255,
 563:			.bInterfaceSubClass	= 0,
 564:			.bInterfaceProtocol	= 255,
 565:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_XMEN_III,
 566:		},
 567:		{
 568:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
 569:			.idVendor	= 0x0eb1,  /* Vendor ID of WIS Technologies */
 570:			.idProduct	= 0x7007,  /* Product ID of GO7007SB chip */
 571:			.bcdDevice_lo	= 0x210,   /* Revision number of Matrix */
 572:			.bcdDevice_hi	= 0x210,   /*     Revolution */
 573:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_MATRIX_REV,
 574:		},
 575:		{
 576:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
 577:			.idVendor	= 0x093b,  /* Vendor ID of Plextor */
 578:			.idProduct	= 0xa102,  /* Product ID of M402U */
 579:			.bcdDevice_lo	= 0x1,	   /* revision number of Blueberry */
 580:			.bcdDevice_hi	= 0x1,
 581:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_PX_M402U,
 582:		},
 583:		{
 584:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
 585:			.idVendor	= 0x093b,  /* Vendor ID of Plextor */
 586:			.idProduct	= 0xa104,  /* Product ID of TV402U */
 587:			.bcdDevice_lo	= 0x1,
 588:			.bcdDevice_hi	= 0x1,
 589:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_PX_TV402U,
 590:		},
 591:		{
 592:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
 593:			.idVendor	= 0x10fd,  /* Vendor ID of Anubis Electronics */
 594:			.idProduct	= 0xde00,  /* Product ID of Lifeview LR192 */
 595:			.bcdDevice_lo	= 0x1,
 596:			.bcdDevice_hi	= 0x1,
 597:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_LIFEVIEW_LR192,
 598:		},
 599:		{
 600:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
 601:			.idVendor	= 0x1943,  /* Vendor ID Sensoray */
 602:			.idProduct	= 0x2250,  /* Product ID of 2250/2251 */
 603:			.bcdDevice_lo	= 0x1,
 604:			.bcdDevice_hi	= 0x1,
 605:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_SENSORAY_2250,
 606:		},
 607:		{
 608:			.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
 609:			.idVendor	= 0x06e1,  /* Vendor ID of ADS Technologies */
 610:			.idProduct	= 0x0709,  /* Product ID of DVD Xpress DX2 */
 611:			.bcdDevice_lo	= 0x204,
 612:			.bcdDevice_hi	= 0x204,
 613:			.driver_info	= (kernel_ulong_t)GO7007_BOARDID_ADS_USBAV_709,
 614:		},
 615:		{ }					/* Terminating entry */
 616:	};
 SourceFile:drivers/media/usb/go7007/go7007-usb.c]

486/2 2026/07/30 13:35 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 30059
							output: 23
							thoughts: 788
						

Thoughts:
**USB Device Descriptor Deep Dive**

Okay, let's see... I've got a device with vendor ID `0x093b`, product ID `0xa104`, and `bcdDevice = 0x1`. Now, let's dig into the descriptor data. Analyzing this byte stream, I can see the standard device descriptor layout:

`12` (bLength)
`01` (bDescriptorType)
`00 02` (bcdUSB)
`00` (bDeviceClass)
`00` (bDeviceSubClass)
`00` (bDeviceProtocol)
`40` (bMaxPacketSize0)
`3b 09` (idVendor = 0x093b)
`04 a1` (idProduct = 0xa104)
`01 00` (bcdDevice = 0x0001)
`00` (iManufacturer)
`00` (iProduct)
`00` (iSerialNumber)
`01` (bNumConfigurations)

Next, the configuration descriptor is:

`09 02 20 00 01 01 00 80 00`

Which breaks down as:

`09` (bLength)
`02` (bDescriptorType)
`20 00` (wTotalLength = 32)
`01` (bNumInterfaces)
`01` (bConfigurationValue)
`00` (iConfiguration)
`80` (bmAttributes)
`00` (bMaxPower)

Then the interface descriptor:

`09 04 00 00 02 ff 00 ff 00`

`09` (bLength)
`04` (bDescriptorType)
`00` (bInterfaceNumber)
`00` (bAlternateSetting)
`02` (bNumEndpoints)
`ff` (bInterfaceClass)
`00` (bInterfaceSubClass)
`ff` (bInterfaceProtocol)
`00` (iInterface)

And finally, the endpoint descriptors:

Endpoint 1: `07 05 84 03 40 00 01` - Interrupt endpoint.

Endpoint 2: `07 05 88 02 40 00 00` - Bulk endpoint.

Now, let's verify the `wTotalLength`. 9 (config) + 9 (interface) + 7 (ep1) + 7 (ep2) = 32. Yep, that checks out perfectly. The descriptors appear well-formed and consistent. So, why isn't this device working as expected? Perhaps, the `go7007-usb` module isn't compiled into the kernel? That's the next logical step. I'll need to check the kernel configuration to be sure.



487/2 2026/07/30 13:35 tool grepper
0m Args:
map[Expression:CONFIG_VIDEO_GO7007]

Results:
map[Output:drivers/media/usb/Makefile=27=obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
drivers/media/usb/Makefile:28:obj-$(CONFIG_VIDEO_GO7007) += go7007/
drivers/media/usb/Makefile-29-obj-$(CONFIG_VIDEO_HDPVR) += hdpvr/
--
drivers/media/usb/go7007/Makefile-1-# SPDX-License-Identifier: GPL-2.0
drivers/media/usb/go7007/Makefile:2:obj-$(CONFIG_VIDEO_GO7007) += go7007.o
drivers/media/usb/go7007/Makefile:3:obj-$(CONFIG_VIDEO_GO7007_USB) += go7007-usb.o
drivers/media/usb/go7007/Makefile:4:obj-$(CONFIG_VIDEO_GO7007_LOADER) += go7007-loader.o
drivers/media/usb/go7007/Makefile:5:obj-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD) += s2250.o
drivers/media/usb/go7007/Makefile-6-
--
drivers/media/usb/go7007/Makefile=10=s2250-y := s2250-board.o
drivers/media/usb/go7007/Makefile-11-
drivers/media/usb/go7007/Makefile:12:ccflags-$(CONFIG_VIDEO_GO7007_LOADER:m=y) += -I $(srctree)/drivers/media/common
]

488/2 2026/07/30 13:35 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 31970
							output: 23
							thoughts: 110
						

Thoughts:
**Kernel Configuration Deep Dive**

Okay, so I need to figure out if `CONFIG_VIDEO_GO7007` is enabled in the syzkaller kernel config. Hmm, I can't just directly inspect the config file, can I? No, of course not. What's the workaround? Ah, right, I can check the `get-coverage-files` output from *any* of the syzkaller runs. If `go7007` appears in that list, I know it's compiled.

Shoot, the last run didn't show it. So, is it even *compiled*? That's the key question now. I need to confirm if the kernel even *contains* `go7007`. Let me check if `go7007_usb_probe` is present. That should give me a definitive answer on whether the driver is built in or as a module.



489/2 2026/07/30 13:35 tool grepper
0m Args:
map[Expression:go7007_usb_probe]

Results:
map[Output:drivers/media/usb/go7007/go7007-usb.c=1032=static struct i2c_adapter go7007_usb_adap_templ = {
--
drivers/media/usb/go7007/go7007-usb.c-1039-
drivers/media/usb/go7007/go7007-usb.c:1040:static int go7007_usb_probe(struct usb_interface *intf,
drivers/media/usb/go7007/go7007-usb.c-1041-		const struct usb_device_id *id)
--
drivers/media/usb/go7007/go7007-usb.c=1347=static struct usb_driver go7007_usb_driver = {
drivers/media/usb/go7007/go7007-usb.c-1348-	.name		= "go7007",
drivers/media/usb/go7007/go7007-usb.c:1349:	.probe		= go7007_usb_probe,
drivers/media/usb/go7007/go7007-usb.c-1350-	.disconnect	= go7007_usb_disconnect,
]

490/2 2026/07/30 13:35 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 32649
							output: 21
							thoughts: 1964
						

Thoughts:
**Analyzing a Slab-Use-After-Free Bug: A Deep Dive**

Okay, let's break this down. My initial hunch was that the `go7007` driver, which I was examining because of its USB interface interaction, might be responsible. First, I wanted to determine if it was even compiled into the kernel. If `CONFIG_VIDEO_GO7007` isn't set, it won't be, and then it can't be the culprit. I initially thought to check the `kallsyms` table, but then realized I could use tools like `codesearch-find-references` or `git-log` (though that's for source, not compiled binaries). I created a syz program to trigger the driver and check coverage, but it returned no coverage. Was that because it wasn't compiled, or merely wasn't reached?

I considered that `syz_usb_connect` should trigger `usb_probe_interface`, which iterates drivers, and therefore if `go7007` was registered, it should be called. Then I went to check `go7007_usb_id_table` to make sure the interface was a match, but my device descriptor had `bInterfaceClass = 255`, where the `go7007_usb_id_table` has a different match. So it should have matched and been called, and it wasn't. I added a wait to the syz program but it didn't crash, so perhaps it wasn't the driver.

Okay, let's rethink. I'm dealing with a `KASAN: slab-use-after-free in i2c_adapter_lock_bus` error. The adapter was allocated by `nsim_dev_trap_skb_build`. The KASAN report details this allocation and subsequent free within `nsim_dev_trap_report_work`. It's a 4096-byte allocation (kmalloc-4k). I then noted that the buggy address is within the 4096-byte region (264 bytes in). This suggests the `i2c_adapter` might have been *embedded* in a struct, which was then freed, and *that* memory reallocated for an `sk_buff`! If so, it would have been freed after being allocated for the sk_buff!

Crucially, the KASAN report only shows the *last* allocation and free of the *physical page*. So, either the `i2c_adapter` was allocated and freed before the `sk_buff` allocation, or after. It's the former: if the `i2c_adapter` was freed, *then* the page reused as `sk_buff` data, *and* then freed again, KASAN reports that last bit. This perfectly aligns with my hypothesis: the `i2c_adapter` memory was leaked, freed, and subsequently reused.

The allocation/free are in the same task, and from the same call stack. The allocation is `nsim_dev_trap_skb_build`, and the free is `nsim_dev_trap_report_work`. This is an skb structure that contains the slab for the i2c adapter.

This means the `i2c_adapter` must have been allocated *before*, and was not allocated or freed within `nsim_dev_trap_skb_build`. This narrows it down considerably. Which driver registered and then freed the `i2c_adapter` without unregistering it? My memory of `go7007_usb_probe` makes me think of other drivers, which adds to my concern about the i2c adapter.

Let's search the kernel code for `i2c_add_adapter` or `i2c_bit_add_bus`, checking for error paths that might free without calling `i2c_del_adapter`. That's where I need to focus my investigation.



491/2 2026/07/30 13:35 tool grepper
0m Args:
map[Expression:i2c_add_adapter]

Results:
map[Output:
Full output is too long, showing 500 out of 1138 lines.
Use more precise expression if possible.

Documentation/driver-api/driver-model/devres.rst=280=I2C
Documentation/driver-api/driver-model/devres.rst:281:  devm_i2c_add_adapter()
Documentation/driver-api/driver-model/devres.rst-282-  devm_i2c_new_dummy_device()
--
drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c=160=struct amdgpu_i2c_chan *amdgpu_i2c_create(struct drm_device *dev,
--
drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c-186-		i2c->adapter.algo = &amdgpu_atombios_i2c_algo;
drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c:187:		ret = devm_i2c_add_adapter(dev->dev, &i2c->adapter);
drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c-188-		if (ret)
--
drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c=727=int smu_v11_0_i2c_control_init(struct amdgpu_device *adev)
--
drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c-747-
drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c:748:	res = devm_i2c_add_adapter(adev->dev, control);
drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c-749-	if (res)
--
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c=3230=static int dm_oem_i2c_hw_init(struct amdgpu_device *adev)
--
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c-3244-
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c:3245:		r = devm_i2c_add_adapter(adev->dev, &oem_i2c->base);
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c-3246-		if (r) {
--
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c=9543=static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
--
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c-9564-	aconnector->i2c = i2c;
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c:9565:	res = devm_i2c_add_adapter(dm->adev->dev, &i2c->base);
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c-9566-
--
drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c=1666=static int arcturus_i2c_control_init(struct smu_context *smu)
--
drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c-1685-
drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c:1686:		res = devm_i2c_add_adapter(adev->dev, control);
drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c-1687-		if (res) {
--
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c=2881=static int navi10_i2c_control_init(struct smu_context *smu)
--
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c-2900-
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c:2901:		res = devm_i2c_add_adapter(adev->dev, control);
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c-2902-		if (res) {
--
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c=2591=static int sienna_cichlid_i2c_control_init(struct smu_context *smu)
--
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c-2610-
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c:2611:		res = devm_i2c_add_adapter(adev->dev, control);
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c-2612-		if (res) {
--
drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c=1507=static int aldebaran_i2c_control_init(struct smu_context *smu)
--
drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c-1523-
drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c:1524:	res = devm_i2c_add_adapter(adev->dev, control);
drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c-1525-	if (res) {
--
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c=2764=static int smu_v13_0_0_i2c_control_init(struct smu_context *smu)
--
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c-2782-
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c:2783:		res = devm_i2c_add_adapter(adev->dev, control);
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c-2784-		if (res) {
--
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c=2526=static int smu_v13_0_6_i2c_control_init(struct smu_context *smu)
--
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c-2544-
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c:2545:		res = devm_i2c_add_adapter(adev->dev, control);
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c-2546-		if (res) {
--
drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c=1996=static int smu_v14_0_2_i2c_control_init(struct smu_context *smu)
--
drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c-2014-
drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c:2015:		res = devm_i2c_add_adapter(adev->dev, control);
drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c-2016-		if (res) {
--
drivers/gpu/drm/bridge/inno-hdmi.c=1030=static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
--
drivers/gpu/drm/bridge/inno-hdmi.c-1050-
drivers/gpu/drm/bridge/inno-hdmi.c:1051:	ret = devm_i2c_add_adapter(hdmi->dev, adap);
drivers/gpu/drm/bridge/inno-hdmi.c-1052-	if (ret) {
--
drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c=716=static struct i2c_adapter *dw_hdmi_qp_i2c_adapter(struct dw_hdmi_qp *hdmi)
--
drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c-736-
drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c:737:	ret = devm_i2c_add_adapter(hdmi->dev, adap);
drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c-738-	if (ret) {
--
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c=509=static struct i2c_adapter *dw_hdmi_i2c_adapter(struct dw_hdmi *hdmi)
--
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c-528-
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c:529:	ret = i2c_add_adapter(adap);
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c-530-	if (ret) {
--
drivers/gpu/drm/display/drm_dp_helper.c=2398=int drm_dp_aux_register(struct drm_dp_aux *aux)
--
drivers/gpu/drm/display/drm_dp_helper.c-2416-
drivers/gpu/drm/display/drm_dp_helper.c:2417:	ret = i2c_add_adapter(&aux->ddc);
drivers/gpu/drm/display/drm_dp_helper.c-2418-	if (ret) {
--
drivers/gpu/drm/display/drm_dp_mst_topology.c=5982=static int drm_dp_mst_register_i2c_bus(struct drm_dp_mst_port *port)
--
drivers/gpu/drm/display/drm_dp_mst_topology.c-5998-
drivers/gpu/drm/display/drm_dp_mst_topology.c:5999:	return i2c_add_adapter(&aux->ddc);
drivers/gpu/drm/display/drm_dp_mst_topology.c-6000-}
--
drivers/gpu/drm/gma500/cdv_intel_dp.c=223=i2c_dp_aux_add_bus(struct i2c_adapter *adapter)
--
drivers/gpu/drm/gma500/cdv_intel_dp.c-229-		return error;
drivers/gpu/drm/gma500/cdv_intel_dp.c:230:	error = i2c_add_adapter(adapter);
drivers/gpu/drm/gma500/cdv_intel_dp.c-231-	return error;
--
drivers/gpu/drm/gma500/intel_gmbus.c=387=int gma_intel_setup_gmbus(struct drm_device *dev)
--
drivers/gpu/drm/gma500/intel_gmbus.c-423-		bus->adapter.algo = &gmbus_algorithm;
drivers/gpu/drm/gma500/intel_gmbus.c:424:		ret = i2c_add_adapter(&bus->adapter);
drivers/gpu/drm/gma500/intel_gmbus.c-425-		if (ret)
--
drivers/gpu/drm/gma500/psb_intel_sdvo.c=2426=psb_intel_sdvo_init_ddc_proxy(struct psb_intel_sdvo *sdvo,
--
drivers/gpu/drm/gma500/psb_intel_sdvo.c-2434-
drivers/gpu/drm/gma500/psb_intel_sdvo.c:2435:	return i2c_add_adapter(&sdvo->ddc) == 0;
drivers/gpu/drm/gma500/psb_intel_sdvo.c-2436-}
--
drivers/gpu/drm/i915/display/intel_gmbus.c=903=int intel_gmbus_setup(struct intel_display *display)
--
drivers/gpu/drm/i915/display/intel_gmbus.c-960-
drivers/gpu/drm/i915/display/intel_gmbus.c:961:		ret = i2c_add_adapter(&bus->adapter);
drivers/gpu/drm/i915/display/intel_gmbus.c-962-		if (ret) {
--
drivers/gpu/drm/i915/display/intel_sdvo.c=3350=intel_sdvo_init_ddc_proxy(struct intel_sdvo_ddc *ddc,
--
drivers/gpu/drm/i915/display/intel_sdvo.c-3366-
drivers/gpu/drm/i915/display/intel_sdvo.c:3367:	return i2c_add_adapter(&ddc->ddc);
drivers/gpu/drm/i915/display/intel_sdvo.c-3368-}
--
drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c=269=static int mtk_hdmi_ddc_probe(struct platform_device *pdev)
--
drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c-300-
drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c:301:	ret = i2c_add_adapter(&ddc->adap);
drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c-302-	if (ret < 0) {
--
drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c=343=static int mtk_hdmi_ddc_v2_probe(struct platform_device *pdev)
--
drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c-377-
drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c:378:	ret = devm_i2c_add_adapter(dev, &ddc->adap);
drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c-379-	if (ret < 0)
--
drivers/gpu/drm/msm/hdmi/hdmi_i2c.c=243=struct i2c_adapter *msm_hdmi_i2c_init(struct hdmi *hdmi)
--
drivers/gpu/drm/msm/hdmi/hdmi_i2c.c-265-
drivers/gpu/drm/msm/hdmi/hdmi_i2c.c:266:	ret = i2c_add_adapter(i2c);
drivers/gpu/drm/msm/hdmi/hdmi_i2c.c-267-	if (ret)
--
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxch.c=186=nvkm_i2c_aux_ctor(const struct nvkm_i2c_aux_func *func,
--
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxch.c-203-	aux->i2c.algo = &nvkm_i2c_aux_i2c_algo;
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxch.c:204:	return i2c_add_adapter(&aux->i2c);
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxch.c-205-}
--
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.c=208=nvkm_i2c_bus_ctor(const struct nvkm_i2c_bus_func *func,
--
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.c-249-		bus->i2c.algo = &nvkm_i2c_bus_algo;
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.c:250:		ret = i2c_add_adapter(&bus->i2c);
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.c-251-	}
--
drivers/gpu/drm/radeon/radeon_i2c.c=903=struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
--
drivers/gpu/drm/radeon/radeon_i2c.c-933-		i2c->adapter.algo = &radeon_i2c_algo;
drivers/gpu/drm/radeon/radeon_i2c.c:934:		ret = devm_i2c_add_adapter(dev->dev, &i2c->adapter);
drivers/gpu/drm/radeon/radeon_i2c.c-935-		if (ret)
--
drivers/gpu/drm/radeon/radeon_i2c.c-943-		i2c->adapter.algo = &radeon_atom_i2c_algo;
drivers/gpu/drm/radeon/radeon_i2c.c:944:		ret = i2c_add_adapter(&i2c->adapter);
drivers/gpu/drm/radeon/radeon_i2c.c-945-		if (ret)
--
drivers/gpu/drm/rockchip/rk3066_hdmi.c=643=static struct i2c_adapter *rk3066_hdmi_i2c_adapter(struct rk3066_hdmi *hdmi)
--
drivers/gpu/drm/rockchip/rk3066_hdmi.c-663-
drivers/gpu/drm/rockchip/rk3066_hdmi.c:664:	ret = devm_i2c_add_adapter(hdmi->dev, adap);
drivers/gpu/drm/rockchip/rk3066_hdmi.c-665-	if (ret) {
--
drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c=287=int sun4i_hdmi_i2c_create(struct device *dev, struct sun4i_hdmi *hdmi)
--
drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c-308-
drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c:309:	ret = i2c_add_adapter(adap);
drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c-310-	if (ret)
--
drivers/gpu/drm/tests/drm_connector_test.c=79=static int drm_test_connector_init(struct kunit *test)
--
drivers/gpu/drm/tests/drm_connector_test.c-97-
drivers/gpu/drm/tests/drm_connector_test.c:98:	ret = i2c_add_adapter(&priv->ddc);
drivers/gpu/drm/tests/drm_connector_test.c-99-	KUNIT_ASSERT_EQ(test, ret, 0);
--
drivers/hid/hid-cp2112.c=1218=static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
--
drivers/hid/hid-cp2112.c-1339-	hid_device_io_start(hdev);
drivers/hid/hid-cp2112.c:1340:	ret = i2c_add_adapter(&dev->adap);
drivers/hid/hid-cp2112.c-1341-	hid_device_io_stop(hdev);
--
drivers/hid/hid-ft260.c=960=static int ft260_probe(struct hid_device *hdev, const struct hid_device_id *id)
--
drivers/hid/hid-ft260.c-1027-	i2c_set_adapdata(&dev->adap, dev);
drivers/hid/hid-ft260.c:1028:	ret = i2c_add_adapter(&dev->adap);
drivers/hid/hid-ft260.c-1029-	if (ret) {
--
drivers/hid/hid-mcp2221.c=1237=static int mcp2221_probe(struct hid_device *hdev,
--
drivers/hid/hid-mcp2221.c-1305-	i2c_set_adapdata(&mcp->adapter, mcp);
drivers/hid/hid-mcp2221.c:1306:	ret = devm_i2c_add_adapter(&hdev->dev, &mcp->adapter);
drivers/hid/hid-mcp2221.c-1307-	if (ret) {
--
drivers/i2c/algos/i2c-algo-bit.c=675=int i2c_bit_add_bus(struct i2c_adapter *adap)
drivers/i2c/algos/i2c-algo-bit.c-676-{
drivers/i2c/algos/i2c-algo-bit.c:677:	return __i2c_bit_add_bus(adap, i2c_add_adapter);
drivers/i2c/algos/i2c-algo-bit.c-678-}
--
drivers/i2c/algos/i2c-algo-pca.c=532=int i2c_pca_add_bus(struct i2c_adapter *adap)
--
drivers/i2c/algos/i2c-algo-pca.c-539-
drivers/i2c/algos/i2c-algo-pca.c:540:	return i2c_add_adapter(adap);
drivers/i2c/algos/i2c-algo-pca.c-541-}
--
drivers/i2c/algos/i2c-algo-pcf.c=349=int i2c_pcf_add_bus(struct i2c_adapter *adap)
--
drivers/i2c/algos/i2c-algo-pcf.c-360-
drivers/i2c/algos/i2c-algo-pcf.c:361:	rval = i2c_add_adapter(adap);
drivers/i2c/algos/i2c-algo-pcf.c-362-
--
drivers/i2c/busses/i2c-ali1535.c=486=static int ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id)
--
drivers/i2c/busses/i2c-ali1535.c-500-		"SMBus ALI1535 adapter at %04x", ali1535_offset);
drivers/i2c/busses/i2c-ali1535.c:501:	ret = i2c_add_adapter(&ali1535_adapter);
drivers/i2c/busses/i2c-ali1535.c-502-	if (ret)
--
drivers/i2c/busses/i2c-ali1563.c=396=static int ali1563_probe(struct pci_dev *dev,
--
drivers/i2c/busses/i2c-ali1563.c-406-		 "SMBus ALi 1563 Adapter @ %04x", ali1563_smba);
drivers/i2c/busses/i2c-ali1563.c:407:	error = i2c_add_adapter(&ali1563_adapter);
drivers/i2c/busses/i2c-ali1563.c-408-	if (error)
--
drivers/i2c/busses/i2c-ali15x3.c=473=static int ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
--
drivers/i2c/busses/i2c-ali15x3.c-487-		"SMBus ALI15X3 adapter at %04x", ali15x3_smba);
drivers/i2c/busses/i2c-ali15x3.c:488:	ret = i2c_add_adapter(&ali15x3_adapter);
drivers/i2c/busses/i2c-ali15x3.c-489-	if (ret)
--
drivers/i2c/busses/i2c-altera.c=383=static int altr_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-altera.c-457-
drivers/i2c/busses/i2c-altera.c:458:	ret = i2c_add_adapter(&idev->adapter);
drivers/i2c/busses/i2c-altera.c-459-	if (ret) {
--
drivers/i2c/busses/i2c-amd-asf-plat.c=299=static int amd_asf_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-amd-asf-plat.c-348-
drivers/i2c/busses/i2c-amd-asf-plat.c:349:	return devm_i2c_add_adapter(dev, &asf_dev->adap);
drivers/i2c/busses/i2c-amd-asf-plat.c-350-}
--
drivers/i2c/busses/i2c-amd-mp2-plat.c=245=static int i2c_amd_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-amd-mp2-plat.c-314-	/* Attach to the i2c layer */
drivers/i2c/busses/i2c-amd-mp2-plat.c:315:	ret = i2c_add_adapter(&i2c_dev->adap);
drivers/i2c/busses/i2c-amd-mp2-plat.c-316-
--
drivers/i2c/busses/i2c-amd756.c=314=static int amd756_probe(struct pci_dev *pdev, const struct pci_device_id *id)
--
drivers/i2c/busses/i2c-amd756.c-371-
drivers/i2c/busses/i2c-amd756.c:372:	error = i2c_add_adapter(&amd756_smbus);
drivers/i2c/busses/i2c-amd756.c-373-	if (error)
--
drivers/i2c/busses/i2c-amd8111.c=422=static int amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id)
--
drivers/i2c/busses/i2c-amd8111.c-455-	pci_write_config_dword(smbus->dev, AMD_PCI_MISC, 0);
drivers/i2c/busses/i2c-amd8111.c:456:	error = i2c_add_adapter(&smbus->adapter);
drivers/i2c/busses/i2c-amd8111.c-457-	if (error)
--
drivers/i2c/busses/i2c-aspeed.c=998=static int aspeed_i2c_probe_bus(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-aspeed.c-1072-
drivers/i2c/busses/i2c-aspeed.c:1073:	ret = i2c_add_adapter(&bus->adap);
drivers/i2c/busses/i2c-aspeed.c-1074-	if (ret < 0)
--
drivers/i2c/busses/i2c-axxia.c=720=static int axxia_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-axxia.c-782-
drivers/i2c/busses/i2c-axxia.c:783:	ret = i2c_add_adapter(&idev->adapter);
drivers/i2c/busses/i2c-axxia.c-784-	if (ret)
--
drivers/i2c/busses/i2c-bcm-iproc.c=1088=static int bcm_iproc_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-bcm-iproc.c-1158-
drivers/i2c/busses/i2c-bcm-iproc.c:1159:	return i2c_add_adapter(adap);
drivers/i2c/busses/i2c-bcm-iproc.c-1160-}
--
drivers/i2c/busses/i2c-bcm-kona.c=737=static int bcm_kona_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-bcm-kona.c-845-
drivers/i2c/busses/i2c-bcm-kona.c:846:	rc = i2c_add_adapter(adap);
drivers/i2c/busses/i2c-bcm-kona.c-847-	if (rc)
--
drivers/i2c/busses/i2c-bcm2835.c=408=static int bcm2835_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-bcm2835.c-488-
drivers/i2c/busses/i2c-bcm2835.c:489:	ret = i2c_add_adapter(adap);
drivers/i2c/busses/i2c-bcm2835.c-490-	if (ret)
--
drivers/i2c/busses/i2c-brcmstb.c=612=static int brcmstb_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-brcmstb.c-691-	adap->dev.of_node = pdev->dev.of_node;
drivers/i2c/busses/i2c-brcmstb.c:692:	rc = i2c_add_adapter(adap);
drivers/i2c/busses/i2c-brcmstb.c-693-	if (rc)
--
drivers/i2c/busses/i2c-cadence.c=1493=static int cdns_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-cadence.c-1599-
drivers/i2c/busses/i2c-cadence.c:1600:	ret = i2c_add_adapter(&id->adap);
drivers/i2c/busses/i2c-cadence.c-1601-	if (ret < 0)
--
drivers/i2c/busses/i2c-cht-wc.c=426=static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-cht-wc.c-490-	i2c_set_adapdata(&adap->adapter, adap);
drivers/i2c/busses/i2c-cht-wc.c:491:	ret = i2c_add_adapter(&adap->adapter);
drivers/i2c/busses/i2c-cht-wc.c-492-	if (ret)
--
drivers/i2c/busses/i2c-cp2615.c=282=cp2615_i2c_probe(struct usb_interface *usbif, const struct usb_device_id *id)
--
drivers/i2c/busses/i2c-cp2615.c-311-
drivers/i2c/busses/i2c-cp2615.c:312:	ret = i2c_add_adapter(adap);
drivers/i2c/busses/i2c-cp2615.c-313-	if (ret)
--
drivers/i2c/busses/i2c-cros-ec-tunnel.c=242=static int ec_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-cros-ec-tunnel.c-280-
drivers/i2c/busses/i2c-cros-ec-tunnel.c:281:	err = i2c_add_adapter(&bus->adap);
drivers/i2c/busses/i2c-cros-ec-tunnel.c-282-	if (err)
--
drivers/i2c/busses/i2c-digicolor.c=288=static int dc_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-digicolor.c-340-
drivers/i2c/busses/i2c-digicolor.c:341:	ret = i2c_add_adapter(&i2c->adap);
drivers/i2c/busses/i2c-digicolor.c-342-	if (ret < 0) {
--
drivers/i2c/busses/i2c-diolan-u2c.c=430=static int diolan_u2c_probe(struct usb_interface *interface,
--
drivers/i2c/busses/i2c-diolan-u2c.c-474-	/* and finally attach to i2c layer */
drivers/i2c/busses/i2c-diolan-u2c.c:475:	ret = i2c_add_adapter(&dev->adapter);
drivers/i2c/busses/i2c-diolan-u2c.c-476-	if (ret < 0)
--
drivers/i2c/busses/i2c-dln2.c=187=static int dln2_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-dln2.c-224-	/* and finally attach to i2c layer */
drivers/i2c/busses/i2c-dln2.c:225:	ret = i2c_add_adapter(&dln2->adapter);
drivers/i2c/busses/i2c-dln2.c-226-	if (ret < 0)
--
drivers/i2c/busses/i2c-eg20t.c=712=static int pch_i2c_probe(struct pci_dev *pdev,
--
drivers/i2c/busses/i2c-eg20t.c-783-		if (ret) {
drivers/i2c/busses/i2c-eg20t.c:784:			pch_pci_err(pdev, "i2c_add_adapter[ch:%d] FAILED\n", i);
drivers/i2c/busses/i2c-eg20t.c-785-			goto err_add_adapter;
--
drivers/i2c/busses/i2c-emev2.c=360=static int em_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-emev2.c-403-
drivers/i2c/busses/i2c-emev2.c:404:	ret = i2c_add_adapter(&priv->adap);
drivers/i2c/busses/i2c-emev2.c-405-	if (ret)
--
drivers/i2c/busses/i2c-exynos5.c=887=static int exynos5_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-exynos5.c-960-
drivers/i2c/busses/i2c-exynos5.c:961:	ret = i2c_add_adapter(&i2c->adap);
drivers/i2c/busses/i2c-exynos5.c-962-	if (ret < 0)
--
drivers/i2c/busses/i2c-fsi.c=677=static int fsi_i2c_probe(struct fsi_device *fsi_dev)
--
drivers/i2c/busses/i2c-fsi.c-728-
drivers/i2c/busses/i2c-fsi.c:729:		rc = i2c_add_adapter(&port->adapter);
drivers/i2c/busses/i2c-fsi.c-730-		if (rc < 0) {
--
drivers/i2c/busses/i2c-gxp.c=507=static int gxp_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-gxp.c-572-
drivers/i2c/busses/i2c-gxp.c:573:	rc = i2c_add_adapter(adapter);
drivers/i2c/busses/i2c-gxp.c-574-	if (rc)
--
drivers/i2c/busses/i2c-hisi.c=457=static int hisi_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-hisi.c-506-
drivers/i2c/busses/i2c-hisi.c:507:	ret = devm_i2c_add_adapter(dev, adapter);
drivers/i2c/busses/i2c-hisi.c-508-	if (ret)
--
drivers/i2c/busses/i2c-hix5hd2.c=390=static int hix5hd2_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-hix5hd2.c-454-
drivers/i2c/busses/i2c-hix5hd2.c:455:	ret = i2c_add_adapter(&priv->adap);
drivers/i2c/busses/i2c-hix5hd2.c-456-	if (ret < 0)
--
drivers/i2c/busses/i2c-i801.c=1537=static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
--
drivers/i2c/busses/i2c-i801.c-1664-
drivers/i2c/busses/i2c-i801.c:1665:	err = i2c_add_adapter(&priv->adapter);
drivers/i2c/busses/i2c-i801.c-1666-	if (err) {
--
drivers/i2c/busses/i2c-ibm_iic.c=682=static int iic_probe(struct platform_device *ofdev)
--
drivers/i2c/busses/i2c-ibm_iic.c-738-
drivers/i2c/busses/i2c-ibm_iic.c:739:	ret = i2c_add_adapter(adap);
drivers/i2c/busses/i2c-ibm_iic.c-740-	if (ret  < 0)
--
drivers/i2c/busses/i2c-imx-lpi2c.c=1471=static int lpi2c_imx_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-imx-lpi2c.c-1566-
drivers/i2c/busses/i2c-imx-lpi2c.c:1567:	ret = i2c_add_adapter(&lpi2c_imx->adapter);
drivers/i2c/busses/i2c-imx-lpi2c.c-1568-	if (ret)
--
drivers/i2c/busses/i2c-isch.c=274=static int smbus_sch_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-isch.c-300-
drivers/i2c/busses/i2c-isch.c:301:	return devm_i2c_add_adapter(dev, &priv->adapter);
drivers/i2c/busses/i2c-isch.c-302-}
--
drivers/i2c/busses/i2c-ismt.c=883=ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id)
--
drivers/i2c/busses/i2c-ismt.c-965-
drivers/i2c/busses/i2c-ismt.c:966:	err = i2c_add_adapter(&priv->adapter);
drivers/i2c/busses/i2c-ismt.c-967-	if (err)
--
drivers/i2c/busses/i2c-jz4780.c=761=static int jz4780_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-jz4780.c-833-
drivers/i2c/busses/i2c-jz4780.c:834:	ret = i2c_add_adapter(&i2c->adap);
drivers/i2c/busses/i2c-jz4780.c-835-	if (ret < 0)
--
drivers/i2c/busses/i2c-keba.c=507=static int ki2c_probe(struct auxiliary_device *auxdev,
--
drivers/i2c/busses/i2c-keba.c-546-
drivers/i2c/busses/i2c-keba.c:547:	ret = devm_i2c_add_adapter(dev, adap);
drivers/i2c/busses/i2c-keba.c-548-	if (ret) {
--
drivers/i2c/busses/i2c-ljca.c=273=static int ljca_i2c_probe(struct auxiliary_device *auxdev,
--
drivers/i2c/busses/i2c-ljca.c-307-
drivers/i2c/busses/i2c-ljca.c:308:	ret = devm_i2c_add_adapter(&auxdev->dev, &ljca_i2c->adap);
drivers/i2c/busses/i2c-ljca.c-309-	if (ret)
--
drivers/i2c/busses/i2c-lpc2k.c=345=static int i2c_lpc2k_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-lpc2k.c-416-
drivers/i2c/busses/i2c-lpc2k.c:417:	ret = i2c_add_adapter(&i2c->adap);
drivers/i2c/busses/i2c-lpc2k.c-418-	if (ret < 0)
--
drivers/i2c/busses/i2c-ls2x-v2.c=475=static int loongson2_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-ls2x-v2.c-523-
drivers/i2c/busses/i2c-ls2x-v2.c:524:	return devm_i2c_add_adapter(dev, adap);
drivers/i2c/busses/i2c-ls2x-v2.c-525-}
--
drivers/i2c/busses/i2c-ls2x.c=287=static int ls2x_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-ls2x.c-327-
drivers/i2c/busses/i2c-ls2x.c:328:	return devm_i2c_add_adapter(dev, adap);
drivers/i2c/busses/i2c-ls2x.c-329-}
--
drivers/i2c/busses/i2c-mchp-pci1xxxx.c=1129=static int pci1xxxx_i2c_probe_pci(struct pci_dev *pdev,
--
drivers/i2c/busses/i2c-mchp-pci1xxxx.c-1181-
drivers/i2c/busses/i2c-mchp-pci1xxxx.c:1182:	ret = devm_i2c_add_adapter(dev, &i2c->adap);
drivers/i2c/busses/i2c-mchp-pci1xxxx.c-1183-	if (ret)
--
drivers/i2c/busses/i2c-meson.c=456=static int meson_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-meson.c-527-
drivers/i2c/busses/i2c-meson.c:528:	ret = i2c_add_adapter(&i2c->adap);
drivers/i2c/busses/i2c-meson.c-529-	if (ret < 0) {
--
drivers/i2c/busses/i2c-microchip-corei2c.c=538=static int mchp_corei2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-microchip-corei2c.c-608-
drivers/i2c/busses/i2c-microchip-corei2c.c:609:	ret = i2c_add_adapter(&idev->adapter);
drivers/i2c/busses/i2c-microchip-corei2c.c-610-	if (ret) {
--
drivers/i2c/busses/i2c-mt65xx.c=1385=static int mtk_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-mt65xx.c-1500-	i2c_set_adapdata(&i2c->adap, i2c);
drivers/i2c/busses/i2c-mt65xx.c:1501:	ret = i2c_add_adapter(&i2c->adap);
drivers/i2c/busses/i2c-mt65xx.c-1502-	if (ret)
--
drivers/i2c/busses/i2c-mt7621.c=268=static int mtk_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-mt7621.c-311-
drivers/i2c/busses/i2c-mt7621.c:312:	ret = i2c_add_adapter(adap);
drivers/i2c/busses/i2c-mt7621.c-313-	if (ret < 0)
--
drivers/i2c/busses/i2c-nct6694.c=145=static int nct6694_i2c_probe(struct platform_device *pdev)
--
drivers/i2c/busses/i2c-nct6694.c-180-
drivers/i2c/busses/i2c-nct6694.c:181:	return devm_i2c_add_adapter(dev, &data->adapter);
drivers/i2c/busses/i2c-nct6694.c-182-}
--
drivers/i2c/busses/i2c-nforce2.c=304=static int nforce2_probe_smb(struct pci_dev *dev, int bar, int alt_reg,
--
drivers/i2c/busses/i2c-nforce2.c-344-
drivers/i2c/busses/i2c-nforce2.c:345:	error = i2c_add_adapter(&smbus->adapter);
drivers/i2c/busses/i2c-nforce2.c-346-	if (error) {
--
drivers/i2c/busses/i2c-nomadik.c=1082=static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)

]

492/2 2026/07/30 13:35 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 48771
							output: 54
							thoughts: 288
						

Thoughts:
**Analyzing a Potential Kernel Bug**

Okay, so it's not *just* `go7007` causing this issue. I'm trying to trace down this memory leak that we've seen, specifically the one where `i2c_add_adapter` gets called but `i2c_del_adapter` doesn't. We know that `go7007` has this known issue: it calls `i2c_add_adapter`, and if `ep_in[6]` is missing, it skips `i2c_del_adapter` before freeing the struct, which causes a leak.

First, I need to confirm if `go7007` is even compiled into the syzkaller kernel. If it's not, we can rule it out immediately. My instinct is to check the kernel config for `CONFIG_VIDEO_GO7007`, but I don't have direct access to that. I could try `codesearch-find-references` for `go7007_usb_probe`, but that seems like it would just search the source code and I need to know if it's compiled, not just present. So, no.

Hmm... Let's see if another driver exhibits the same flawed behavior. I need to widen the search. What about `au0828`? I'll check `au0828_usb_probe` and see what it does. `au0828` calls `au0828_i2c_register`, so I need to see if it unregisters in its error paths. I'll focus on `au0828_usb_probe` and its cleanup.



493/2 2026/07/30 13:35 tool codesearch-definition-source
0m Args:
map[ContextFile:drivers/media/usb/au0828/au0828-core.c Name:au0828_usb_probe]

Results:
map[SourceCode: 643:	static int au0828_usb_probe(struct usb_interface *interface,
 644:		const struct usb_device_id *id)
 645:	{
 646:		int ifnum;
 647:		int retval = 0;
 648:	
 649:		struct au0828_dev *dev;
 650:		struct usb_device *usbdev = interface_to_usbdev(interface);
 651:	
 652:		ifnum = interface->altsetting->desc.bInterfaceNumber;
 653:	
 654:		if (ifnum != 0)
 655:			return -ENODEV;
 656:	
 657:		dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__,
 658:			le16_to_cpu(usbdev->descriptor.idVendor),
 659:			le16_to_cpu(usbdev->descriptor.idProduct),
 660:			ifnum);
 661:	
 662:		/*
 663:		 * Make sure we have 480 Mbps of bandwidth, otherwise things like
 664:		 * video stream wouldn't likely work, since 12 Mbps is generally
 665:		 * not enough even for most Digital TV streams.
 666:		 */
 667:		if (usbdev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) {
 668:			pr_err("au0828: Device initialization failed.\n");
 669:			pr_err("au0828: Device must be connected to a high-speed USB 2.0 port.\n");
 670:			return -ENODEV;
 671:		}
 672:	
 673:		dev = kzalloc_obj(*dev);
 674:		if (dev == NULL) {
 675:			pr_err("%s() Unable to allocate memory\n", __func__);
 676:			return -ENOMEM;
 677:		}
 678:	
 679:		mutex_init(&dev->lock);
 680:		mutex_lock(&dev->lock);
 681:		mutex_init(&dev->mutex);
 682:		mutex_init(&dev->dvb.lock);
 683:		dev->usbdev = usbdev;
 684:		dev->boardnr = id->driver_info;
 685:		dev->board = au0828_boards[dev->boardnr];
 686:	
 687:		/* Initialize the media controller */
 688:		retval = au0828_media_device_init(dev, usbdev);
 689:		if (retval) {
 690:			pr_err("%s() au0828_media_device_init failed\n",
 691:			       __func__);
 692:			mutex_unlock(&dev->lock);
 693:			kfree(dev);
 694:			return retval;
 695:		}
 696:	
 697:		retval = au0828_v4l2_device_register(interface, dev);
 698:		if (retval) {
 699:			au0828_usb_v4l2_media_release(dev);
 700:			mutex_unlock(&dev->lock);
 701:			kfree(dev);
 702:			return retval;
 703:		}
 704:	
 705:		/* Power Up the bridge */
 706:		au0828_write(dev, REG_600, 1 << 4);
 707:	
 708:		/* Bring up the GPIO's and supporting devices */
 709:		au0828_gpio_setup(dev);
 710:	
 711:		/* I2C */
 712:		au0828_i2c_register(dev);
 713:	
 714:		/* Setup */
 715:		au0828_card_setup(dev);
 716:	
 717:		/*
 718:		 * Store the pointer to the au0828_dev so it can be accessed in
 719:		 * au0828_usb_disconnect
 720:		 */
 721:		usb_set_intfdata(interface, dev);
 722:	
 723:		/* Analog TV */
 724:		retval = au0828_analog_register(dev, interface);
 725:		if (retval) {
 726:			pr_err("%s() au0828_analog_register failed to register on V4L2\n",
 727:				__func__);
 728:			mutex_unlock(&dev->lock);
 729:			goto done;
 730:		}
 731:	
 732:		/* Digital TV */
 733:		retval = au0828_dvb_register(dev);
 734:		if (retval)
 735:			pr_err("%s() au0828_dvb_register failed\n",
 736:			       __func__);
 737:	
 738:		/* Remote controller */
 739:		au0828_rc_register(dev);
 740:	
 741:		pr_info("Registered device AU0828 [%s]\n",
 742:			dev->board.name == NULL ? "Unset" : dev->board.name);
 743:	
 744:		mutex_unlock(&dev->lock);
 745:	
 746:		retval = au0828_media_device_register(dev, usbdev);
 747:	
 748:	done:
 749:		if (retval < 0)
 750:			au0828_usb_disconnect(interface);
 751:	
 752:		return retval;
 753:	}
 SourceFile:drivers/media/usb/au0828/au0828-core.c]

494/2 2026/07/30 13:35 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 51169
							output: 54
							thoughts: 50
						

Thoughts:
**Analyzing the USB Probe and Disconnect Functions**

Okay, so I'm looking at this `au0828_usb_probe` function, and something just clicked. It looks like it checks the return value, `retval`. And if it's less than zero, which indicates an error, it calls `au0828_usb_disconnect` immediately, passing in the `interface` variable. That's a critical bit of logic. It means the disconnect function is intended to clean up resources or handle errors if the initial probing of the USB device fails. I need to understand what this disconnect function actually *does*. I need to see if it makes sense in the context of device initialization and error handling. So, I need to investigate `au0828_usb_disconnect` right now. Let's see what we are dealing with.



495/2 2026/07/30 13:35 tool codesearch-definition-source
0m Args:
map[ContextFile:drivers/media/usb/au0828/au0828-core.c Name:au0828_usb_disconnect]

Results:
map[SourceCode: 163:	static void au0828_usb_disconnect(struct usb_interface *interface)
 164:	{
 165:		struct au0828_dev *dev = usb_get_intfdata(interface);
 166:	
 167:		dprintk(1, "%s()\n", __func__);
 168:	
 169:		/* there is a small window after disconnect, before
 170:		   dev->usbdev is NULL, for poll (e.g: IR) try to access
 171:		   the device and fill the dmesg with error messages.
 172:		   Set the status so poll routines can check and avoid
 173:		   access after disconnect.
 174:		*/
 175:		set_bit(DEV_DISCONNECTED, &dev->dev_state);
 176:	
 177:		au0828_rc_unregister(dev);
 178:		/* Digital TV */
 179:		au0828_dvb_unregister(dev);
 180:	
 181:		usb_set_intfdata(interface, NULL);
 182:		mutex_lock(&dev->mutex);
 183:		dev->usbdev = NULL;
 184:		mutex_unlock(&dev->mutex);
 185:		if (au0828_analog_unregister(dev)) {
 186:			/*
 187:			 * No need to call au0828_usb_release() if V4L2 is enabled,
 188:			 * as this is already called via au0828_usb_v4l2_release()
 189:			 */
 190:			return;
 191:		}
 192:		au0828_usb_release(dev);
 193:	}
 SourceFile:drivers/media/usb/au0828/au0828-core.c]

496/2 2026/07/30 13:35 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 51985
							output: 54
							thoughts: 291
						

Thoughts:
**Analyzing the Device Disconnect Sequence**

Okay, let's see. My initial thought is, how does `au0828_usb_disconnect` get its device (`dev`)? Right, it uses `usb_get_intfdata(interface)`. I need to ensure the correct `dev` is being passed.

Now, in `au0828_usb_probe`, `usb_set_intfdata(interface, dev)` is *definitely* called *before* `au0828_analog_register`. Good, that seems logical. But what happens if `au0828_analog_register` fails? The code jumps to `done`, and then it calls `au0828_usb_disconnect`. I need to track that.

Hmm, this reminds me of something else. What if there are failures in other places? Specifically, what if `au0828_media_device_init` fails? It frees `dev` and returns. And what if `au0828_v4l2_device_register` fails? Same situation: `kfree(dev)` and returns. So in both these cases, we're not hitting `au0828_usb_disconnect`.

But what if, *again*, `au0828_analog_register` fails, as we were originally considering? Then the flow jumps to `done`, and calls `au0828_usb_disconnect`. And `au0828_usb_disconnect` then retrieves `dev` via `usb_get_intfdata`. Then it calls `au0828_analog_unregister(dev)`.

Wait a minute, if `au0828_analog_unregister` *returns* true (let's assume that means it's "in use", or something similar), the function returns *early*. This might be a critical point of failure. I need to understand that return condition of `au0828_analog_unregister`. I'm going to look at that function next.



497/2 2026/07/30 13:36 tool codesearch-definition-source
0m Args:
map[ContextFile:drivers/media/usb/au0828/au0828-core.c Name:au0828_analog_unregister]

Results:
map[SourceCode: 920:	/* ------------------------------------------------------------------
 921:	   V4L2 interface
 922:	   ------------------------------------------------------------------*/
 923:	/*
 924:	 * au0828_analog_unregister
 925:	 * unregister v4l2 devices
 926:	 */
 927:	int au0828_analog_unregister(struct au0828_dev *dev)
 928:	{
 929:		dprintk(1, "au0828_analog_unregister called\n");
 930:	
 931:		/* No analog TV */
 932:		if (AUVI_INPUT(0).type == AU0828_VMUX_UNDEFINED)
 933:			return 0;
 934:	
 935:		mutex_lock(&au0828_sysfs_lock);
 936:		vb2_video_unregister_device(&dev->vdev);
 937:		vb2_video_unregister_device(&dev->vbi_dev);
 938:		mutex_unlock(&au0828_sysfs_lock);
 939:	
 940:		v4l2_device_disconnect(&dev->v4l2_dev);
 941:		v4l2_device_put(&dev->v4l2_dev);
 942:	
 943:		return 1;
 944:	}
 SourceFile:drivers/media/usb/au0828/au0828-video.c]

498/2 2026/07/30 13:36 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 53207
							output: 59
							thoughts: 247
						

Thoughts:
**Analyzing the Device Unregistration Logic**

Okay, hold on a minute. This `au0828_analog_unregister` function… it returns 1 if the input type isn't defined, right? Specifically, if `AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED`. And if it *does* return 1, the `au0828_usb_disconnect` function in the calling context bails out immediately. That's a crucial detail. Looking at the code:

```c
	if (au0828_analog_unregister(dev)) {
		/*
		 * No need to call au0828_usb_release() if V4L2 is enabled,
		 * as this is already called via au0828_usb_v4l2_release()
		 */
		return;
	}
	au0828_usb_release(dev);
```

So, if `au0828_analog_unregister` signals an error (returns 1), we *don't* call `au0828_usb_release`. Instead, the logic implies that the unregistration of analog components and the associated cleanup are somehow handled by `au0828_usb_v4l2_release` in the V4L2 context. The comment suggests there's an assumption being made here, that `au0828_usb_v4l2_release` handles the necessary release in the error condition. I need to verify that, specifically when the V4L2 device is enabled. I need to examine `au0828_usb_v4l2_release` to understand the full picture.



499/2 2026/07/30 13:36 tool codesearch-definition-source
0m Args:
map[ContextFile:drivers/media/usb/au0828/au0828-video.c Name:au0828_usb_v4l2_release]

Results:
map[SourceCode: 635:	static void au0828_usb_v4l2_release(struct v4l2_device *v4l2_dev)
 636:	{
 637:		struct au0828_dev *dev =
 638:			container_of(v4l2_dev, struct au0828_dev, v4l2_dev);
 639:	
 640:		v4l2_ctrl_handler_free(&dev->v4l2_ctrl_hdl);
 641:		v4l2_device_unregister(&dev->v4l2_dev);
 642:		au0828_usb_v4l2_media_release(dev);
 643:		au0828_usb_release(dev);
 644:	}
 SourceFile:drivers/media/usb/au0828/au0828-video.c]

500/2 2026/07/30 13:36 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 54150
							output: 54
							thoughts: 64
						

Thoughts:
Okay, here's my interpretation of that thought process, assuming I'm already deep in the weeds with this code:

**Release Sequence Confirmation**

Alright, so I've been tracing through this USB video capture driver, and finally, it's clicked. It's clear that when `au0828_usb_v4l2_release` is called, it *does* indeed make that crucial call to `au0828_usb_release(dev)`. That's the first key point. It confirms the higher-level release function correctly initiates the USB-specific cleanup.

And then, looking deeper into `au0828_usb_release`, I see that it triggers `au0828_i2c_unregister(dev)`. This is significant because it means the I2C interface associated with the device is properly unregistered as part of the USB release sequence. This confirms the order of operations for resource deallocation, making sure we shut down the I2C interface used by the driver for communication with the device. It's exactly the sequence I'd expect to see, ensuring a clean and safe shutdown.



501/2 2026/07/30 13:36 tool codesearch-definition-source
0m Args:
map[ContextFile:drivers/media/usb/au0828/au0828-core.c Name:au0828_usb_release]

Results:
map[SourceCode: 153:	void au0828_usb_release(struct au0828_dev *dev)
 154:	{
 155:		au0828_unregister_media_device(dev);
 156:	
 157:		/* I2C */
 158:		au0828_i2c_unregister(dev);
 159:	
 160:		kfree(dev);
 161:	}
 SourceFile:drivers/media/usb/au0828/au0828-core.c]

502/2 2026/07/30 13:36 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 54682
							output: 56
							thoughts: 61
						

Thoughts:
Okay, let's see...

**Analyzing the Potential Risks**

Right, so `au0828` looks like it's behaving itself, no immediate red flags there. Now, the `si4713` module... that's where I need to dig a little deeper. The `si4713_usb_probe` function is interesting because it calls `si4713_register_i2c_adapter`. My immediate concern is error handling. If `si4713_register_i2c_adapter` *fails* at some point, does the driver implement the necessary unregistration and cleanup routines to roll things back properly? I need to verify that it's robust and prevents any lingering resource issues or unexpected behavior. That's a critical point for the overall system stability.



503/2 2026/07/30 13:36 tool codesearch-definition-source
0m Args:
map[ContextFile:drivers/media/radio/si4713/radio-usb-si4713.c Name:usb_si4713_probe]

Results:
map[SourceCode: 410:	/* check if the device is present and register with v4l and usb if it is */
 411:	static int usb_si4713_probe(struct usb_interface *intf,
 412:					const struct usb_device_id *id)
 413:	{
 414:		struct si4713_usb_device *radio;
 415:		struct i2c_adapter *adapter;
 416:		struct v4l2_subdev *sd;
 417:		int retval;
 418:	
 419:		dev_info(&intf->dev, "Si4713 development board discovered: (%04X:%04X)\n",
 420:				id->idVendor, id->idProduct);
 421:	
 422:		/* Initialize local device structure */
 423:		radio = kzalloc_obj(struct si4713_usb_device);
 424:		if (radio)
 425:			radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
 426:	
 427:		if (!radio || !radio->buffer) {
 428:			dev_err(&intf->dev, "kmalloc for si4713_usb_device failed\n");
 429:			kfree(radio);
 430:			return -ENOMEM;
 431:		}
 432:	
 433:		mutex_init(&radio->lock);
 434:	
 435:		radio->usbdev = interface_to_usbdev(intf);
 436:		radio->intf = intf;
 437:		usb_set_intfdata(intf, &radio->v4l2_dev);
 438:	
 439:		retval = si4713_start_seq(radio);
 440:		if (retval < 0)
 441:			goto err_v4l2;
 442:	
 443:		retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
 444:		if (retval < 0) {
 445:			dev_err(&intf->dev, "couldn't register v4l2_device\n");
 446:			goto err_v4l2;
 447:		}
 448:	
 449:		retval = si4713_register_i2c_adapter(radio);
 450:		if (retval < 0) {
 451:			dev_err(&intf->dev, "could not register i2c device\n");
 452:			goto err_i2cdev;
 453:		}
 454:	
 455:		adapter = &radio->i2c_adapter;
 456:		sd = v4l2_i2c_new_subdev_board(&radio->v4l2_dev, adapter,
 457:						  &si4713_board_info, NULL);
 458:		radio->v4l2_subdev = sd;
 459:		if (!sd) {
 460:			dev_err(&intf->dev, "cannot get v4l2 subdevice\n");
 461:			retval = -ENODEV;
 462:			goto del_adapter;
 463:		}
 464:	
 465:		radio->vdev.ctrl_handler = sd->ctrl_handler;
 466:		radio->v4l2_dev.release = usb_si4713_video_device_release;
 467:		strscpy(radio->vdev.name, radio->v4l2_dev.name,
 468:			sizeof(radio->vdev.name));
 469:		radio->vdev.v4l2_dev = &radio->v4l2_dev;
 470:		radio->vdev.fops = &usb_si4713_fops;
 471:		radio->vdev.ioctl_ops = &usb_si4713_ioctl_ops;
 472:		radio->vdev.lock = &radio->lock;
 473:		radio->vdev.release = video_device_release_empty;
 474:		radio->vdev.vfl_dir = VFL_DIR_TX;
 475:		radio->vdev.device_caps = V4L2_CAP_MODULATOR | V4L2_CAP_RDS_OUTPUT;
 476:	
 477:		video_set_drvdata(&radio->vdev, radio);
 478:	
 479:		retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO, -1);
 480:		if (retval < 0) {
 481:			dev_err(&intf->dev, "could not register video device\n");
 482:			goto del_adapter;
 483:		}
 484:	
 485:		dev_info(&intf->dev, "V4L2 device registered as %s\n",
 486:				video_device_node_name(&radio->vdev));
 487:	
 488:		return 0;
 489:	
 490:	del_adapter:
 491:		i2c_del_adapter(adapter);
 492:	err_i2cdev:
 493:		v4l2_device_unregister(&radio->v4l2_dev);
 494:	err_v4l2:
 495:		kfree(radio->buffer);
 496:		kfree(radio);
 497:		return retval;
 498:	}
 SourceFile:drivers/media/radio/si4713/radio-usb-si4713.c]

504/2 2026/07/30 13:36 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 56547
							output: 54
							thoughts: 40
						

Thoughts:
Okay, here's my take on those thoughts, framed as my own:

**Reviewing Adapter Deletion Procedures**

Alright, so the `si4713` driver is definitely on the right track. It's properly using `i2c_del_adapter(adapter)` within its `del_adapter` function. That's good, that's what we want to see.

Now, let's take another look at the `go7007` driver. I need to make sure *that* one is handled correctly as well, because this pattern is critical for resource management and preventing I2C bus contention. Gotta be thorough. Time to revisit that code.



505/2 2026/07/30 13:36 tool codesearch-definition-source
0m Args:
map[ContextFile:drivers/media/usb/go7007/go7007-usb.c Name:go7007_usb_probe]

Results:
map[SourceCode:1040:	static int go7007_usb_probe(struct usb_interface *intf,
1041:			const struct usb_device_id *id)
1042:	{
1043:		struct go7007 *go;
1044:		struct go7007_usb *usb;
1045:		const struct go7007_usb_board *board;
1046:		struct usb_device *usbdev = interface_to_usbdev(intf);
1047:		struct usb_host_endpoint *ep;
1048:		unsigned num_i2c_devs;
1049:		char *name;
1050:		int video_pipe, i, v_urb_len;
1051:	
1052:		pr_debug("probing new GO7007 USB board\n");
1053:	
1054:		switch (id->driver_info) {
1055:		case GO7007_BOARDID_MATRIX_II:
1056:			name = "WIS Matrix II or compatible";
1057:			board = &board_matrix_ii;
1058:			break;
1059:		case GO7007_BOARDID_MATRIX_RELOAD:
1060:			name = "WIS Matrix Reloaded or compatible";
1061:			board = &board_matrix_reload;
1062:			break;
1063:		case GO7007_BOARDID_MATRIX_REV:
1064:			name = "WIS Matrix Revolution or compatible";
1065:			board = &board_matrix_revolution;
1066:			break;
1067:		case GO7007_BOARDID_STAR_TREK:
1068:			name = "WIS Star Trek or compatible";
1069:			board = &board_star_trek;
1070:			break;
1071:		case GO7007_BOARDID_XMEN:
1072:			name = "WIS XMen or compatible";
1073:			board = &board_xmen;
1074:			break;
1075:		case GO7007_BOARDID_XMEN_II:
1076:			name = "WIS XMen II or compatible";
1077:			board = &board_xmen;
1078:			break;
1079:		case GO7007_BOARDID_XMEN_III:
1080:			name = "WIS XMen III or compatible";
1081:			board = &board_xmen;
1082:			break;
1083:		case GO7007_BOARDID_PX_M402U:
1084:			name = "Plextor PX-M402U";
1085:			board = &board_matrix_ii;
1086:			break;
1087:		case GO7007_BOARDID_PX_TV402U:
1088:			name = "Plextor PX-TV402U (unknown tuner)";
1089:			board = &board_px_tv402u;
1090:			break;
1091:		case GO7007_BOARDID_LIFEVIEW_LR192:
1092:			dev_err(&intf->dev, "The Lifeview TV Walker Ultra is not supported. Sorry!\n");
1093:			return -ENODEV;
1094:	#if 0
1095:			name = "Lifeview TV Walker Ultra";
1096:			board = &board_lifeview_lr192;
1097:	#endif
1098:			break;
1099:		case GO7007_BOARDID_SENSORAY_2250:
1100:			dev_info(&intf->dev, "Sensoray 2250 found\n");
1101:			name = "Sensoray 2250/2251";
1102:			board = &board_sensoray_2250;
1103:			break;
1104:		case GO7007_BOARDID_ADS_USBAV_709:
1105:			name = "ADS Tech DVD Xpress DX2";
1106:			board = &board_ads_usbav_709;
1107:			break;
1108:		default:
1109:			dev_err(&intf->dev, "unknown board ID %d!\n",
1110:					(unsigned int)id->driver_info);
1111:			return -ENODEV;
1112:		}
1113:	
1114:		go = go7007_alloc(&board->main_info, &intf->dev);
1115:		if (go == NULL)
1116:			return -ENOMEM;
1117:	
1118:		usb = kzalloc_obj(struct go7007_usb);
1119:		if (usb == NULL) {
1120:			kfree(go);
1121:			return -ENOMEM;
1122:		}
1123:	
1124:		usb->board = board;
1125:		usb->usbdev = usbdev;
1126:		usb_make_path(usbdev, go->bus_info, sizeof(go->bus_info));
1127:		go->board_id = id->driver_info;
1128:		strscpy(go->name, name, sizeof(go->name));
1129:		if (board->flags & GO7007_USB_EZUSB)
1130:			go->hpi_ops = &go7007_usb_ezusb_hpi_ops;
1131:		else
1132:			go->hpi_ops = &go7007_usb_onboard_hpi_ops;
1133:		go->hpi_context = usb;
1134:	
1135:		ep = usb->usbdev->ep_in[4];
1136:		if (!ep)
1137:			goto allocfail;
1138:	
1139:		/* Allocate the URB and buffer for receiving incoming interrupts */
1140:		usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
1141:		if (usb->intr_urb == NULL)
1142:			goto allocfail;
1143:		usb->intr_urb->transfer_buffer = kmalloc_array(2, sizeof(u16),
1144:							       GFP_KERNEL);
1145:		if (usb->intr_urb->transfer_buffer == NULL)
1146:			goto allocfail;
1147:	
1148:		if (usb_endpoint_type(&ep->desc) == USB_ENDPOINT_XFER_BULK)
1149:			usb_fill_bulk_urb(usb->intr_urb, usb->usbdev,
1150:				usb_rcvbulkpipe(usb->usbdev, 4),
1151:				usb->intr_urb->transfer_buffer, 2*sizeof(u16),
1152:				go7007_usb_readinterrupt_complete, go);
1153:		else
1154:			usb_fill_int_urb(usb->intr_urb, usb->usbdev,
1155:				usb_rcvintpipe(usb->usbdev, 4),
1156:				usb->intr_urb->transfer_buffer, 2*sizeof(u16),
1157:				go7007_usb_readinterrupt_complete, go, 8);
1158:		usb_set_intfdata(intf, &go->v4l2_dev);
1159:	
1160:		/* Boot the GO7007 */
1161:		if (go7007_boot_encoder(go, go->board_info->flags &
1162:						GO7007_BOARD_USE_ONBOARD_I2C) < 0)
1163:			goto allocfail;
1164:	
1165:		/* Register the EZ-USB I2C adapter, if we're using it */
1166:		if (board->flags & GO7007_USB_EZUSB_I2C) {
1167:			memcpy(&go->i2c_adapter, &go7007_usb_adap_templ,
1168:					sizeof(go7007_usb_adap_templ));
1169:			mutex_init(&usb->i2c_lock);
1170:			go->i2c_adapter.dev.parent = go->dev;
1171:			i2c_set_adapdata(&go->i2c_adapter, go);
1172:			if (i2c_add_adapter(&go->i2c_adapter) < 0) {
1173:				dev_err(go->dev, "error: i2c_add_adapter failed\n");
1174:				goto allocfail;
1175:			}
1176:			go->i2c_adapter_online = 1;
1177:		}
1178:	
1179:		/* Pelco and Adlink reused the XMen and XMen-III vendor and product
1180:		 * IDs for their own incompatible designs.  We can detect XMen boards
1181:		 * by probing the sensor, but there is no way to probe the sensors on
1182:		 * the Pelco and Adlink designs so we default to the Adlink.  If it
1183:		 * is actually a Pelco, the user must set the assume_endura module
1184:		 * parameter. */
1185:		if ((go->board_id == GO7007_BOARDID_XMEN ||
1186:					go->board_id == GO7007_BOARDID_XMEN_III) &&
1187:				go->i2c_adapter_online) {
1188:			union i2c_smbus_data data;
1189:	
1190:			/* Check to see if register 0x0A is 0x76 */
1191:			i2c_smbus_xfer(&go->i2c_adapter, 0x21, I2C_CLIENT_SCCB,
1192:				I2C_SMBUS_READ, 0x0A, I2C_SMBUS_BYTE_DATA, &data);
1193:			if (data.byte != 0x76) {
1194:				if (assume_endura) {
1195:					go->board_id = GO7007_BOARDID_ENDURA;
1196:					usb->board = board = &board_endura;
1197:					go->board_info = &board->main_info;
1198:					strscpy(go->name, "Pelco Endura",
1199:						sizeof(go->name));
1200:				} else {
1201:					u16 channel;
1202:	
1203:					/* read channel number from GPIO[1:0] */
1204:					if (go7007_read_addr(go, 0x3c81, &channel))
1205:						goto allocfail;
1206:	
1207:					channel &= 0x3;
1208:					go->board_id = GO7007_BOARDID_ADLINK_MPG24;
1209:					usb->board = board = &board_adlink_mpg24;
1210:					go->board_info = &board->main_info;
1211:					go->channel_number = channel;
1212:					snprintf(go->name, sizeof(go->name),
1213:						"Adlink PCI-MPG24, channel #%d",
1214:						channel);
1215:				}
1216:				go7007_update_board(go);
1217:			}
1218:		}
1219:	
1220:		num_i2c_devs = go->board_info->num_i2c_devs;
1221:	
1222:		/* Probe the tuner model on the TV402U */
1223:		if (go->board_id == GO7007_BOARDID_PX_TV402U) {
1224:			/* Board strapping indicates tuner model */
1225:			if (go7007_usb_vendor_request(go, 0x41, 0, 0, go->usb_buf, 3,
1226:						1) < 0) {
1227:				dev_err(go->dev, "GPIO read failed!\n");
1228:				goto allocfail;
1229:			}
1230:			switch (go->usb_buf[0] >> 6) {
1231:			case 1:
1232:				go->tuner_type = TUNER_SONY_BTF_PG472Z;
1233:				go->std = V4L2_STD_PAL;
1234:				strscpy(go->name, "Plextor PX-TV402U-EU",
1235:					sizeof(go->name));
1236:				break;
1237:			case 2:
1238:				go->tuner_type = TUNER_SONY_BTF_PK467Z;
1239:				go->std = V4L2_STD_NTSC_M_JP;
1240:				num_i2c_devs -= 2;
1241:				strscpy(go->name, "Plextor PX-TV402U-JP",
1242:					sizeof(go->name));
1243:				break;
1244:			case 3:
1245:				go->tuner_type = TUNER_SONY_BTF_PB463Z;
1246:				num_i2c_devs -= 2;
1247:				strscpy(go->name, "Plextor PX-TV402U-NA",
1248:					sizeof(go->name));
1249:				break;
1250:			default:
1251:				pr_debug("unable to detect tuner type!\n");
1252:				break;
1253:			}
1254:			/* Configure tuner mode selection inputs connected
1255:			 * to the EZ-USB GPIO output pins */
1256:			if (go7007_usb_vendor_request(go, 0x40, 0x7f02, 0,
1257:						NULL, 0, 0) < 0) {
1258:				dev_err(go->dev, "GPIO write failed!\n");
1259:				goto allocfail;
1260:			}
1261:		}
1262:	
1263:		/* Print a nasty message if the user attempts to use a USB2.0 device in
1264:		 * a USB1.1 port.  There will be silent corruption of the stream. */
1265:		if ((board->flags & GO7007_USB_EZUSB) &&
1266:				usbdev->speed != USB_SPEED_HIGH)
1267:			dev_err(go->dev, "*** WARNING ***  This device must be connected to a USB 2.0 port! Attempting to capture video through a USB 1.1 port will result in stream corruption, even at low bitrates!\n");
1268:	
1269:		/* Allocate the URBs and buffers for receiving the video stream */
1270:		if (board->flags & GO7007_USB_EZUSB) {
1271:			if (!usb->usbdev->ep_in[6])
1272:				goto allocfail;
1273:			v_urb_len = 1024;
1274:			video_pipe = usb_rcvbulkpipe(usb->usbdev, 6);
1275:		} else {
1276:			if (!usb->usbdev->ep_in[1])
1277:				goto allocfail;
1278:			v_urb_len = 512;
1279:			video_pipe = usb_rcvbulkpipe(usb->usbdev, 1);
1280:		}
1281:		for (i = 0; i < 8; ++i) {
1282:			usb->video_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
1283:			if (usb->video_urbs[i] == NULL)
1284:				goto allocfail;
1285:			usb->video_urbs[i]->transfer_buffer =
1286:							kmalloc(v_urb_len, GFP_KERNEL);
1287:			if (usb->video_urbs[i]->transfer_buffer == NULL)
1288:				goto allocfail;
1289:			usb_fill_bulk_urb(usb->video_urbs[i], usb->usbdev, video_pipe,
1290:					usb->video_urbs[i]->transfer_buffer, v_urb_len,
1291:					go7007_usb_read_video_pipe_complete, go);
1292:		}
1293:	
1294:		/* Allocate the URBs and buffers for receiving the audio stream */
1295:		if ((board->flags & GO7007_USB_EZUSB) &&
1296:		    (board->main_info.flags & GO7007_BOARD_HAS_AUDIO)) {
1297:			if (!usb->usbdev->ep_in[8])
1298:				goto allocfail;
1299:			for (i = 0; i < 8; ++i) {
1300:				usb->audio_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
1301:				if (usb->audio_urbs[i] == NULL)
1302:					goto allocfail;
1303:				usb->audio_urbs[i]->transfer_buffer = kmalloc(4096,
1304:									GFP_KERNEL);
1305:				if (usb->audio_urbs[i]->transfer_buffer == NULL)
1306:					goto allocfail;
1307:				usb_fill_bulk_urb(usb->audio_urbs[i], usb->usbdev,
1308:					usb_rcvbulkpipe(usb->usbdev, 8),
1309:					usb->audio_urbs[i]->transfer_buffer, 4096,
1310:					go7007_usb_read_audio_pipe_complete, go);
1311:			}
1312:		}
1313:	
1314:		/* Do any final GO7007 initialization, then register the
1315:		 * V4L2 and ALSA interfaces */
1316:		if (go7007_register_encoder(go, num_i2c_devs) < 0)
1317:			goto allocfail;
1318:	
1319:		go->status = STATUS_ONLINE;
1320:		return 0;
1321:	
1322:	allocfail:
1323:		go7007_usb_release(go);
1324:		kfree(go);
1325:		return -ENOMEM;
1326:	}
 SourceFile:drivers/media/usb/go7007/go7007-usb.c]

506/2 2026/07/30 13:36 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 61998
							output: 54
							thoughts: 118
						

Thoughts:
**Analyzing the GO7007 USB Probe Function**

Okay, let's break this down. My initial observation is that `go7007_usb_probe` is adding the I2C adapter using `i2c_add_adapter(&go->i2c_adapter)` around line 1172. That's a key part of the device setup. Now, I see that right after that, at line 1271, we have a crucial check: `if (!usb->usbdev->ep_in[6]) goto allocfail;`. Essentially, we're verifying the existence of the input endpoint. If that check fails, the code jumps to `allocfail`.

And if we hit `allocfail`, the function calls `go7007_usb_release(go)` *and* `kfree(go)`. The driver's cleaning up its resources, which is sensible. Before I continue, I really should examine what is happening inside `go7007_usb_release`, to ensure the teardown is properly handled.



507/2 2026/07/30 13:36 tool codesearch-definition-source
0m Args:
map[ContextFile:drivers/media/usb/go7007/go7007-usb.c Name:go7007_usb_release]

Results:
map[SourceCode: 896:	static void go7007_usb_release(struct go7007 *go)
 897:	{
 898:		struct go7007_usb *usb = go->hpi_context;
 899:		struct urb *vurb, *aurb;
 900:		int i;
 901:	
 902:		if (usb->intr_urb) {
 903:			usb_kill_urb(usb->intr_urb);
 904:			kfree(usb->intr_urb->transfer_buffer);
 905:			usb_free_urb(usb->intr_urb);
 906:		}
 907:	
 908:		/* Free USB-related structs */
 909:		for (i = 0; i < 8; ++i) {
 910:			vurb = usb->video_urbs[i];
 911:			if (vurb) {
 912:				usb_kill_urb(vurb);
 913:				kfree(vurb->transfer_buffer);
 914:				usb_free_urb(vurb);
 915:			}
 916:			aurb = usb->audio_urbs[i];
 917:			if (aurb) {
 918:				usb_kill_urb(aurb);
 919:				kfree(aurb->transfer_buffer);
 920:				usb_free_urb(aurb);
 921:			}
 922:		}
 923:	
 924:		kfree(go->hpi_context);
 925:	}
 SourceFile:drivers/media/usb/go7007/go7007-usb.c]

508/2 2026/07/30 13:36 llm crash-repro-finder
0m Model:
gemini-3.1-pro-preview

Tokens:
							input: 62882
							output: 54
							thoughts: 288
						

Thoughts:
**The Eureka Moment!**

Yes! I've got it! The `go7007_usb_release` function *doesn't* call `i2c_del_adapter`! It just frees the URBs and the `go->hpi_context`. And then, right after, `go7007_usb_probe` goes and calls `kfree(go)`! The crucial thing is that `go->i2c_adapter` is *embedded* within the `struct go7007` itself! Meaning it's being freed while still registered in the I2C subsystem! That's the bug, plain and simple!

Now, why didn't my reproducer hit this consistently? I need to understand that. Let's look at `go7007_boot_encoder`. That's called *before* `i2c_add_adapter`, isn't it?

```c
/* Boot the GO7007 */
if (go7007_boot_encoder(go, go->board_info->flags &
				GO7007_BOARD_USE_ONBOARD_I2C) < 0)
    goto allocfail;
```

Ah, here we go! If `go7007_boot_encoder` fails, the code jumps to `allocfail` *before* `i2c_add_adapter` gets called! Therefore, to trigger the bug, we *must* ensure that `go7007_boot_encoder` succeeds. I need to dive deeper into `go7007_boot_encoder` now, and understand what conditions might cause it to fail. That's the key to reliable reproduction!



509/2 2026/07/30 13:36 tool codesearch-definition-source
0m Args:
map[ContextFile:drivers/media/usb/go7007/go7007-driver.c Name:go7007_boot_encoder]

Results:
map[SourceCode: 121:	/*
 122:	 * Boot the encoder and register the I2C adapter if requested.  Do the
 123:	 * minimum initialization necessary, since the board-specific code may
 124:	 * still need to probe the board ID.
 125:	 *
 126:	 * Must NOT be called with the hw_lock held.
 127:	 */
 128:	int go7007_boot_encoder(struct go7007 *go, int init_i2c)
 129:	{
 130:		int ret;
 131:	
 132:		mutex_lock(&go->hw_lock);
 133:		ret = go7007_load_encoder(go);
 134:		mutex_unlock(&go->hw_lock);
 135:		if (ret < 0)
 136:			return -1;
 137:		if (!init_i2c)
 138:			return 0;
 139:		if (go7007_i2c_init(go) < 0)
 140:			return -1;
 141:		go->i2c_adapter_online = 1;
 142:		return 0;
 143:	}
 SourceFile:drivers/media/usb/go7007/go7007-driver.c]

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)