/** 
 * @brief           USBC Api Header
 * @author          AXELL CORPORATION
 * @description     usbc_api.c用ヘッダ
 * @note            none
 * @history         2017_02_22	初版
 * @history         2017_10_26  Ver2.0
*/
/* DOM-IGNORE-BEGIN */
/*
 * This program was created by AXELL CORPORATION.
 * Copyright (C) 2017 AXELL CORPORATION, all rights reserved.
 */



#ifndef __USBC_API_H__
#define __USBC_API_H__
/* DOM-IGNORE-END */

// *************************************************************************************************
//	include
// *************************************************************************************************
#include	"usbc_main.h"


// *************************************************************************************************
//	define
// *************************************************************************************************
//------------------------------------------------------------------------------
// Default エンドポイント番号
//------------------------------------------------------------------------------
/** デフォルトパイプEP番号 */
#define		USB_DEFAULT_EP_NUM				(0x00)

//------------------------------------------------------------------------------
// パケットID
//------------------------------------------------------------------------------
/** Data-OUT パケットID */
#define		USB_PACKETID_OUT				(0x01)
/** Data-IN パケットID */
#define		USB_PACKETID_IN					(0x09)
// SOF パケットID */
#define		USB_PACKETID_SOF				(0x0A)
/** SETUP パケットID */
#define		USB_PACKETID_SETUP				(0x0D)

//------------------------------------------------------------------------------
// 転送タイプ
//------------------------------------------------------------------------------
/** Endpointのタイプのマスク */
#define		USB_TRANS_TYPEMASK				(0x03)
/** コントロール転送 */
#define		USB_TRANS_CONTROL				(0x00)
/** アイソクロナス転送 */
#define		USB_TRANS_ISOCHRONOUS			(0x01)
/** バルク転送 */
#define		USB_TRANS_BULK					(0x02)
/** インタラプト転送 */
#define		USB_TRANS_INTERRUPT				(0x03)

//------------------------------------------------------------------------------
//	CB発生元
//------------------------------------------------------------------------------
/** USB コア */
#define		MOD_ID_USBH						(0)
/** 非サポートデバイスクラスドライバ */
#define		MOD_ID_CLASSDRV_UNKNOWNDEV		(1)
/** ストレージ */
#define		MOD_ID_CLASSDRV_STOR			(2)
/** コミュニケーションデバイス */
#define		MOD_ID_CLASSDRV_CDC				(3)
/** HIDデバイス */
#define		MOD_ID_CLASSDRV_HID				(4)
/** OS_WRAPPER */
#define		MOD_ID_OSWRAP					(100)


//------------------------------------------------------------------------------
//	CB種別
//------------------------------------------------------------------------------
/** デバイスが接続された */
#define		CBID_CORE_DEVATTACH				(0)
/** デバイスが切断された */
#define		CBID_CORE_DEVDETACH				(1)
/** 過電流を検知した */
#define		CBID_CORE_OVERCURRENT			(2)
/** リクエストに対するコールバック */
#define		CBID_CORE_REQ					(3)
/** ステータス通知 */
#define		CBID_CORE_STATUS				(4)
/** Split Err Notify通知 */
#define		CBID_CORE_SPLITERR				(5)


//------------------------------------------------------------------------------
//	デバイス種別							※CALLBACK構造体等
//------------------------------------------------------------------------------
typedef enum {

    USB_CLASS_UNKNOWN,															//	非サポートデバイスクラス
    USB_CLASS_CDC,																//	CDCクラス
    USB_CLASS_HID,																//	HIDクラス
    USB_CLASS_MASSSTOR,															//	MSC(BOT)クラス
    USB_CLASS_HUB																//	HUBクラス

} class_driver_type;


//------------------------------------------------------------------------------
//	Message ID - Bit Format
//
//	X											0=REQ/1=ANS
//	 --- ----									処理BLOCK種別
//            ---- ---- 						Reserved
//                       ---- ---- ---- ---- 	各Block毎のMessageID
//------------------------------------------------------------------------------
//	処理タスク種別
#define		USBH_MSGID_KIND_MSK								(0x7F000000)		//	
#define		USBH_MSGID_KIND_API_WRAPP						(0x01000000)		//	For API_WRAPPER
#define		USBH_MSGID_KIND_HUB_THREAD						(0x02000000)		//	For HUB_Thraed

#define		USBH_MSGID_KIND_RESPONSE						(0x80000000)

// *************************************************************************************************
//	structure
// *************************************************************************************************

struct usb_control_block;

// void (*usb_complete_t)(struct usb_control_block * ucb);
typedef int (*usb_common_callback_t)( int mod_id, int callback_id, void * context );	/** クラスドライバ コールバック登録用関数型 */
typedef usb_common_callback_t usb_complete_t;

//------------------------------------------------------------------------------
//	Message送信（基本系）
//		⇒	mbx_buf に、対応するポインタはめる。
//------------------------------------------------------------------------------
struct uhs_mbxbuf {                 // __st__
    uhs_ubit32_t    os_area;													// OS使用エリア
    void *          mbx_buf;													// 転送データバッファ
};

//------------------------------------------------------------------------------
//	イベント＋関数処理定義
//------------------------------------------------------------------------------
typedef	struct	{

	uhs_ubit32_t		mess_id;
	void				(*func)(void *msg_ptr);

}	UHS_EVNT_FUNC_TBL;

//------------------------------------------------------------------------------
//	共通MessageBlock
//------------------------------------------------------------------------------
typedef	struct	{

    uhs_ubit32_t    os_area;													//	OS使用エリア
	uhs_ubit32_t	mess_id;													//	Message ID
	uhs_ubit32_t	mem_pool;													//	利用mem poolアドレス

}	UHS_MSG_COMMON;

/**	本構造体はUSBリクエストの発行やパイプ操作に使用します。<p>
    クラスドライバは本構造体のためにメモリを確保し、各メンバを適切に設定後、本構造体を使用してUSB HostのAPIを呼び出します。<p>
    生成タイミング ： 随時<p>
    削除タイミング ： コールバック関数が呼び出されるAPIの場合、コールバック関数が呼び出されるまで削除禁止 */
struct usb_control_block {
    struct usbd_usb_deviceinfo* usbdev;											/** デバイス情報
																					Split管理情報も含む。(HUBクラスで格納する。) */

    uhs_ubit32_t         pipe;													/**	PIPE情報<p>
                                                                                    Pipe情報は主にUSBコントロールブロックのメンバとしてパイプ操作やUSBリクエストの発行に使用します。<p>
                                                                                    Pipe情報には、以下の情報が含まれます。<p>
                                                                                    MAXパケットサイズ、EP種別、パケットID、EP番号、USBアドレス */
        #define USB_PIPE_ADDR_SHIFT 0
            /**	 bit0 〜 6    USBアドレス */
            #define USB_PIPE_ADDR_MASK  (0x7fU << USB_PIPE_ADDR_SHIFT)
        #define USB_PIPE_EPNUM_SHIFT 8
            /**	    8 〜 11   エンドポイント番号 */
            #define USB_PIPE_EPNUM_MASK (0x0fU << USB_PIPE_EPNUM_SHIFT)
        #define USB_PIPE_PID_SHIFT 12
            /**	   12 〜 15   パケットID */
            #define USB_PIPE_PID_MASK   (0x0fU << USB_PIPE_PID_SHIFT)
        #define USB_PIPE_EPTYPE_SHIFT 16
            /**	   16 〜 17   エンドポイントタイプ */
            #define USB_PIPE_EPTYPE_MASK (0x03U << USB_PIPE_EPTYPE_SHIFT)
        #define USB_PIPE_MAXPKT_SHIFT 20
            /**	   20 〜 30   マックスパケットサイズ */
            #define USB_PIPE_MAXPKT_MASK (0x3ffU << USB_PIPE_MAXPKT_SHIFT)

    uhs_ubit8_t         open_cnt;												/** パイプのオープンカウンタ */
    usb_device_request_t *setup_data;											/** SETUPパケット格納(コントロール転送のみ) */
    void                 *data_buf;												/** データ格納バッファ(非キャッシュ領域) */
    uhs_ubit32_t         data_len;												/** 転送データサイズ格納 */
    uhs_ubit32_t         act_len;												/** 転送済みデータサイズ格納 */

    usb_common_callback_t complete_func;										/** 完了CALLBACK関数ポインタ */

    uhs_ubit32_t         time_out;												/** タイムアウト時間格納 */
    uhs_status_t         status;												/** 転送ステータス格納<p>
                                                                                    次のAPIを使用時に下のエラーが格納されます。<p>
                                                                                    Usbh_Api_ControlMsg<p>
                                                                                    Usbh_Api_BulkMsg<p>
                                                                                    Usbh_Api_SyncControlMsg<p>
                                                                                    Usbh_Api_SyncBulkMsg<p>
                                                                                    Usbh_Api_IntMsg<p>
                                                                                    Usbh_Api_CancelPipe<p>
                                                                                    Usbh_Api_GetDescriptor<p>
                                                                                    Usbh_Api_ClearFeature<p>
                                                                                    Usbh_Api_SetFeature<p>
                                                                                    Usbh_Api_GetStatus<p>
                                                                                    Usbh_Api_GetInterface<p>
                                                                                    Usbh_Api_GetConfiguration<p>
                                                                                    EUSB_NO_ERROR ： 正常終了<p>
                                                                                    EUSB_DATABUF_ERROR ： Overrun/underrunエラー<p>
                                                                                    EUSB_BABBLE_DETECTED ： Bubble検出エラー<p>
                                                                                    EUSB_TX_ERROR ： 転送エラー検出（BadPID,CRC,Timeout）<p>
                                                                                    EUSB_MISSED_MICROFRAME ： FS/LS Missed microフレーム<p>
                                                                                    EUSB_INTXFER_UNKNOWNSIZE ： 転送サイズ未定。（Interruptの転送キャンセル時）<p>
                                                                                    EUSB_STOP_TRANS ： 転送停止<p>
                                                                                    EUSB_HALT ： AnyError,STALL(上記エラーに引っかからないケース)<p>
                                                                                    EUSB_TIMEOUT ： タイムアウト */
    uhs_ubit8_t          interval;												/** 同期転送時のインターバル時間 */
        #define USB_INTERVAL_1us        (1)										/** 1 us */
        #define USB_INTERVAL_2us        (2)										/** 2 us */
        #define USB_INTERVAL_4us        (4)										/** 4 us */
        #define USB_INTERVAL_1ms        (8)										/** 1 ms */
        #define USB_INTERVAL_2ms        (16)									/** 2 ms */
        #define USB_INTERVAL_4ms        (32)									/** 4 ms */
        #define USB_INTERVAL_8ms        (64)									/** 8 ms */
        #define USB_INTERVAL_16ms       (128)									/** 16ms */
        #define USB_INTERVAL_32ms       (256)									/** 32ms */

	//	API_WRAPP情報。
	//^^^^^^^^^^^^^^^^^
    kernel_context_t     ucb_mbx;												/** 同期転送用メールボックス（同期転送の待ち合せようにmailboxを生成する） */
    uhs_boolean_t        is_sync;												/** 同期時にTrue設定（転送完了Threadで参照） */

    uhs_ubit8_t          flags;													/** フラグ */
        /** フラグ無し */
        #define USB_UCB_OK                  (0)

//        #define USB_UCB_XFER_ABORTED        (1)								/** 転送がアボートされた */

        /** 転送がタイムアウトした */
        #define USB_UCB_XFER_TIMEOUT        (2)

    uhs_ubit8_t          request_flags;											/** フラグ */
        #define USB_UCB_NONE                (0x00U)
        #define USB_UCB_NOT_LINKED_YET      (0x01U)
        #define USB_UCB_LINKED              (0x02U)
        #define USB_UCB_UNLINKED            (0x03U)

    uhs_ubit8_t          cancel_flags;											/** フラグ */
        #define USB_UCB_NOT_CANCELED        (0x00U)
        #define USB_UCB_CANCELED            (0x01U)

    void                *context;												/** コンテキストデータポインタ */
};



//------------------------------------------------------------------------------
//	クラスドライバ検出　条件テーブル
//------------------------------------------------------------------------------

/** クラスドライバに対応するデバイスを指定するための構造体<p>
    クラスドライバの登録で使用するclass_driver_reginfo構造体のメンバとして使用します。<p>
    USB Host は、クラスドライバが設定した本構造体のメンバと、デバイスが接続された際に取得するディスクリプタ情報を比較することで、
    デバイスに対応するドライバを検索・ロードします。<p>
    なお、ひとつのクラスドライバに複数のデバイスを対応づける場合、本構造体を必要な条件の数だけ配列として確保し、条件を設定後
    その先頭ポインタをclass_driver_reginfo構造体のメンバに格納して下さい。<p>
    比較を行なわないメンバの設置値については不問ですが、将来の拡張性を考慮し0で埋めることを推奨します。<p>
    生成タイミング ： クラスドライバイニシャル時<p>
    削除タイミング ： クラスドライバ削除時 */
struct usb_class_driver_ids {
    uhs_ubit32_t    check_ids;													/** 一致を比較するIDを指定 */
        /** デバイススピードを比較 */
        #define         CHECK_DEV_SPEED         (1 << 0)
        /** USBバージョンを比較 */
        #define         CHECK_BCD_USB           (1 << 1)
        /** ベンダIDを比較 */
        #define         CHECK_VENDOR_ID         (1 << 2)
        /** プロトコルIDを比較 */
        #define         CHECK_PRODUCT_ID        (1 << 3)
        /** デバイスクラスIDを比較 */
        #define         CHECK_DEVCLASS_ID       (1 << 4)
        /** デバイスサブクラスIDを比較 */
        #define         CHECK_DEVSUBCLASS_ID    (1 << 5)
        /** デバイスプロトコルIDを比較 */
        #define         CHECK_DEVPROTOCOL_ID    (1 << 6)
        /** インタフェースクラスIDを比較 */
        #define         CHECK_INTCLASS_ID       (1 << 7)
        /** インタフェースサブクラスIDを比較 */
        #define         CHECK_INTSUBCLASS_ID    (1 << 8)
        /** インタフェースプロトコルIDを比較 */
        #define         CHECK_INTPROTOCOL_ID    (1 << 9)
    uhs_ubit16_t    dev_speed;													/** USBの転送スピードの一致をチェック */
    uhs_ubit16_t    bcdusb_id;													/** USBバージョンの一致をチェック */
    uhs_ubit16_t    vendor_id;													/** ベンダIDの一致をチェック */
    uhs_ubit16_t    product_id;													/** プロダクトIDの一致をチェック */
    uhs_ubit16_t    device_class_id;											/** デバイスクラスIDの一致をチェック */
    uhs_ubit16_t    device_subclass_id;											/** デバイスサブクラスIDの一致をチェック */
    uhs_ubit16_t    device_protocol_id;											/** デバイスプロトコルIDの一致をチェック */
    uhs_ubit16_t    interface_class_id;											/** インターフェースクラスIDの一致をチェック */
    uhs_ubit16_t    interface_subclass_id;										/** インターフェースサブクラスIDの一致をチェック */
    uhs_ubit16_t    interface_protocol_id;										/** インターフェースプロトコルIDの一致をチェック */
    uhs_ubit32_t    terminated;													/** ターミネータ判別 */
        /** 配列の最終要素ではない */
        #define NON_TERMINATE       0x00000000
        /** 配列の最終要素、もしくは単一の要素 */
        #define TERMINATE           0xffffffff
};

typedef int (*usb_class_reregi_callback_t)(void * stCallback);					/** クラスドライバ コールバック再登録用関数型 */
typedef int (*usb_class_exit_callback_t)(void * stCallback);					/** クラスドライバ 終了処理コールバック関数型 */

/** クラスドライバをUSB Hostに登録(Usbh_Api_DriverRegister)および
    登録解除(Usbh_Api_DriverUnRegister)するための構造体<p>
    生成タイミング ： クラスドライバイニシャル時<p>
    削除タイミング ： クラスドライバ削除時 */
struct class_driver_reginfo {

    usb_common_callback_t			attach;										/** デバイス接続時にコールされるコールバック関数 */
    usb_common_callback_t			detach;										/** デバイス切断時にコールされるコールバック関数 */

	usb_class_reregi_callback_t		class_reregi_callback;						/** クラスドライバ コールバック再登録関数ポインタ */
	usb_class_exit_callback_t		class_exit_callback;						/** クラスドライバ 終了処理関数ポインタ(Initはアプリから設定するため、app_callback_info型で保持) */
    struct usb_class_driver_ids		*id_table;									/** 対応ドライバ検索に使用するIDテーブル */
    void 							*context;									/** APIラッパで使用するコンテキスト(アタッチ／デタッチで渡されたい情報を上位側で指定する。） */
	class_driver_type				class_id;									/** クラスID情報 */
};


// 接続コールバックの context
typedef struct _usb_cbcontext_dev_attach {
    struct usbd_usb_deviceinfo * usbdev;
    void* context;
} usb_cbcontext_dev_attach;

// 切断コールバックの context

typedef struct _usb_cbcontext_dev_detach {
    struct usbd_usb_deviceinfo * usbdev;
    void* context;
} usb_cbcontext_dev_detach;




// *************************************************************************************************
//	extern
// *************************************************************************************************
//------------------------------------------------------------------------------
//	USB_CORE API一覧
//------------------------------------------------------------------------------
extern uhs_status_t Usbc_Api_DriverRegister(struct class_driver_reginfo * driver_info);
extern void         Usbc_Api_DriverUnRegister(struct class_driver_reginfo * driver_info);
extern uhs_status_t Usbc_Api_ControlMsg(struct usb_control_block* ucb);
extern uhs_status_t Usbc_Api_BulkMsg(struct usb_control_block* ucb);
extern uhs_status_t Usbc_Api_IntMsg(struct usb_control_block* ucb);
extern uhs_status_t Usbc_Api_IsoMsg(struct usb_control_block* ucb);
extern uhs_status_t Usbc_Api_StopTrans(struct usb_control_block* ucb);
extern uhs_status_t Usbc_Api_StdGetDescriptor(struct usb_control_block* ucb, struct usbd_usb_deviceinfo* usbdev, uhs_ubit8_t type, uhs_ubit8_t index, uhs_ubit16_t wIndex, void *buf, uhs_ubit32_t size);
extern uhs_status_t Usbc_Api_StdClrFeature(struct usb_control_block* ucb, struct usbd_usb_deviceinfo* usbdev, uhs_ubit8_t bmRequest, uhs_ubit16_t feature_select, uhs_ubit16_t wIndex);
extern uhs_status_t Usbc_Api_StdSetFeature(struct usb_control_block* ucb, struct usbd_usb_deviceinfo* usbdev, uhs_ubit8_t bmRequest, uhs_ubit16_t feature_select, uhs_ubit16_t wIndex);
extern uhs_status_t Usbc_Api_StdGetStatus(struct usb_control_block* ucb, struct usbd_usb_deviceinfo* usbdev, uhs_ubit8_t bmRequest, uhs_ubit16_t wIndex, void *buf);
extern uhs_status_t Usbc_Api_StdSetAddress(struct usb_control_block* ucb, struct usbd_usb_deviceinfo* usbdev, uhs_ubit16_t address);
extern uhs_status_t Usbc_Api_StdSetDescriptor(struct usb_control_block* ucb, struct usbd_usb_deviceinfo* usbdev, uhs_ubit8_t type, uhs_ubit8_t index, uhs_ubit16_t wIndex, void *buf, uhs_ubit32_t size);
extern uhs_status_t Usbc_Api_StdGetInterface(struct usb_control_block* ucb, struct usbd_usb_deviceinfo* usbdev, uhs_ubit16_t wIndex, void *buf);
extern uhs_status_t Usbc_Api_StdGetConfiguration(struct usb_control_block* ucb, struct usbd_usb_deviceinfo* usbdev, void *buf);
extern uhs_status_t Usbc_Api_StdSetInterface(struct usb_control_block* ucb, struct usbd_usb_deviceinfo* usbdev, uhs_ubit16_t intf_num, uhs_ubit16_t alt_num);
extern uhs_status_t Usbc_Api_StdSetConfig(struct usb_control_block* ucb, struct usbd_usb_deviceinfo* usbdev, uhs_ubit16_t config_num);
extern uhs_status_t Usbc_Api_StdSynchFrame(struct usb_control_block* ucb, struct usbd_usb_deviceinfo* usbdev, uhs_ubit8_t endpoint, void *buf);
extern uhs_status_t Usbc_Api_AllocUsbDev(struct usbd_usb_deviceinfo ** usbdev);
extern uhs_status_t Usbc_Api_FreeUsbDev(struct usbd_usb_deviceinfo * usbdev);
extern uhs_status_t Usbc_Api_AllocUsbCtrlBlock(struct usb_control_block ** ucb);
extern uhs_status_t Usbc_Api_FreeUsbCtrlBlock(struct usb_control_block * ucb);
extern struct usb_endpoint_descriptor *Usbc_Api_GetEpDescriptor(struct usbd_usb_deviceinfo *usbdev, uhs_ubit8_t conf_num, uhs_ubit8_t intf_num, uhs_ubit8_t ep_type, uhs_ubit8_t ep_dir);
extern struct usb_endpoint_descriptor *Usbc_Api_GetEpDescriptorEx(struct usbd_usb_deviceinfo * usbdev, uhs_ubit8_t conf_num, uhs_ubit8_t intf_num, uhs_ubit8_t ep_type, uhs_ubit8_t ep_dir, 
    uhs_ubit8_t ep_num);
extern void Usbc_Api_FixupUsbCtrlBlock(struct usb_control_block * ucb, struct usbd_usb_deviceinfo* usbdev,  uhs_ubit32_t pipe,  usb_device_request_t *setup_data,
                    void *data_buf, uhs_ubit32_t data_len, uhs_ubit8_t interval, usb_complete_t complete_func, void     *context);
extern uhs_status_t Usbc_Api_OpenPipe(struct usb_control_block* ucb);
extern uhs_status_t Usbc_Api_ClosePipe(struct usb_control_block* ucb);
extern uhs_boolean_t Usbc_Api_PipeIsOpened(struct usb_control_block* ucb);

extern uhs_ubit32_t Usbc_Api_GetPipeMaxPktSize(uhs_ubit32_t pipe);
extern void Usbc_Api_FixupPipeInfo( uhs_ubit32_t *pipe, uhs_ubit8_t usb_addr, uhs_ubit8_t ep_num, uhs_ubit8_t packet_id, uhs_ubit8_t ep_type, uhs_ubit32_t maxpkt_size);
extern uhs_ubit32_t Usbc_Api_GetPipeAddr(uhs_ubit32_t pipe);
extern uhs_ubit32_t Usbc_Api_GetPipeEpNum(uhs_ubit32_t pipe);
extern uhs_ubit32_t Usbc_Api_GetPipePID(uhs_ubit32_t pipe);
extern uhs_boolean_t Usbc_Api_GetPipeDirIn(uhs_ubit32_t pipe);
extern uhs_ubit32_t Usbc_Api_GetPipeEpType(uhs_ubit32_t pipe);
extern uhs_ubit32_t Usbc_Api_GetPipeMaxPktSize(uhs_ubit32_t pipe);
extern uhs_status_t	Usbc_Api_NotifyStartSuspend( struct usbd_usb_deviceinfo * usbdev );
extern uhs_status_t	Usbc_Api_NotifyFinishSuspend( struct usbd_usb_deviceinfo * usbdev );



//------------------------------------------------------------------------------
//  マクロ定義
//------------------------------------------------------------------------------
/** コントロール転送用UCB設定API */
#define Usb_Core_FixupCtrlUcb(ucb, usbdev, pipe, setup, buf, size, function, context)   \
            Usbc_Api_FixupUsbCtrlBlock(ucb, usbdev, pipe, setup, buf, size, 0x00, function, context)
/** バルク転送用UCB設定API */
#define Usb_Core_FixupBulkUcb(ucb, usbdev, pipe, buf, size, function, context)  \
            Usbc_Api_FixupUsbCtrlBlock(ucb, usbdev, pipe, NULL, buf, size, 0, function, context)
/** インタラプト転送用UCB設定API */
#define Usb_Core_FixupIntrUcb(ucb, usbdev, pipe, buf, size, interval, function, context)    \
            Usbc_Api_FixupUsbCtrlBlock(ucb, usbdev, pipe, NULL, buf, size, interval, function, context)
/** アイソ転送用UCB設定API */
#define Usb_Core_FixupIsoUcb(ucb, usbdev, pipe, buf, size, function, context)   \
            Usbc_Api_FixupUsbCtrlBlock(ucb, usbdev, pipe, NULL, buf, size, 0, function, context)





#endif
// end of __USBC_API_H__


//End of File
//  usbc_api.h

