/*
 * Copyright 2012-2022 Great Scott Gadgets <info@greatscottgadgets.com>
 * Copyright 2012 Jared Boone
 *
 * This file is part of HackRF.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 */

#include <stdint.h>

#include "usb_type.h"
#include "usb_descriptor.h"

#define USB_VENDOR_ID (0x1D50)

#if (defined HACKRF_ONE || defined PRALINE)
	#define USB_PRODUCT_ID (0x6089)
#elif JAWBREAKER
	#define USB_PRODUCT_ID (0x604B)
#elif RAD1O
	#define USB_PRODUCT_ID (0xCC15)
#else
	#define USB_PRODUCT_ID (0xFFFF)
#endif

#define USB_API_VERSION (0x0110)

#define USB_WORD(x) (x & 0xFF), ((x >> 8) & 0xFF)

#define USB_MAX_PACKET0        (64)
#define USB_MAX_PACKET_BULK_FS (64)
#define USB_MAX_PACKET_BULK_HS (512)

#define USB_BULK_IN_EP_ADDR  (0x81)
#define USB_BULK_OUT_EP_ADDR (0x02)

#define USB_STRING_LANGID (0x0409)

uint8_t usb_descriptor_device[] = {
	18,                         // bLength
	USB_DESCRIPTOR_TYPE_DEVICE, // bDescriptorType
	USB_WORD(0x0200),           // bcdUSB
	0x00,                       // bDeviceClass
	0x00,                       // bDeviceSubClass
	0x00,                       // bDeviceProtocol
	USB_MAX_PACKET0,            // bMaxPacketSize0
	USB_WORD(USB_VENDOR_ID),    // idVendor
	USB_WORD(USB_PRODUCT_ID),   // idProduct
	USB_WORD(USB_API_VERSION),  // bcdDevice
	0x01,                       // iManufacturer
	0x02,                       // iProduct
	0x04,                       // iSerialNumber
	0x01                        // bNumConfigurations
};

uint8_t usb_descriptor_device_qualifier[] = {
	10,                                   // bLength
	USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, // bDescriptorType
	USB_WORD(0x0200),                     // bcdUSB
	0x00,                                 // bDeviceClass
	0x00,                                 // bDeviceSubClass
	0x00,                                 // bDeviceProtocol
	64,                                   // bMaxPacketSize0
	0x01,                                 // bNumOtherSpeedConfigurations
	0x00                                  // bReserved
};

uint8_t usb_descriptor_configuration_full_speed[] = {
	9,                                 // bLength
	USB_DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType
	USB_WORD(32),                      // wTotalLength
	0x01,                              // bNumInterfaces
	0x01,                              // bConfigurationValue
	0x03,                              // iConfiguration
	0x80,                              // bmAttributes: USB-powered
	250,                               // bMaxPower: 500mA

	9,                             // bLength
	USB_DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType
	0x00,                          // bInterfaceNumber
	0x00,                          // bAlternateSetting
	0x02,                          // bNumEndpoints
	0xFF,                          // bInterfaceClass: vendor-specific
	0xFF,                          // bInterfaceSubClass
	0xFF,                          // bInterfaceProtocol: vendor-specific
	0x00,                          // iInterface

	7,                                // bLength
	USB_DESCRIPTOR_TYPE_ENDPOINT,     // bDescriptorType
	USB_BULK_IN_EP_ADDR,              // bEndpointAddress
	0x02,                             // bmAttributes: BULK
	USB_WORD(USB_MAX_PACKET_BULK_FS), // wMaxPacketSize
	0x00,                             // bInterval: no NAK

	7,                                // bLength
	USB_DESCRIPTOR_TYPE_ENDPOINT,     // bDescriptorType
	USB_BULK_OUT_EP_ADDR,             // bEndpointAddress
	0x02,                             // bmAttributes: BULK
	USB_WORD(USB_MAX_PACKET_BULK_FS), // wMaxPacketSize
	0x00,                             // bInterval: no NAK

	0, // TERMINATOR
};

uint8_t usb_descriptor_configuration_high_speed[] = {
	9,                                 // bLength
	USB_DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType
	USB_WORD(32),                      // wTotalLength
	0x01,                              // bNumInterfaces
	0x01,                              // bConfigurationValue
	0x03,                              // iConfiguration
	0x80,                              // bmAttributes: USB-powered
	250,                               // bMaxPower: 500mA

	9,                             // bLength
	USB_DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType
	0x00,                          // bInterfaceNumber
	0x00,                          // bAlternateSetting
	0x02,                          // bNumEndpoints
	0xFF,                          // bInterfaceClass: vendor-specific
	0xFF,                          // bInterfaceSubClass
	0xFF,                          // bInterfaceProtocol: vendor-specific
	0x00,                          // iInterface

	7,                                // bLength
	USB_DESCRIPTOR_TYPE_ENDPOINT,     // bDescriptorType
	USB_BULK_IN_EP_ADDR,              // bEndpointAddress
	0x02,                             // bmAttributes: BULK
	USB_WORD(USB_MAX_PACKET_BULK_HS), // wMaxPacketSize
	0x00,                             // bInterval: no NAK

	7,                                // bLength
	USB_DESCRIPTOR_TYPE_ENDPOINT,     // bDescriptorType
	USB_BULK_OUT_EP_ADDR,             // bEndpointAddress
	0x02,                             // bmAttributes: BULK
	USB_WORD(USB_MAX_PACKET_BULK_HS), // wMaxPacketSize
	0x00,                             // bInterval: no NAK

	0, // TERMINATOR
};

uint8_t usb_descriptor_string_languages[] = {
	0x04,                        // bLength
	USB_DESCRIPTOR_TYPE_STRING,  // bDescriptorType
	USB_WORD(USB_STRING_LANGID), // wLANGID
};

// clang-format off
uint8_t usb_descriptor_string_manufacturer[] = {
	40,                         // bLength
	USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
	'G', 0x00,
	'r', 0x00,
	'e', 0x00,
	'a', 0x00,
	't', 0x00,
	' ', 0x00,
	'S', 0x00,
	'c', 0x00,
	'o', 0x00,
	't', 0x00,
	't', 0x00,
	' ', 0x00,
	'G', 0x00,
	'a', 0x00,
	'd', 0x00,
	'g', 0x00,
	'e', 0x00,
	't', 0x00,
	's', 0x00,
};

uint8_t usb_descriptor_string_product[] = {
#ifdef HACKRF_ONE
	22,                         // bLength
	USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
	'H', 0x00,
	'a', 0x00,
	'c', 0x00,
	'k', 0x00,
	'R', 0x00,
	'F', 0x00,
	' ', 0x00,
	'O', 0x00,
	'n', 0x00,
	'e', 0x00,
#elif JAWBREAKER
	36,                         // bLength
	USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
	'H', 0x00,
	'a', 0x00,
	'c', 0x00,
	'k', 0x00,
	'R', 0x00,
	'F', 0x00,
	' ', 0x00,
	'J', 0x00,
	'a', 0x00,
	'w', 0x00,
	'b', 0x00,
	'r', 0x00,
	'e', 0x00,
	'a', 0x00,
	'k', 0x00,
	'e', 0x00,
	'r', 0x00,
#elif RAD1O
	12,                         // bLength
	USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
	'r', 0x00,
	'a', 0x00,
	'd', 0x00,
	'1', 0x00,
	'o', 0x00,
#elif PRALINE
	22,                         // bLength
	USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
	'H', 0x00,
	'a', 0x00,
	'c', 0x00,
	'k', 0x00,
	'R', 0x00,
	'F', 0x00,
	' ', 0x00,
	'P', 0x00,
	'r', 0x00,
	'o', 0x00,
#else
	14,                         // bLength
	USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
	'H', 0x00,
	'a', 0x00,
	'c', 0x00,
	'k', 0x00,
	'R', 0x00,
	'F', 0x00,
#endif
};

uint8_t usb_descriptor_string_config_description[] = {
	24,                         // bLength
	USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
	'T', 0x00,
	'r', 0x00,
	'a', 0x00,
	'n', 0x00,
	's', 0x00,
	'c', 0x00,
	'e', 0x00,
	'i', 0x00,
	'v', 0x00,
	'e', 0x00,
	'r', 0x00,
};

#ifdef DFU_MODE
uint8_t usb_descriptor_string_serial_number[] = {
	30,                         // bLength
	USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
	'R', 0x00,
	'u', 0x00,
	'n', 0x00,
	'n', 0x00,
	'i', 0x00,
	'n', 0x00,
	'g', 0x00,
	'F', 0x00,
	'r', 0x00,
	'o', 0x00,
	'm', 0x00,
	'R', 0x00,
	'A', 0x00,
	'M', 0x00,
};
#else
uint8_t usb_descriptor_string_serial_number[USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN];
#endif

uint8_t* usb_descriptor_strings[] = {
	usb_descriptor_string_languages,
	usb_descriptor_string_manufacturer,
	usb_descriptor_string_product,
	usb_descriptor_string_config_description,
	usb_descriptor_string_serial_number,
	0, // TERMINATOR
};

uint8_t wcid_string_descriptor[] = {
	18,                          // bLength
	USB_DESCRIPTOR_TYPE_STRING,  // bDescriptorType
	'M', 0x00,
	'S', 0x00,
	'F', 0x00,
	'T', 0x00,
	'1', 0x00,
	'0', 0x00,
	'0', 0x00,
	USB_WCID_VENDOR_REQ, // vendor request code for further descriptor
	0x00
};

uint8_t wcid_feature_descriptor[] = {
	0x28, 0x00, 0x00, 0x00,                  // bLength
	USB_WORD(0x0100),                        // WCID version
	USB_WORD(0x0004),                        // WICD descriptor index
	0x01,                                    // bNumSections
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,      // Reserved
	0x00,                                    // bInterfaceNumber
	0x01,                                    // Reserved
	'W', 'I', 'N', 'U', 'S', 'B', 0x00,0x00, // Compatible ID, padded with zeros
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Sub-compatible ID
	0x00,0x00,0x00,0x00,0x00,0x00            // Reserved
};
