/*
 * FaceAuth Firmware
 *
 * Copyright (C) 2019 Google, Inc.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * 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.
 */

#ifndef __FACEAUTH_SHARED_H__
#define __FACEAUTH_SHARED_H__

/* input image sizes */
#define INPUT_IMAGE_WIDTH 480
#define INPUT_IMAGE_HEIGHT 640
#define INPUT_IMAGE_SIZE (INPUT_IMAGE_WIDTH * INPUT_IMAGE_HEIGHT)

/* Feature Flags - bug: 123535349 */
#define DISABLE_GAZE_DEPRECATED                 (1ULL << 0) //bit 0
#define SECURE_CAMERA_DATA                      (1ULL << 2) //bit 2
#define REQUIRE_ATTENTION                       (1ULL << 3) //bit 3

/* Keep temporary feature bits in the top part of the field */

#define MAX_CACHE_ENROLLMENT 1536

/* TODO (masterwilliams) change max enrollments to 21
 * once it is changed in citadel */
#define MAX_ENROLLMENT 20
#define MAX_NUM_USERS 4

/*  The error codes are broken up into functional groups with space reserve for
 *  future error codes. The divisions are as follows:
 *  0     - success
 *  1     - general error (debug only, never used)
 *  2-31  - TPU device driver errors (inherrited from the TPU driver)
 *  32-47 - Errors returned from the citadel chip
 *  48-63 - Errors returned form the M0 citadel code
 *  64-83   - TPU/IPU model errors and M0 processing errors
 *  84-90   - M0 errors
 */
#define ERROR_NO_ERROR 0
#define ERROR_GENERAL_ERROR -1

#define ERROR_INTERNAL_CITADEL_INVALID_ARGS -32
#define ERROR_INTERNAL_CITADEL_TIMEOUT -33
#define ERROR_INTERNAL_CITADEL_SFS_FULL -34
#define ERROR_INTERNAL_CITADEL_SFS_INTERNAL -35
#define ERROR_INTERNAL_CITADEL_ERR_THROTTLE -36
#define ERROR_INTERNAL_CITADEL_SESSION_ID -37
#define ERROR_INTERNAL_CITADEL_CRC -38
#define ERROR_INTERNAL_CITADEL_NONSECURE_MODE -39
#define ERROR_INTERNAL_CITADEL_INVALID_TOKEN -40
#define ERROR_INTERNAL_CITADEL_RECALIBRATE -41
#define ERROR_INTERNAL_CITADEL_VERSION -42
#define ERROR_INTERNAL_CITADEL_ERR_UNKNOWN -43
#define ERROR_INTERNAL_CITADEL_INVALID_CHALLENGE -44
#define ERROR_INTERNAL_CITADEL_INVALID_USER_ID -45
#define ERROR_INTERNAL_CITADEL_EMBEDDING_VERSION -46
#define ERROR_INTERNAL_CITADEL_EMBEDDING_DOWNGRADE -47

/* errors generated by the M0 citadel code */
#define ERROR_CITADEL_INVALID_ARGS -48
#define ERROR_CITADEL_TIMEOUT -49
#define ERROR_CITADEL_CACHE_FULL -50
#define ERROR_CITADEL_CACHE_INVALID_INDEX -51
#define ERROR_CITADEL_INVALID_PROFILE -52
#define ERROR_CITADEL_EARLY_FAIL -53
#define ERROR_CITADEL_SESSION_ID -54
#define ERROR_CITADEL_CRC -55
#define ERROR_CITADEL_UNSUPPORTED -56
#define ERROR_INTERNAL_CITADEL_CHALLENGE_EXPIRED -57
#define ERROR_INTERNAL_CITADEL_WIPED_USER -58
#define ERROR_INTERNAL_CITADEL_INVALID_FACENET -59
#define ERROR_INTERNAL_CITADEL_INVALID_DEPTHID -60

#define ERROR_DEPTH_IPU_TIMEOUT -64
#define ERROR_SKIN_INVALID_LAYER_SIZE -65
#define ERROR_FSSD_BUFFER_SIZE_MISMATCH -66
#define ERROR_SKIN_INVALID_PATCH_SIZE -67
#define ERROR_SKIN_INVALID_FACE_SIZE -68
#define ERROR_DOWNSCALE_IPU_TIMEOUT -69
#define ERROR_AFFINE_COMBINED_IPU_TIMEOUT -70
#define ERROR_FACENET_BUFFER_SIZE_MISMATCH -71
#define ERROR_DEPTHID_BUFFER_SIZE_MISMATCH -72
#define ERROR_GAZENET_BUFFER_SIZE_MISMATCH -73
#define ERROR_SKIN_BUFFER_SIZE_MISMATCH -74
#define ERROR_MAX_THRESHOLD_FACES -75
/* TODO (masterwilliams) b/126613551 */
#define ERROR_INSUFFICIENT_ALLOCATOR_MEMORY -76
#define ERROR_IPU_TIMEOUT -77
#define ERROR_REJECT_USERS_FULL -78
#define ERROR_REJECT_PROFILES_FULL -79
#define ERROR_REJECT_MAX_PROFILES_PER_USER -80
#define ERROR_UNSUPPORTED_COMMAND -81

#define ERROR_FW_DRIVER_SYNC_ERROR -84
#define ERROR_UNEXPECTED_COMMAND -85

#define CMD_IS_VALID(cmd) ((cmd) < COMMAND_COUNT)

/* Any change to the WorkloadStatus should also be accompanied by a change to
 * WORKLOAD_STATUS_STRINGS in defines.h.
 */
typedef enum _workload_status {
	WORKLOAD_STATUS_NO_STATUS = 0,
	WORKLOAD_STATUS_PASS,

	/* Soft errors */
	/* Reject (post)FSSD code when no face is found */
	WORKLOAD_STATUS_REJECT_NO_FACE,
	/* Reject (post)FDDS code when number of faces is more than capacity */
	WORKLOAD_STATUS_REJECT_MAX_FACE_CAPACITY,
	/* Reject Gazenet for no camera attention, optionally can be ignored */
	WORKLOAD_STATUS_REJECT_NO_ATTENTION,
	/* Reject Face Check when the face bounding box is too small */
	WORKLOAD_STATUS_REJECT_TOO_SMALL,
	/* Reject Face Check when the face is clipped on the left side */
	WORKLOAD_STATUS_REJECT_CLIPPED_LEFT,
	/* Reject Face Check when the face is clipped on the right side */
	WORKLOAD_STATUS_REJECT_CLIPPED_RIGHT,
	/* Reject Face Check when the face is clipped on the top */
	WORKLOAD_STATUS_REJECT_CLIPPED_TOP,
	/* Reject Face Check when the face is clipped on the bottom */
	WORKLOAD_STATUS_REJECT_CLIPPED_BOTTOM,
	/* Reject Face Check when the flood image is too dark */
	WORKLOAD_STATUS_REJECT_TOO_DARK,
	/* Reject Face Check when the flood image is too bright */
	WORKLOAD_STATUS_REJECT_TOO_BRIGHT,
	/* Reject Face Check when the face tilt angle is too extreme */
	WORKLOAD_STATUS_REJECT_TILT_ANGLE,
	/* Reject Face Check when the face pan angle is too extreme */
	WORKLOAD_STATUS_REJECT_PAN_ANGLE,
	/* Reject depth when the face is too close */
	WORKLOAD_STATUS_REJECT_TOO_CLOSE,
	/* Reject depth when the face is too far */
	WORKLOAD_STATUS_REJECT_TOO_FAR,
	/* Reject enrollment due to max users enrolled */
	WORKLOAD_STATUS_REJECT_USERS_FULL,
	/* Reject enrollment/migration due to no additional free profiles */
	WORKLOAD_STATUS_REJECT_PROFILES_FULL,
	/* Reject an invalid depth thumbnail (bad calibration or a smudge) */
	WORKLOAD_STATUS_REJECT_INVALID_DEPTH,

	/* hard errors - these should be squashed into a single status in
	 * GetCumulativeStatus() */
	/* Reject Skin */
	WORKLOAD_STATUS_REJECT_SKIN,
	/* Reject depth id spoof */
	WORKLOAD_STATUS_REJECT_SPOOF,
	WORKLOAD_STATUS_HARD_REJECT,

	/* fatal error */
	WORKLOAD_STATUS_ERROR,

	/* Soft error */
	WORKLOAD_STATUS_REJECT_FRAME_SELECTION,

	WORKLOAD_STATUS_COUNT,
	WORKLOAD_STATUS_INTMAX =
		0xffffffff /* used to extend enum size to 4 bytes */
} WorkloadStatus;

/* The set of commands accepted by faceauth FW
 * Needs to be kept in sync with WORKLOAD_STATE_STRINGS in define.h
 */
typedef enum _faceauth_input_commands {
	COMMAND_NONE = 0,
	COMMAND_ENROLL,
	COMMAND_ENROLL_COMPLETE,
	COMMAND_ERASE,
	COMMAND_VALIDATE,
	COMMAND_EXIT,
	COMMAND_GET_CHALLENGE,
	COMMAND_REVOKE_CHALLENGE,
	COMMAND_GET_USER_INFO,
	COMMAND_SET_FEATURE,
	COMMAND_CLR_FEATURE,
	COMMAND_RESET_LOCKOUT,
	COMMAND_MIGRATE,
	// EL2 should filter this command so it can't be sent from userspace
	COMMAND_EXIT_DIRTY,
	COMMAND_VERIFY_HAT,

	COMMAND_COUNT,
	/* used to extend enum size to 4 bytes */
	COMMAND_INTMAX =
		0xffffffff /* used to extend enum size to 4 bytes */
} FaceAuthInputCommands;

#define IS_IMAGE_PROCESSING_CMD(cmd) ((cmd) == COMMAND_ENROLL || \
				      (cmd) == COMMAND_VALIDATE || \
				      (cmd) == COMMAND_MIGRATE)

typedef enum _faceauth_ack_messages {
	STATUS_NONE = 0,
	STATUS_READY,
	STATUS_BUSY,
	STATUS_CLEAN,
	STATUS_INTMAX =
		0xffffffff /* used to extend enum size to 4 bytes */
} FaceAckMessages;

/* Definitions needed to interpret debug data */

struct Coordinate {
	int32_t x;
	int32_t y;
} __attribute__((packed));

struct BoundingBox {
	/* These coordinates are in integer format */
	struct Coordinate top_left;
	struct Coordinate bottom_right;
} __attribute__((packed));

struct BoundingBoxes {
	struct BoundingBox right_box;
	struct BoundingBox left_box;
} __attribute__((packed));

enum FaceLandmarks {
	LEFT_EYE = 0,
	RIGHT_EYE,
	NOSE_TIP,
	MOUTH_CENTER,
	LEFT_EAR_TRAGION,
	RIGHT_EAR_TRAGION,
	NUM_FACE_LANDMARKS,
	FACE_LANDMARK_INTMAX =
		0xffffffff /* used to extend enum size to 4 bytes */
};

struct Face {
	/* In whole pixels */
	int32_t x1;
	int32_t y1;
	int32_t x2;
	int32_t y2;
	/* Fixed point 16.16 */
	struct Coordinate landmark[NUM_FACE_LANDMARKS];
	uint32_t confidence;
	int32_t pan_angle;
	int32_t tilt_angle;
	int32_t roll_angle;
} __attribute__((packed));

struct SerialVerificationToken {
	uint64_t challenge;
	uint64_t timestamp;
	uint32_t security_level;
	uint8_t mac[32];
} __attribute__((packed));

#endif /* __FACEAUTH_SHARED_H__ */
