/* SPDX-License-Identifier: LGPL-2.1-only OR BSD-3-Clause */
/******************************************************************************
 *
 * This file is provided under a dual license.  When you use or
 * distribute this software, you may choose to be licensed under
 * version 2.1 of the GNU Lesser General Public License
 * ("LGPLv2.1 License") or BSD License.
 *
 * LGPLv2.1 License
 *
 * Copyright(C) 2019 MediaTek Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2.1 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * 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 https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html for more
 * details.
 *
 * BSD LICENSE
 *
 * Copyright(C) 2019 MediaTek Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *****************************************************************************/

#ifndef _X_ODD_DEV_H_
#define _X_ODD_DEV_H_

#include "x_common.h"

/*! The status type used by ODD device to notify middleware.
 *! - When the tray of ODD is moving, there are five kinds of status:
 *!   - When the tray is completely opened,
 *!     notifies ODD_STATUS_TRAY_OPEN.
 *!   - When the tray is completely closed,
 *!     notifies ODD_STATUS_TRAY_CLOSE.
 *!   - When the tray is in opening process,
 *!     notifies ODD_STATUS_TRAY_OPENING.
 *!   - When the tray is in closing process,
 *!     notifies ODD_STATUS_TRAY_CLOSING.
 *!   - When the tray is blocked or out of order,
 *!     notifies ODD_STATUS_TRAY_ERROR.
 *!
 *! - Once the tray is completely closed and ODD device will detect if there
 *!   is a disc inside, and notify to middleware the disc status:
 *!   - If there is a disc inside, notifies ODD_STATUS_DISC_PRESENT
 *!   - If there is NOT a disc inside, notifies ODD_STATUS_DISC_ABSENT
 */
typedef enum
{
    ODD_STATUS_TRAY_OPEN = 0x81,  /*!< tray is completely opened */
    ODD_STATUS_TRAY_CLOSE,        /*!< tray is completely closed */
    ODD_STATUS_TRAY_OPENING,      /*!< tray is in opening process */
    ODD_STATUS_TRAY_CLOSING,      /*!< tray is in closing process */
    ODD_STATUS_TRAY_ERROR,        /*!< tray is blocked or out of order */
    ODD_STATUS_DISC_LOADING,      /*!< loader is loading disc */
    ODD_STATUS_DISC_PRESENT,      /*!< there is a disc inside */
    ODD_STATUS_DISC_ABSENT        /*!< there is NOT a disc inside */
} ODD_STATUS_T;


/******************************************************************************/
/*! ODD socket device access only property types */
/******************************************************************************/
typedef enum {
    ODD_PR_DEV_SPEED                = 0x81, /*!< returns the current ODD transfer speed in Kbytes/Sec */
    ODD_PR_DEV_SPIN_OFF_TIMER               /*!< set or returns the auto spindle off timer in seconds due to ODD idle for a long time */
} ODD_DEV_PROP_TYPE_T;


/******************************************************************************/
/*! ODD block device access only property types */
/******************************************************************************/
typedef enum {
    ODD_PR_MED_TYPE                 = 0xB1, /*!< Returns the medium type enumeration */
    ODD_PR_MED_STATUS,                      /*!< Returns the medium status enumeration */
    ODD_PR_MED_LAYER_NUM,                   /*!< Returns the medium layer number */
    ODD_PR_MED_LAYER_SIZE,                  /*!< Returns the medium layer size in sectors of specified layer number */
    ODD_PR_MED_NWA,                         /*!< Returns next writable LBA of write-once medium */
    ODD_PR_MED_TOC_HEADER,                  /*!< Returns the medium TOC Header information (ODD_PR_TOC_HEADER_T)*/
    ODD_PR_MED_TOC_ENTRY,                   /*!< Returns the medium TOC Entry information (ODD_PR_TOC_ENTRY_T)*/
    ODD_PR_MED_SESSION_NUM,                 /*!< Returns the total session number of the medium */
    ODD_PR_MED_SESSION_INFO,                /*!< Returns the session information of specified session no. */
    ODD_PR_MED_TRACK_NUM,                   /*!< Returns the total track number of the medium */
    ODD_PR_MED_TRACK_INFO                   /*!< Returns the track information of specified track no. */
} ODD_MED_PROP_TYPE_T;


/******************************************************************************/
/*! ODD socket device access only property types */
/******************************************************************************/
typedef enum {
    ODD_PR_COM_LAST_SENSE_KEY       = 0xE1, /*!< Returns the last command error codes */
} ODD_COM_PROP_TYPE_T;


typedef enum {
    ODD_SPD_CD_CLV_4X,
    ODD_SPD_CD_CLV_10X,
    ODD_SPD_DVD_CLV_2X,
    ODD_SPD_DVD_CLV_4X,
    ODD_SPD_BD_CAV_4X,
    ODD_SPD_BD_CLV_2X
} ODD_DEV_SPEED_TYPE_T;

/*! Device speed information */
typedef struct _ODD_DEV_SPEED_T {
    ODD_DEV_SPEED_TYPE_T  u4ReadSpeed;     /*!< read speed */
    ODD_DEV_SPEED_TYPE_T  u4WriteSpeed;    /*!< write speed */
} ODD_DEV_SPEED_T;


/*! medium type enumeration */
typedef enum {
    ODD_MED_UNKNOWN   =0x01,
    ODD_MED_CD_ROM    =0x03,
    ODD_MED_CD_R,
    ODD_MED_CD_RW,
    ODD_MED_DVD_ROM,
    ODD_MED_DVD_R,
    ODD_MED_DVD_RW,
    ODD_MED_DVD_PR,
    ODD_MED_DVD_PRW,
    ODD_MED_DVD_RAM,
    ODD_MED_BD_ROM,
    ODD_MED_BD_RE,
    ODD_MED_BD_RW
} ODD_PR_MED_TYPE_T;


/*! medium status enumeration */
typedef enum {
    ODD_MED_INVALID,
    ODD_MED_RDONLY,
    ODD_MED_BLANK,
    ODD_MED_FORMATTED,
    ODD_MED_APPENDALBE
} ODD_PR_MED_STATUS_T;


/*! the medium layer size in sectors of specified layer number */
typedef struct _ODD_PR_MED_LAYER_SIZE_T {
    UINT32 u4LayerNo;         /*!< [IN]  specified layer no. */
    UINT32 u4SectorNum;       /*!< [OUT] returns the sector number of the specified layer no. */
} ODD_PR_MED_LAYER_SIZE_T;


#define ODD_TOC_ENTRY_MAX_NS (15854) /* 7927 tracks + 7927 sessions */

typedef struct
{
    UINT8 u1DiscType;   /* Byte 0 */
    UINT8 u1TotalTrk;   /* Byte 1 */
    UINT8 u1TotalSen;   /* Byte 2 */
    UINT8 u1Flag;       /* Byte 3 */
    UINT8 u1Trk1St;     /* Byte 4 */
    UINT8 u1Reserve;    /* Byte 5 */
} ODD_PR_TOC_HEADER_T;

typedef struct
{
    UINT8 u1TrkNo;      /* Byte 0 */
    UINT8 u1CtrlAddr;   /* Byte 1 */
    UINT8 u1Reserve;    /* Byte 2 */
    UINT8 u1AMin;       /* Byte 3 */
    UINT8 u1ASec;       /* Byte 4 */
    UINT8 u1ABlk;       /* Byte 5 */
} ODD_PR_TOC_ENTRY_T;

/*! session information of specified session no. */
typedef struct _ODD_PR_MED_SESSION_INFO_T {
    UINT32 u4SessionNo;         /*!< [IN]  specified session no. */
    UINT32 u4StartTrackNo;      /*!< [OUT] start track no. */
    UINT32 u4EndTrackNo;        /*!< [OUT] end track no. */
} ODD_PR_MED_SESSION_INFO_T;


/*! track information of specified session no. */
typedef struct _ODD_PR_MED_TRACK_INFO_T {
    UINT32  u4TrackNo;          /*!< [IN]  specified track no. */
    BOOL    fgIsAudioTrack;     /*!< [OUT] TRUE - audio track, FALSE - data track */
    BOOL    fgIsComplete;       /*!< [OUT] TRUE - complete track, FALSE - incomplete track */
    UINT32  u4StartLBA;         /*!< [OUT] track start LBA address */
    UINT32  u4SectorNum;        /*!< [OUT] track sector number */
} ODD_PR_MED_TRACK_INFO_T;


/******************************************************************************/
/*! socket device I/O control types */
/******************************************************************************/
typedef enum {
    ODD_IO_DEV_SPIN_CTRL,         /*!< Start or Stop the ODD spindle */
    ODD_IO_DEV_TRAY_CTRL,         /*!< Open or Close the ODD tray */
    ODD_IO_DEV_SET_SPEED,         /*!< Set current read/write speed */
    ODD_IO_DEV_UPGRADE,           /*!< Upgrade ODD firmware */
    ODD_IO_DEV_SOFTWARE_RESET,    /*!< Software reset ODD */
    ODD_IO_DEV_HARDWARE_RESET,    /*!< Hardware reset ODD */
    ODD_IO_DEV_TEST_UNIT_READY,   /*!< Check ODD is ready or not */
    ODD_IO_DEV_GET_EVENT_ST,      /*!< Check medium is available or not, TRUE ¡V medium present, FALSE ¡V medium abse */
    ODD_IO_DEV_MECHANISM_ST,      /*!< Check ODD tray status */
    ODD_IO_DEV_SET_TRANS_MODE,    /*!< Set ODD transfer mode to PIO or UDMA transfer */
    ODD_IO_DEV_READ_BUF_CAP,      /*!< Read buffer capacity from ODD for burning engine buffer control */
    ODD_IO_DEV_MTK_INQUIRY        /*!< Read vendor information from ODD for manufacture mode (FA mode) */
} ODD_DEV_IO_TYPE_T;


typedef enum {
    ODD_DEV_SPIN_ON,
    ODD_DEV_SPIN_OFF
} ODD_IO_DEV_SPIN_CTRL_T;


typedef enum {
    ODD_DEV_TRAY_OPEN,
    ODD_DEV_TRAY_CLOSE
} ODD_IO_DEV_TRAY_CTRL_T;


typedef struct _ODD_IO_DEV_FIRMWARE_T {
    UINT32  u4BufLen;             /*!< firmware buffer length */
    UINT8   *pu1Buf;              /*!< firmware buffer pointer */
} ODD_IO_DEV_FIRMWARE_T;


typedef enum {
    ODD_DEV_TRANS_MODE_PIO_1,
    ODD_DEV_TRANS_MODE_PIO_2,
    ODD_DEV_TRANS_MODE_PIO_3,
    ODD_DEV_TRANS_MODE_PIO_4,
    ODD_DEV_TRANS_MODE_UDMA_1,
    ODD_DEV_TRANS_MODE_UDMA_2
} ODD_IO_DEV_TRANS_MODE_T;


typedef struct _ODD_IO_DEV_BUF_CAP_T {
    UINT32  u4TotalBuf;           /*!< total buffer length in bytes */
    UINT32  u4UnusedBuf;          /*!< unused buffer length in bytes */
} ODD_IO_DEV_BUF_CAP_T;


typedef struct _ODD_IO_DEV_MTK_INQUIRY_T {
    UINT8   pu1Buf[4];            /*!< MTK inquiry data */
} ODD_IO_DEV_MTK_INQUIRY_T;


/******************************************************************************/
/*! block device I/O control types */
/******************************************************************************/
typedef enum {
    ODD_IO_MED_FORMAT         = 0x81,   /*!< Format the medium physical information */
    ODD_IO_MED_FINALIZE,                /*!< Finalize the medium to update physical information for playback */
    ODD_IO_MED_UNFINALIZE,              /*!< Unfinalize the medium to allow further recording */
    ODD_IO_MED_GET_SECTOR_SIZE,         /*!< Returns the sector size of specified LBA */
    ODD_IO_MED_READ_CD,                 /*!< Use Read CD ATAPI command to read data from CDDA discs */
    ODD_IO_MED_READ_DVD_STRUCT,         /*!< Read DVD structure information from medium to get physical information */
    ODD_IO_MED_AUTO_TUNE,               /*!< Execute disc auto tunning command to automatically adjust write strategy for unsupported discs. */
    ODD_IO_MED_READ_KCD,                /*!< Read KCD data */
    ODD_IO_MED_READ_CD_TEXT             /*!< Read CD-TEXT data */
} ODD_MED_IO_TYPE_T;


typedef struct _ODD_IO_MED_FORMAT_T {
    ODD_PR_MED_TYPE_T   eMedType;       /*!< medium type */
    UINT32              u4FormatType;   /*!< format type */
    VOID                *pvCallback;    /*!< progress callback function */
} ODD_IO_MED_FORMAT_T;


typedef struct _ODD_IO_MED_FINALIZE_T {
    ODD_PR_MED_TYPE_T   eMedType;       /*!< medium type */
    UINT32              u4FormatType;   /*!< format type */
    VOID                *pvCallback;    /*!< progress callback function */
} ODD_IO_MED_FINALIZE_T;


typedef struct _ODD_IO_MED_UNFINALIZE_T {
    ODD_PR_MED_TYPE_T   eMedType;       /*!< medium type */
    UINT32              u4FormatType;   /*!< format type */
    VOID                *pvCallback;    /*!< progress callback function */
} ODD_IO_MED_UNFINALIZE_T;


typedef enum {
    ODD_MED_SECT_SZ_2448,               /*!< audio track */
    ODD_MED_SECT_SZ_2336,               /*!< mode 0 / mode 2 formless */
    ODD_MED_SECT_SZ_2048,               /*!< mode 1 / mode 2 form 1 */
    ODD_MED_SECT_SZ_2324,               /*!< mode 2 form 2 */
    ODD_MED_SECT_SZ_2328                /*!< mode 2 form 2 */
} ODD_MED_SECTOR_SIZE_TYPE_T;


typedef struct _ODD_IO_MED_SECTOR_SIZE_T {
    UINT32                     u4Lba;   /*!< [IN] specified LBA */
    ODD_MED_SECTOR_SIZE_TYPE_T rSectSz; /*!< [OUT] sector size type of the specified LBA */
} ODD_IO_MED_SECTOR_SIZE_T;


typedef struct _ODD_IO_MED_READ_CD_T {
    UINT32                      u4Offset;       /*!< read start address */
    UINT32                      u4Count;        /*!< read data length */
    ODD_MED_SECTOR_SIZE_TYPE_T  rSectSz;        /*!< sector size in bytes */
    void                        *pvBuf;         /*!< buffer pointer */
    UINT32                      *pu4XferCnt;    /*!< actual transfer count */
} ODD_IO_MED_READ_CD_T;


typedef struct _ODD_IO_MED_READ_DVD_STRUCT_T {
    UINT8               u1MedType;      /*!< MedType: 00b - DVD & HD DVD, 01b - BD */
    UINT32              u4Address;      /*!< Address */
    UINT8               u1Layer;        /*!< Layer */
    UINT8               u1FmtCd;        /*!< FmtCd */
    UINT8               u1AGID;         /*!< AGID */
    void                *pvBuf;         /*!< buffer pointer */
    UINT32              u4BufLen;       /*!< buffer length */
} ODD_IO_MED_READ_DVD_STRUCT_T;


typedef struct _ODD_IO_MED_READ_KCD_T {
    UINT8               u1AGID;         /*!< AGID */
    void                *pvBuf;         /*!< buffer pointer */
    UINT32              u4BufLen;       /*!< buffer length */
} ODD_IO_MED_READ_KCD_T;

typedef struct _ODD_IO_MED_READ_CD_TEXT_T {
    void                *pvBuf;         /*!< buffer pointer */
    UINT32              u4BufLen;       /*!< buffer length */
} ODD_IO_MED_READ_CD_TEXT_T;

/******************************************************************************/
/*! ODD socket & block device access I/O types */
/******************************************************************************/
typedef enum {
    ODD_IO_COM_REPORT_KEY       = 0xE1, /*!< Report key from ODD for content protection key exchange */
    ODD_IO_COM_SEND_KEY,                /*!< Send key to ODD for content protection key exchange */
    ODD_IO_COM_GET_FEATURE              /*!< Get features of ODD loader or disc */
} ODD_COM_IO_TYPE_T;


typedef struct _ODD_IO_COM_REPORT_KEY_T {
    UINT32              u4Lba;          /*!< Lba */
    UINT8               u1Func;         /*!< Func */
    UINT8               u1KeyClass;     /*!< Key class */
    UINT8               u1AGID;         /*!< AGID */
    UINT8               u1KeyFmt;       /*!< KeyFmt */
    void                *pvBuf;         /*!< buffer pointer */
    UINT32              u4BufLen;       /*!< buffer length */
} ODD_IO_COM_REPORT_KEY_T;


typedef struct _ODD_IO_COM_SEND_KEY_T {
    UINT8               u1Func;         /*!< Func */
    UINT8               u1KeyClass;     /*!< Key class */
    UINT8               u1AGID;         /*!< AGID */
    UINT8               u1KeyFmt;       /*!< KeyFmt */
    void                *pvBuf;         /*!< buffer pointer */
    UINT32              u4BufLen;       /*!< buffer length */
} ODD_IO_COM_SEND_KEY_T;


typedef struct _ODD_IO_COM_GET_FEATURE_T {
    UINT32              u4FeatureNum;   /*!< Feature Number */
    void                *pvBuf;         /*!< buffer pointer */
    UINT32              u4BufLen;       /*!< buffer length */
} ODD_IO_COM_GET_FEATURE_T;


#endif /* _X_ODD_DEV_H_ */

