/** 
 * @brief           USBC main Header
 * @author          AXELL CORPORATION
 * @description     usbc_main.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_MAIN_H__
#define __USBC_MAIN_H__
//#include "hcd_com.h"
//#include "uhs_config.h"
/* DOM-IGNORE-END */


// *************************************************************************************************
//	define
// *************************************************************************************************
//------------------------------------------------------------------------------
// システムの動作・制限事項に関わる宣言
//------------------------------------------------------------------------------
/** USBデバイス接続直後のコマンドのリトライ回数 */
#define 	USBD_CONN_RETRY_CNT     (1)
/** 本システムで対応する接続デバイス総数 */
#define 	USB_MAX_CHILDREN_LOCAL  (32)
/** 接続デバイスに割り当てるデバイス番号の最小値 */
#define 	USB_MIN_CHILDREN_LOCAL  (1)
/** 本システムに同時に登録できるクラスドライバ数 */
#define 	USB_MAX_DRIVERS         (20)
/** ハブの下位ポートに接続可能なデバイス数 */
#define 	USB_MAX_LOWER_DEV       (7)
/** タイムアウト時間 */
/** デフォルトの転送タイムアウト時間 */
#define 	USB_HOST_TIMEOUT		(2500)
/** セマフォ待ち */
#define 	USB_HOST_SEMTIMEOUT		(8000)
/** USB転送タイムアウト時間（Control通信が同期処理で、rcv_msg待ちする時間） */
#define 	USB_CTRL_GET_TIMEOUT    (USB_HOST_TIMEOUT+500)


//------------------------------------------------------------------------------
// USB使用に関する宣言
//------------------------------------------------------------------------------
/** USBデバイスディスクリプタサイズ */
#define 	USB_DEVDESC_SIZE        (0x12)
/** USBデバイスクォリファイアディスクリプタサイズ */
#define 	USB_DEVQLFRDESC_SIZE    (0xA)
/** USBコンフィグレーションディスクリプタサイズ */
#define 	USB_CONFIGDESC_SIZE     (0x9)
/** USBインターフェースディスクリプタサイズ */
#define 	USB_INFTDESC_SIZE       (0x9)
/** USBエンドポイントディスクリプタサイズ */
#define 	USB_EPDESC_SIZE         (0x7)
/** USB仕様で規定されている接続デバイス総数 */
#define 	USB_MAX_CHILDREN        (127)
/** コントロールパイプのマックスパケットサイズ */
#define 	USB_MAXPKT_CTRLEP       (64)
/** USB セットアップパケットのサイズ */
#define 	USB_SETUP_SIZE          (8)
/** エンドポイントの総数(1.1の場合) */
#define 	USB_MAX_ENDPOINT        (32)


//------------------------------------------------------------------------------
// 転送に関するエラーコード
//------------------------------------------------------------------------------
#define     EUSB_NO_ERROR           (0)											// OHCI Completion Codes
#define     EUSB_CRC                (-100)
#define     EUSB_BIT_STUFF          (-101)
#define     EUSB_DATA_TOGGLE        (-102)
#define     EUSB_HALT               (-103)
#define     EUSB_TIMEOUT            (-104)
#define     EUSB_PID                (-105)
#define     EUSB_DATA_OVERRUN       (-106)
#define     EUSB_DATA_UNDERRUN      (-107)
#define     EUSB_BUF_OVERRUN        (-108)
#define     EUSB_BUF_UNDERRUN       (-109)
#define     EUSB_NOT_ACCESSED       (-110)
/** S/Wの要求により転送を停止した */
#define     EUSB_STOP_TRANS         (-111)

#define     EUSB_DATABUF_ERROR      (-200)										// EHCI status code in qTD
#define     EUSB_BABBLE_DETECTED    (-201)
#define     EUSB_TX_ERROR           (-202)
#define     EUSB_MISSED_MICROFRAME  (-203)

#define     EUSB_INTXFER_UNKNOWNSIZE  (-204)

//------------------------------------------------------------------------------
// ストリング取得マクロ
//------------------------------------------------------------------------------
#define 	Usb_Core_GetStringManu(ucb, usbdev)     Usb_Core_GetString(ucb, usbdev, usbdev->usbdev_DevDescriptor->iManufacturer, &usbdev->usbdev_StringManu)
#define 	Usb_Core_GetStringProduct(ucb, usbdev)  Usb_Core_GetString(ucb, usbdev, usbdev->usbdev_DevDescriptor->iProduct, &usbdev->usbdev_StringProduct)
#define 	Usb_Core_GetStringSerial(ucb, usbdev)   Usb_Core_GetString(ucb, usbdev, usbdev->usbdev_DevDescriptor->iSerialNumber, &usbdev->usbdev_StringSerial)
#define 	CS_DESC_DATA_OFFSET 0x02		/* bLength +  bDescriptorType = 2Byte */

// *************************************************************************************************
//	structure
// *************************************************************************************************
//------------------------------------------------------------------------------
// USBコア管理構造体
//------------------------------------------------------------------------------
typedef struct {                            // __st__
    kernel_context_t    *lock_driver_list;										// ドライバ登録リスト保護用セマフォ
//  kernel_context_t    *mbx_osc;
} usb_core_object_t;

/** コンフィグレーション・ディスクリプタに含まれる情報を展開する構造体。<p>
    本構造体から、インタフェース・ディスクリプタ及び、クラスSpecificディスクリプタ、
    エンドポイント・ディスクリプタの情報をたどる事ができます。<p>
    生成タイミング ： デバイス接続時<p>
    削除タイミング ： デバイス切断時 */
struct drv_usb_configuration_descriptor {
    struct drv_usb_configuration_descriptor *next;		/** 次のConfigディスクリプタ */
    struct usb_configuration_descriptor *conf_desc;		/** USB規格フォーマットで格納された
    														コンフィグレーション・ディスクリプタ */
    uhs_ubit8_t                         num_intf;		/** 全インターフェース数 */
    struct usb_interface                *interfaces;	/** インタフェース・ディスクリプタ情報への
    														ポインタ(先頭) */
    uhs_ubit8_t                         config_num;		/** コンフィグレーション番号 */
    uhs_ubit8_t                         *extra;			/** 拡張データ(9byte以上の場合) */
    uhs_size_t                          extralen;		/** 拡張データレングス */
};

/** クラスSpecificディスクリプタを保持する構造体<p>
    生成タイミング ： デバイス接続時<p>
    削除タイミング ： デバイス切断時 */
struct usb_cs_descriptor {
    udi_ubit8_t bLength;        		/** Size of this descriptor in bytes */
    udi_ubit8_t bDescriptorType;        /** descriptor type (assigned by USB) */
    udi_ubit8_t* pbData;        		/** Pointer of specific data */
};

/** インタフェース・ディスクリプタに含まれる情報を展開する構造体。<p>
    複数のインタフェース・ディスクリプタが存在する場合は、*next にその実体がリンクされます。<p>
    生成タイミング ： デバイス接続時<p>
    削除タイミング ： デバイス切断時 */
struct usb_interface {
    struct usb_interface                *next;			/** 次のインタフェース・ディスクリプタへの
    														リンク */
    uhs_ubit8_t                         intf_num;		/** インターフェース番号 */
    uhs_ubit8_t                         num_altif;		/** 同じインターフェース番号に属する
    														インターフェース数 */
    uhs_ubit32_t                        act_alt_num;	/** アクティブなオルタネート番号 */
    struct drv_usb_interface_descriptor *alt_intf;		/** 先頭のインタフェース・ディスクリプタ
    														情報ポインタ */
    struct drv_usb_interface_descriptor *act_alt;		/** アクティブなオルタネートセッティング
    														管理構造体 */
    void                                *private_data;	/** 未使用 */
};

/** インタフェース・ディスクリプタの展開情報用構造体<p>
    生成タイミング ： デバイス接続時<p>
    削除タイミング ： デバイス切断時 */
struct drv_usb_interface_descriptor {
    struct drv_usb_interface_descriptor *next;			/** マルチインターフェース対応の為のリンク */
    struct usb_interface_descriptor     *intf_desc;		/** USB規格フォーマットのインタフェース・
    														ディスクリプタ */
    uhs_ubit8_t                         intf_num;		/**	インターフェース番号 */
    uhs_ubit8_t                         *extra;			/** 拡張データ(9byte以上の場合) */
    uhs_size_t                          extralen;		/** 拡張データレングス */
    uhs_ubit8_t                         num_ep;			/** このインタフェース・ディスクリプタに
    														含まれるEp数 */
    struct drv_usb_cs_descriptor 		*cs_descriptors;/**	クラス固有のDescriptor用領域 */

    struct drv_usb_endpoint_descriptor  *endpoints;		/** このインタフェース・ディスクリプタに
    														関連するエンドポイント・ディスクリプタ
    														情報 */
};

/** エンドポイント・ディスクリプタの情報用構造体<p>
    生成タイミング ： デバイス接続時<p>
    削除タイミング ： デバイス切断時 */
struct drv_usb_endpoint_descriptor {
    struct drv_usb_endpoint_descriptor *next;		/** 複数エンドポイント対応の為のリンク */
    struct usb_endpoint_descriptor      *ep_desc;	/** USB規格フォーマットでのエンドポイント・
    													ディスクリプタ情報 */
    uhs_ubit8_t                         *extra;		/** 拡張データ(7byte以上の場合) */
    uhs_size_t                          extralen;	/** 拡張データレングス */
    uhs_ubit8_t                         ep_addr;	/** EPアドレス */
};

/** クラスSpecificディスクリプタ情報を管理する構造体<p>
    生成タイミング ： デバイス接続時<p>
    削除タイミング ： デバイス切断時 */
struct drv_usb_cs_descriptor {
	struct drv_usb_cs_descriptor	*next;		/** 次のクラスSpecificディスクリプタへのリンク */
	struct usb_cs_descriptor  		*cs_desc;	/** クラスSpecificディスクリプタの実体先 */
};

/**	Split Infomation (for LS/FS device via HS hub) ⇒ QHに設定すべきSplit関連情報<p>
    USB2.0HUBを経由してFS/LSデバイスと通信を行う際にSprit Transactionを利用します。<p>
    これに関連する情報を保持する為の構造体です。接続デバイス毎に本構造体を生成し、管理します。<p>
    生成タイミング ： デバイス接続時<p>
    削除タイミング ： デバイス切断時 */
struct	split_infomation	{

	uhs_boolean_t	is_split;			/**	0=NotSplit / 1=Split */

		#define		USBH_SPLT_DISABLE				(0)
		#define		USBH_SPLT_ENABLE				(1)

	uhs_boolean_t	is_multi;			/**	0=SingleTT / 1=MultiTT */

		#define		USBH_TT_KIND_SINGLE				(0)
		#define		USBH_TT_KIND_MULTI				(1)

	uhs_ubit8_t		hub_adr;			/**	HUB ADDRESS */
	uhs_ubit16_t	port_no;			/**	PORT Number */
};


/** USBデバイス管理用構造体		(USBデバイス接続時に生成する情報)<p>
    USB HostはUSBペリフェラルデバイスの情報を、接続デバイス毎に本構造体を生成し管理します。<p>
    また、デバイス接続時・切断時にクラスドライバへのコールバックの引数として本構造体は使われます。<p>
    クラスドライバはデバイス接続時のコールバックで受け取った本構造体をクラスドライバ内部で保持し、
    各APIの引数として直接、またはUSBコントロールブロックのメンバ等として間接的に使用します。<p>
    クラスドライバはデバイス接続時のコールバックで受け取った本構造体を解放する事を禁止します。
    また、メンバへの書き込みも禁止です。<p>
    生成タイミング ： デバイス接続時<p>
    削除タイミング ： デバイス切断時 */
struct usbd_usb_deviceinfo{

    uhs_ubit8_t     usbdev_DevNum;			/** デバイス番号 */
    uhs_sbit32_t    usbdev_DevSpeed;		/** デバイスのスピード */
        #define USB_DEVSPEED_HS         0	/** High-Speed */
        #define USB_DEVSPEED_FS         1	/** Full-Speed */
        #define USB_DEVSPEED_LS         2	/** Low-Speed */

    struct usb_device_descriptor *usbdev_DevDescriptor;	/** デバイスディスクリプタ */
    uhs_ubit8_t     * raw_config;			/** ゲットディスクリプタ・コンフィグレーション発行時に
												受信したデータバッファポインタ */
    struct drv_usb_configuration_descriptor *Drv_ConfDescriptor;	/** コンフィグレーションディスクリプタ */
    uhs_ubit32_t    usbdev_EpMaxpktIn[16];	/** 各エンドポイントのマックスパケットサイズ */
    uhs_ubit32_t    usbdev_EpMaxpktOut[16];	/** 各エンドポイントのマックスパケットサイズ */
    uhs_ubit16_t    usbdev_EpHalt[2];		/** 各エンドポイントのHALT状態<p>
											    各ビットをフラグとして使用<p>
											    [0]･･･アウトエンドポイント<p>
											    [1]･･･インエンドポイント */
    uhs_ubit16_t    usbdev_EpToggle[2];		/** 各エンドポイントのHALT状態<p>
											    各ビットをフラグとして使用<p>
											    [0]･･･アウトエンドポイント<p>
											    [1]･･･インエンドポイント */
    struct usbd_usb_deviceinfo *usbdev_UpperHub;	/** 上位ハブのデバイス構造体アドレス */
    struct usbd_usb_deviceinfo *usbdev_LowerHub[USB_MAX_LOWER_DEV+1];	/** ハブの下位デバイス構造体アドレス<p>
    																	    [1]-[n]がポートに対応 */
    uhs_ubit8_t     usbdev_LanguageId[2];	/** 言語ID保存バッファ */
    uhs_sbit8_t     * usbdev_StringManu;	/** ベンダ情報格納バッファアドレス */
    uhs_sbit8_t     * usbdev_StringProduct;	/** 製造番号格納バッファアドレス */
    uhs_sbit8_t     * usbdev_StringSerial;	/** シリアル番号格納バッファアドレス */
    
    uhs_ubit8_t     usbdev_TotalConfig;		/** 全コンフィグ数 */
    uhs_ubit8_t     usbdev_ActConfig;		/** 現在設定されているコンフィグレーション番号 */
    void            *drv_info;				/** ドライバ情報格納バッファポインタ ⇒ unknown device はNULL */

    struct hcd_info * hcd_info;				/** 接続元のHCD情報 */

    void * hc_context;						/** HCD固有データ格納 */

    kernel_context_t    usbdev_sem;			/** USBデバイス保護用セマフォ */

    kernel_context_t    usbdev_mbx;			/** コントロール転送用メールボックス */

    uhs_boolean_t connect_status;			/** 接続状態ステータス */
    void * context;							/** コンテキストデータ格納 */

	struct split_infomation	split_info;		/**	split infomation */
};


/**	Sprit Transactionのエラー時にエラーが発生した転送要求に関する情報を格納する構造体<p>
    この情報は、CLEAR_TT_BUFFERを発行する際に必要な情報です。<p>
    生成タイミング ： Splitエラー検出時<p>
    削除タイミング ： SplitエラーCALLBACK完了後 */
struct	usbd_usb_spliterrinfo{

    uhs_ubit8_t					usbdev_DevNum;	/** デバイス番号 */
    uhs_ubit32_t				pipe;			/**	PIPE情報 */
	struct	split_infomation	split_info;		/**	split infomation */
};


// *************************************************************************************************
//	extern
// *************************************************************************************************
extern uhs_status_t Usb_Core_Constructor(void);
extern void         Usb_Core_Destructor(void);
extern uhs_status_t Usb_Core_DeviceEnumerate(struct usbd_usb_deviceinfo *usbdev);
extern uhs_status_t  Usb_Core_FreeConfDesc(struct drv_usb_configuration_descriptor * conf_ctrl);
extern void         Usb_Core_RelDevNumber(uhs_ubit8_t dev_num);

#endif	// __USBC_MAIN_H__

