/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
 *
 * Copyright (C) 2015 Richard Hughes <richard@hughsie.com>
 *
 * Licensed under the GNU General Public License Version 2
 *
 * 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 of the License, 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; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef OSP_ENUM_H
#define OSP_ENUM_H

#include <glib.h>
#include <gusb.h>

G_BEGIN_DECLS

#define	OSP_USB_VID			0x2457
#define	OSP_USB_PID			0x4200

typedef enum {
	OSP_HEADER_FLAG_NONE		= 0,
	OSP_HEADER_FLAG_RESPONSE	= 1 << 0,	/* set by device */
	OSP_HEADER_FLAG_ACK		= 1 << 1,	/* set by device */
	OSP_HEADER_FLAG_ACK_REQUIRED	= 1 << 2,	/* set by host */
	OSP_HEADER_FLAG_NACK		= 1 << 3,	/* set by device */
	OSP_HEADER_FLAG_ERROR		= 1 << 4,	/* set by device */
	OSP_HEADER_FLAG_DEPRECATED	= 1 << 5,	/* set by device */
	/*< private >*/
	OSP_HEADER_FLAG_LAST
} OspHeaderFlag;

typedef enum {
	OSP_ERROR_CODE_SUCCESS			= 0,
	OSP_ERROR_CODE_UNSUPPORTED_PROTOCOL	= 1,
	OSP_ERROR_CODE_UNKNOWN_MESSAGE_TYPE	= 2,
	OSP_ERROR_CODE_BAD_CHECKSUM		= 3,
	OSP_ERROR_CODE_MESSAGE_TOO_LARGE	= 4,
	OSP_ERROR_CODE_PAYLOAD_LENGTH_INVALID	= 5,
	OSP_ERROR_CODE_PAYLOAD_DATA_INVALID	= 6,
	OSP_ERROR_CODE_DEVICE_NOT_READY		= 7,
	OSP_ERROR_CODE_UNKNOWN_CHECKSUM_TYPE	= 8,
	OSP_ERROR_CODE_DEVICE_RESET		= 9,
	OSP_ERROR_CODE_TOO_MANY_BUSES		= 10,
	OSP_ERROR_CODE_OUT_OF_MEMORY		= 11,
	OSP_ERROR_CODE_COMMAND_DATA_MISSING	= 12,
	OSP_ERROR_CODE_INTERNAL_ERROR		= 13,
	OSP_ERROR_CODE_COULD_NOT_DECRYPT	= 100,
	OSP_ERROR_CODE_FIRMWARE_LAYOUT_INVALID	= 101,
	OSP_ERROR_CODE_DATA_PACKET_INVALID_SIZE	= 102,
	OSP_ERROR_CODE_HW_REVISION_INVALID	= 103,
	OSP_ERROR_CODE_FLASH_MAP_INVALID	= 104,
	OSP_ERROR_CODE_RESPONSE_DEFERRED	= 255,
	/*< private >*/
	OSP_ERROR_CODE_LAST,
} OspErrorCode;

typedef enum {
	OSP_HEADER_CHECKSUM_KIND_NONE		= 0,
	OSP_HEADER_CHECKSUM_KIND_MD5		= 1,
	/*< private >*/
	OSP_HEADER_CHECKSUM_KIND_LAST
} OspHeaderChecksumKind;

typedef enum {
	OSP_CMD_RESET						= 0x00000000,
	OSP_CMD_RESET_TO_DEFAULTS				= 0x00000001,
	OSP_CMD_GET_HARDWARE_VERSION				= 0x00000080,
	OSP_CMD_GET_FIRMWARE_VERSION				= 0x00000090,
	OSP_CMD_GET_SERIAL_NUMBER				= 0x00000100,
	OSP_CMD_GET_SERIAL_NUMBER_LENGTH			= 0x00000101,
	OSP_CMD_GET_DEVICE_ALIAS				= 0x00000200,
	OSP_CMD_GET_DEVICE_ALIAS_LENGTH				= 0x00000201,
	OSP_CMD_SET_DEVICE_ALIAS				= 0x00000210,
	OSP_CMD_GET_NUMBER_OF_AVAILABLE_USER_STRINGS		= 0x00000300,
	OSP_CMD_GET_USER_STRING_LENGTH				= 0x00000301,
	OSP_CMD_GET_USER_STRING					= 0x00000302,
	OSP_CMD_SET_USER_STRING					= 0x00000310,
	OSP_CMD_SET_LED						= 0x00001010,
	OSP_CMD_PUT_DEVICE_IN_REPROGRAMMING_MODE		= 0x000fff00,
	OSP_CMD_GET_AND_SEND_CORRECTED_SPECTRUM			= 0x00101000,
	OSP_CMD_GET_AND_SEND_RAW_SPECTRUM			= 0x00101100,
	OSP_CMD_GET_PARTIAL_SPECTRUM_MODE			= 0x00102000,
	OSP_CMD_SET_PARTIAL_SPECTRUM_MODE			= 0x00102010,
	OSP_CMD_GET_AND_SEND_PARTIAL_CORRECTED_SPECTRUM		= 0x00102080,
	OSP_CMD_SET_INTEGRATION_TIME				= 0x00110010,
	OSP_CMD_GET_PIXEL_BINNING_FACTOR			= 0x00110280,
	OSP_CMD_GET_MAXIMUM_BINNING_FACTOR			= 0x00110281,
	OSP_CMD_GET_DEFAULT_BINNING_FACTOR			= 0x00110285,
	OSP_CMD_SET_PIXEL_BINNING_FACTOR			= 0x00110290,
	OSP_CMD_SET_DEFAULT_BINNING_FACTOR			= 0x00110295,
	OSP_CMD_SET_TRIGGER_DELAY_MS				= 0x00110510,
	OSP_CMD_GET_SCANS_TO_AVERAGE				= 0x00120000,
	OSP_CMD_SET_SCANS_TO_AVERAGE				= 0x00120010,
	OSP_CMD_GET_BOXCAR_WIDTH				= 0x00121000,
	OSP_CMD_SET_BOXCAR_WIDTH				= 0x00121010,
	OSP_CMD_GET_WAVELENGTH_COEFFICIENT_COUNT		= 0x00180100,
	OSP_CMD_GET_WAVELENGTH_COEFFICIENT			= 0x00180101,
	OSP_CMD_SET_WAVELENGTH_COEFFICIENT			= 0x00180111,
	OSP_CMD_GET_NONLINEARITY_COEFFICIENT_COUNT		= 0x00181100,
	OSP_CMD_GET_NONLINEARITY_COEFFICIENT			= 0x00181101,
	OSP_CMD_SET_NONLINEARITY_COEFFICIENT			= 0x00181111,
	OSP_CMD_GET_IRRADIANCE_CALIBRATION			= 0x00182001,
	OSP_CMD_GET_IRRADIANCE_CALIBRATION_COUNT		= 0x00182002,
	OSP_CMD_GET_IRRADIANCE_CALIBRATION_COLLECTION_AREA	= 0x00182003,
	OSP_CMD_SET_IRRADIANCE_CALIBRATION			= 0x00182011,
	OSP_CMD_SET_IRRADIANCE_CALIBRATION_COLLECTION_AREA	= 0x00182013,
	OSP_CMD_GET_NUMBER_OF_STRAY_LIGHT_COEFFICIENTS		= 0x00183100,
	OSP_CMD_GET_STRAY_LIGHT_COEFFICIENT			= 0x00183101,
	OSP_CMD_SET_STRAY_LIGHT_COEFFICIENT			= 0x00183111,
	OSP_CMD_GET_HOT_PIXEL_INDICES				= 0x00186000,
	OSP_CMD_SET_HOT_PIXEL_INDICES				= 0x00186010,
	OSP_CMD_GET_BENCH_ID					= 0x001b0000,
	OSP_CMD_GET_BENCH_SERIAL_NUMBER				= 0x001b0100,
	OSP_CMD_GET_SLIT_WIDTH_MICRONS				= 0x001b0200,
	OSP_CMD_GET_FIBER_DIAMETER_MICRONS			= 0x001b0300,
	OSP_CMD_GET_GRATING					= 0x001b0400,
	OSP_CMD_GET_FILTER					= 0x001b0500,
	OSP_CMD_GET_COATING					= 0x001b0600,
	OSP_CMD_GET_GET_TEMPERATURE_SENSOR_COUNT		= 0x00400000,
	OSP_CMD_GET_READ_TEMPERATURE_SENSOR			= 0x00400001,
	OSP_CMD_GET_READ_ALL_TEMPERATURE_SENSORS		= 0x00400002,
	/*< private >*/
	OSP_CMD_LAST
} OspCmd;

typedef struct {
    guint16	 start_bytes;
    guint16	 protocol_version;
    guint16	 flags;
    guint16	 error_code;
    guint32	 message_type;
    guint32	 regarding;
    guint8	 reserved[6];
    guint8	 checksum_type;
    guint8	 immediate_data_length;
    guint8	 immediate_data[16];
    guint32	 bytes_remaining;
} OspProtocolHeader;

typedef struct {
    guint8	 checksum[16];
    guint32	 end_bytes;
} OspProtocolFooter;

const gchar	*osp_error_code_to_string	(OspErrorCode	 error_code);
const gchar	*osp_cmd_to_string		(OspCmd		 cmd);

G_END_DECLS

#endif
