The USB specification includes a section on Human Interface Devices (HID). These devices range from keyboards, mice, joysticks, audio controls to medical controls, eye tracking and LED lighting. CircuitPython has support for USB HID with built-in defaults for a keyboard, mouse and consumer control and associated libraries. Dan Halbert has an excellent guide to get started with this.
A USB report descriptor tells the host machine the how to talk to your device. But what if you want to communicate to a device that no one else has written a report descriptor for? Perhaps you are building a new joystick, LED indicator or medical ultrasound device. Then you will have to write your own report descriptor.
Initially when you look at report desciptors they seem complicated but it is best to think of them as a description of one or more reports that can be sent to or from your device. Each report gives the current state you wish to communicate. For example a joystick report may give the X and Y axis, a throttle value and if any of a dozen buttons are pressed. The joystick may also have a second report defined that allows the host machine to light up one or more indicator lights.
Because of the breadth of possibilities the USB HID specification is large. The area you will be most interested in is the HID Usage Tables. HID usages cover the items in your device from the generic to the detailed elements and give you the assigned usage IDs that are used.
Following those documents you can make your own descriptor by hand. But it will be tedious. Luckily there is a collection of Microsoft HID Tools. The only tool currently available is called Waratah which will take a report descriptor in TOML format and automatically convert it to the hex you need to pass to the USB HID host.