| /* |
| * Copyright (C) 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef __FM_H__ |
| #define __FM_H__ |
| |
| #include <linux/ioctl.h> |
| #include <linux/time.h> |
| |
| typedef signed char fm_s8; |
| typedef signed short fm_s16; |
| typedef signed int fm_s32; |
| typedef signed long long fm_s64; |
| typedef unsigned char fm_u8; |
| typedef unsigned short fm_u16; |
| typedef unsigned int fm_u32; |
| typedef unsigned long long fm_u64; |
| typedef enum fm_bool { |
| fm_false = 0, |
| fm_true = 1 |
| } fm_bool; |
| |
| // scan sort algorithm |
| enum { |
| FM_SCAN_SORT_NON = 0, |
| FM_SCAN_SORT_UP, |
| FM_SCAN_SORT_DOWN, |
| FM_SCAN_SORT_MAX |
| }; |
| |
| // scan methods |
| enum { |
| FM_SCAN_SEL_HW = 0, // select hardware scan, advantage: fast |
| FM_SCAN_SEL_SW, // select software scan, advantage: more accurate |
| FM_SCAN_SEL_MAX |
| }; |
| |
| //***************************************************************************************** |
| //***********************************FM config for customer ******************************* |
| //***************************************************************************************** |
| #define FMR_RSSI_TH_LONG 0x0301 // FM radio long antenna RSSI threshold(11.375dBuV) |
| #define FMR_RSSI_TH_SHORT 0x02E0 // FM radio short antenna RSSI threshold(-1dBuV) |
| #define FMR_CQI_TH 0x00E9 // FM radio Channel quality indicator threshold(0x0000~0x00FF) |
| #define FMR_SEEK_SPACE 1 // FM radio seek space,1:100KHZ; 2:200KHZ |
| #define FMR_SCAN_CH_SIZE 40 // FM radio scan max channel size |
| #define FMR_BAND 1 // FM radio band, 1:87.5MHz~108.0MHz; 2:76.0MHz~90.0MHz; |
| // 3:76.0MHz~108.0MHz; 4:special |
| #define FMR_BAND_FREQ_L 875 // FM radio special band low freq(Default 87.5MHz) |
| #define FMR_BAND_FREQ_H 1080 // FM radio special band high freq(Default 108.0MHz) |
| #define FM_SCAN_SORT_SELECT FM_SCAN_SORT_NON |
| #define FM_SCAN_SELECT FM_SCAN_SEL_HW |
| #define FM_SCAN_SOFT_MUTE_GAIN_TH 3 // soft-mute threshold when software scan, rang: 0~3, |
| // 0 means better audio quality but less channel |
| #define FM_CHIP_DESE_RSSI_TH (-102) // rang: -102 ~ -72 |
| |
| //***************************************************************************************** |
| //***********************************FM config for engineer ******************************* |
| //***************************************************************************************** |
| #define FMR_MR_TH 0x01BD // FM radio MR threshold |
| #define ADDR_SCAN_TH 0xE0 // scan thrshold register |
| #define ADDR_CQI_TH 0xE1 // scan CQI register |
| //***************************************************************************************** |
| |
| #define FM_NAME "fm" |
| #define FM_DEVICE_NAME "/dev/fm" |
| |
| // errno |
| #define FM_SUCCESS 0 |
| #define FM_FAILED 1 |
| #define FM_EPARM 2 |
| #define FM_BADSTATUS 3 |
| #define FM_TUNE_FAILED 4 |
| #define FM_SEEK_FAILED 5 |
| #define FM_BUSY 6 |
| #define FM_SCAN_FAILED 7 |
| |
| // band |
| #define FM_BAND_UNKNOWN 0 |
| #define FM_BAND_UE 1 // US/Europe band 87.5MHz ~ 108MHz (DEFAULT) |
| #define FM_BAND_JAPAN 2 // Japan band 76MHz ~ 90MHz |
| #define FM_BAND_JAPANW 3 // Japan wideband 76MHZ ~ 108MHz |
| #define FM_BAND_SPECIAL 4 // special band between 76MHZ and 108MHz |
| #define FM_BAND_DEFAULT FM_BAND_UE |
| |
| #define FM_UE_FREQ_MIN 875 |
| #define FM_UE_FREQ_MAX 1080 |
| #define FM_JP_FREQ_MIN 760 |
| #define FM_JP_FREQ_MAX 1080 |
| #define FM_FREQ_MIN FMR_BAND_FREQ_L |
| #define FM_FREQ_MAX FMR_BAND_FREQ_H |
| #define FM_RAIDO_BAND FM_BAND_UE |
| |
| // space |
| #define FM_SPACE_UNKNOWN 0 |
| #define FM_SPACE_100K 1 |
| #define FM_SPACE_200K 2 |
| #define FM_SPACE_50K 5 |
| #define FM_SPACE_DEFAULT FM_SPACE_100K |
| |
| #define FM_SEEK_SPACE FMR_SEEK_SPACE |
| |
| // max scan channel num |
| #define FM_MAX_CHL_SIZE FMR_SCAN_CH_SIZE |
| // auto HiLo |
| #define FM_AUTO_HILO_OFF 0 |
| #define FM_AUTO_HILO_ON 1 |
| |
| // seek direction |
| #define FM_SEEK_UP 0 |
| #define FM_SEEK_DOWN 1 |
| |
| // seek threshold |
| #define FM_SEEKTH_LEVEL_DEFAULT 4 |
| |
| struct fm_tune_parm { |
| uint8_t err; |
| uint8_t band; |
| uint8_t space; |
| uint8_t hilo; |
| uint16_t freq; |
| }; |
| |
| struct fm_seek_parm { |
| uint8_t err; |
| uint8_t band; |
| uint8_t space; |
| uint8_t hilo; |
| uint8_t seekdir; |
| uint8_t seekth; |
| uint16_t freq; |
| }; |
| |
| struct fm_scan_parm { |
| uint8_t err; |
| uint8_t band; |
| uint8_t space; |
| uint8_t hilo; |
| uint16_t freq; |
| uint16_t ScanTBL[16]; |
| uint16_t ScanTBLSize; |
| }; |
| |
| struct fm_ch_rssi { |
| uint16_t freq; |
| int rssi; |
| }; |
| |
| enum fm_scan_cmd_t { |
| FM_SCAN_CMD_INIT = 0, |
| FM_SCAN_CMD_START, |
| FM_SCAN_CMD_GET_NUM, |
| FM_SCAN_CMD_GET_CH, |
| FM_SCAN_CMD_GET_RSSI, |
| FM_SCAN_CMD_GET_CH_RSSI, |
| FM_SCAN_CMD_MAX |
| }; |
| |
| struct fm_scan_t { |
| enum fm_scan_cmd_t cmd; |
| int ret; // 0, success; else error code |
| uint16_t lower; // lower band, Eg, 7600 -> 76.0Mhz |
| uint16_t upper; // upper band, Eg, 10800 -> 108.0Mhz |
| int space; // 5: 50KHz, 10: 100Khz, 20: 200Khz |
| int num; // valid channel number |
| void *priv; |
| int sr_size; // scan result buffer size in bytes |
| union { |
| uint16_t *ch_buf; // channel buffer |
| int *rssi_buf; // rssi buffer |
| struct fm_ch_rssi *ch_rssi_buf; //channel and RSSI buffer |
| } sr; |
| }; |
| |
| struct fm_seek_t { |
| int ret; // 0, success; else error code |
| uint16_t freq; |
| uint16_t lower; // lower band, Eg, 7600 -> 76.0Mhz |
| uint16_t upper; // upper band, Eg, 10800 -> 108.0Mhz |
| int space; // 5: 50KHz, 10: 100Khz, 20: 200Khz |
| int dir; // 0: up; 1: down |
| int th; // seek threshold in dbm(Eg, -95dbm) |
| void *priv; |
| }; |
| |
| struct fm_tune_t { |
| int ret; // 0, success; else error code |
| uint16_t freq; |
| uint16_t lower; // lower band, Eg, 7600 -> 76.0Mhz |
| uint16_t upper; // upper band, Eg, 10800 -> 108.0Mhz |
| int space; // 5: 50KHz, 10: 100Khz, 20: 200Khz |
| void *priv; |
| }; |
| |
| struct fm_softmute_tune_t { |
| fm_s32 rssi; // RSSI of current channel |
| fm_u16 freq; // current frequency |
| fm_bool valid; // current channel is valid(true) or not(false) |
| }; |
| |
| struct fm_rssi_req { |
| uint16_t num; |
| uint16_t read_cnt; |
| struct fm_ch_rssi cr[16*16]; |
| }; |
| |
| struct fm_hw_info { |
| int chip_id; |
| int eco_ver; |
| int rom_ver; |
| int patch_ver; |
| int reserve; |
| }; |
| |
| struct fm_search_threshold_t { |
| fm_s32 th_type;// 0, RSSI. 1,desense RSSI. 2,SMG. |
| fm_s32 th_val; //threshold value |
| fm_s32 reserve; |
| }; |
| |
| #define NEED_DEF_RDS 1 |
| |
| #if NEED_DEF_RDS |
| //For RDS feature |
| typedef struct { |
| uint8_t TP; |
| uint8_t TA; |
| uint8_t Music; |
| uint8_t Stereo; |
| uint8_t Artificial_Head; |
| uint8_t Compressed; |
| uint8_t Dynamic_PTY; |
| uint8_t Text_AB; |
| uint32_t flag_status; |
| } RDSFlag_Struct; |
| |
| typedef struct { |
| uint16_t Month; |
| uint16_t Day; |
| uint16_t Year; |
| uint16_t Hour; |
| uint16_t Minute; |
| uint8_t Local_Time_offset_signbit; |
| uint8_t Local_Time_offset_half_hour; |
| } CT_Struct; |
| |
| typedef struct { |
| int16_t AF_Num; |
| int16_t AF[2][25]; |
| uint8_t Addr_Cnt; |
| uint8_t isMethod_A; |
| uint8_t isAFNum_Get; |
| } AF_Info; |
| |
| typedef struct { |
| uint8_t PS[4][8]; |
| uint8_t Addr_Cnt; |
| } PS_Info; |
| |
| typedef struct { |
| uint8_t TextData[4][64]; |
| uint8_t GetLength; |
| uint8_t isRTDisplay; |
| uint8_t TextLength; |
| uint8_t isTypeA; |
| uint8_t BufCnt; |
| uint16_t Addr_Cnt; |
| } RT_Info; |
| |
| struct rds_raw_data { |
| int dirty; // indicate if the data changed or not |
| int len; // the data len form chip |
| uint8_t data[146]; |
| }; |
| |
| struct rds_group_cnt { |
| unsigned long total; |
| unsigned long groupA[16]; // RDS groupA counter |
| unsigned long groupB[16]; // RDS groupB counter |
| }; |
| |
| enum rds_group_cnt_opcode { |
| RDS_GROUP_CNT_READ = 0, |
| RDS_GROUP_CNT_WRITE, |
| RDS_GROUP_CNT_RESET, |
| RDS_GROUP_CNT_MAX |
| }; |
| |
| struct rds_group_cnt_req { |
| int err; |
| enum rds_group_cnt_opcode op; |
| struct rds_group_cnt gc; |
| }; |
| |
| typedef struct { |
| CT_Struct CT; |
| RDSFlag_Struct RDSFlag; |
| uint16_t PI; |
| uint8_t Switch_TP; |
| uint8_t PTY; |
| AF_Info AF_Data; |
| AF_Info AFON_Data; |
| uint8_t Radio_Page_Code; |
| uint16_t Program_Item_Number_Code; |
| uint8_t Extend_Country_Code; |
| uint16_t Language_Code; |
| PS_Info PS_Data; |
| uint8_t PS_ON[8]; |
| RT_Info RT_Data; |
| uint16_t event_status; |
| struct rds_group_cnt gc; |
| } RDSData_Struct; |
| |
| //valid Rds Flag for notify |
| typedef enum { |
| RDS_FLAG_IS_TP = 0x0001, // Program is a traffic program |
| RDS_FLAG_IS_TA = 0x0002, // Program currently broadcasts a traffic ann. |
| RDS_FLAG_IS_MUSIC = 0x0004, // Program currently broadcasts music |
| RDS_FLAG_IS_STEREO = 0x0008, // Program is transmitted in stereo |
| RDS_FLAG_IS_ARTIFICIAL_HEAD = 0x0010, // Program is an artificial head recording |
| RDS_FLAG_IS_COMPRESSED = 0x0020, // Program content is compressed |
| RDS_FLAG_IS_DYNAMIC_PTY = 0x0040, // Program type can change |
| RDS_FLAG_TEXT_AB = 0x0080 // If this flag changes state, a new radio text string begins |
| } RdsFlag; |
| |
| typedef enum { |
| RDS_EVENT_FLAGS = 0x0001, // One of the RDS flags has changed state |
| RDS_EVENT_PI_CODE = 0x0002, // The program identification code has changed |
| RDS_EVENT_PTY_CODE = 0x0004, // The program type code has changed |
| RDS_EVENT_PROGRAMNAME = 0x0008, // The program name has changed |
| RDS_EVENT_UTCDATETIME = 0x0010, // A new UTC date/time is available |
| RDS_EVENT_LOCDATETIME = 0x0020, // A new local date/time is available |
| RDS_EVENT_LAST_RADIOTEXT = 0x0040, // A radio text string was completed |
| RDS_EVENT_AF = 0x0080, // Current Channel RF signal strength too weak, need do AF switch |
| RDS_EVENT_AF_LIST = 0x0100, // An alternative frequency list is ready |
| RDS_EVENT_AFON_LIST = 0x0200, // An alternative frequency list is ready |
| RDS_EVENT_TAON = 0x0400, // Other Network traffic announcement start |
| RDS_EVENT_TAON_OFF = 0x0800, // Other Network traffic announcement finished. |
| RDS_EVENT_RDS = 0x2000, // RDS Interrupt had arrived durint timer period |
| RDS_EVENT_NO_RDS = 0x4000, // RDS Interrupt not arrived durint timer period |
| RDS_EVENT_RDS_TIMER = 0x8000 // Timer for RDS Bler Check. ---- BLER block error rate |
| } RdsEvent; |
| #endif |
| |
| typedef enum { |
| FM_I2S_ON = 0, |
| FM_I2S_OFF, |
| FM_I2S_STATE_ERR |
| } fm_i2s_state_e; |
| |
| typedef enum { |
| FM_I2S_MASTER = 0, |
| FM_I2S_SLAVE, |
| FM_I2S_MODE_ERR |
| } fm_i2s_mode_e; |
| |
| typedef enum { |
| FM_I2S_32K = 0, |
| FM_I2S_44K, |
| FM_I2S_48K, |
| FM_I2S_SR_ERR |
| } fm_i2s_sample_e; |
| |
| struct fm_i2s_setting { |
| int onoff; |
| int mode; |
| int sample; |
| }; |
| |
| typedef enum { |
| FM_RX = 0, |
| FM_TX = 1 |
| } FM_PWR_T; |
| |
| typedef struct fm_i2s_info { |
| int status; /* 0:FM_I2S_ON, 1:FM_I2S_OFF,2:error */ |
| int mode; /* 0:FM_I2S_MASTER, 1:FM_I2S_SLAVE,2:error */ |
| int rate; /* 0:FM_I2S_32K:32000,1:FM_I2S_44K:44100,2:FM_I2S_48K:48000,3:error */ |
| } fm_i2s_info_t; |
| |
| typedef enum { |
| FM_AUD_ANALOG = 0, |
| FM_AUD_I2S = 1, |
| FM_AUD_MRGIF = 2, |
| FM_AUD_ERR |
| } fm_audio_path_e; |
| |
| typedef enum { |
| FM_I2S_PAD_CONN = 0, |
| FM_I2S_PAD_IO = 1, |
| FM_I2S_PAD_ERR |
| } fm_i2s_pad_sel_e; |
| |
| typedef struct fm_audio_info { |
| fm_audio_path_e aud_path; |
| fm_i2s_info_t i2s_info; |
| fm_i2s_pad_sel_e i2s_pad; |
| } fm_audio_info_t; |
| |
| struct fm_cqi { |
| int ch; |
| int rssi; |
| int reserve; |
| }; |
| |
| struct fm_cqi_req { |
| uint16_t ch_num; |
| int buf_size; |
| char *cqi_buf; |
| }; |
| |
| typedef struct { |
| int freq; |
| int rssi; |
| } fm_desense_check_t; |
| |
| typedef struct { |
| uint16_t lower; // lower band, Eg, 7600 -> 76.0Mhz |
| uint16_t upper; // upper band, Eg, 10800 -> 108.0Mhz |
| int space; // 0x1: 50KHz, 0x2: 100Khz, 0x4: 200Khz |
| int cycle; // repeat times |
| } fm_full_cqi_log_t; |
| |
| // ********** ***********FM IOCTL define start ******************************* |
| #define FM_IOC_MAGIC 0xf5 |
| |
| #define FM_IOCTL_POWERUP _IOWR(FM_IOC_MAGIC, 0, struct fm_tune_parm*) |
| #define FM_IOCTL_POWERDOWN _IOWR(FM_IOC_MAGIC, 1, int32_t*) |
| #define FM_IOCTL_TUNE _IOWR(FM_IOC_MAGIC, 2, struct fm_tune_parm*) |
| #define FM_IOCTL_SEEK _IOWR(FM_IOC_MAGIC, 3, struct fm_seek_parm*) |
| #define FM_IOCTL_SETVOL _IOWR(FM_IOC_MAGIC, 4, uint32_t*) |
| #define FM_IOCTL_GETVOL _IOWR(FM_IOC_MAGIC, 5, uint32_t*) |
| #define FM_IOCTL_MUTE _IOWR(FM_IOC_MAGIC, 6, uint32_t*) |
| #define FM_IOCTL_GETRSSI _IOWR(FM_IOC_MAGIC, 7, int32_t*) |
| #define FM_IOCTL_SCAN _IOWR(FM_IOC_MAGIC, 8, struct fm_scan_parm*) |
| #define FM_IOCTL_STOP_SCAN _IO(FM_IOC_MAGIC, 9) |
| |
| //IOCTL and struct for test |
| #define FM_IOCTL_GETCHIPID _IOWR(FM_IOC_MAGIC, 10, uint16_t*) |
| #define FM_IOCTL_EM_TEST _IOWR(FM_IOC_MAGIC, 11, struct fm_em_parm*) |
| #define FM_IOCTL_RW_REG _IOWR(FM_IOC_MAGIC, 12, struct fm_ctl_parm*) |
| #define FM_IOCTL_GETMONOSTERO _IOWR(FM_IOC_MAGIC, 13, uint16_t*) |
| #define FM_IOCTL_GETCURPAMD _IOWR(FM_IOC_MAGIC, 14, uint16_t*) |
| #define FM_IOCTL_GETGOODBCNT _IOWR(FM_IOC_MAGIC, 15, uint16_t*) |
| #define FM_IOCTL_GETBADBNT _IOWR(FM_IOC_MAGIC, 16, uint16_t*) |
| #define FM_IOCTL_GETBLERRATIO _IOWR(FM_IOC_MAGIC, 17, uint16_t*) |
| |
| //IOCTL for RDS |
| #define FM_IOCTL_RDS_ONOFF _IOWR(FM_IOC_MAGIC, 18, uint16_t*) |
| #define FM_IOCTL_RDS_SUPPORT _IOWR(FM_IOC_MAGIC, 19, int32_t*) |
| |
| #define FM_IOCTL_RDS_SIM_DATA _IOWR(FM_IOC_MAGIC, 23, uint32_t*) |
| #define FM_IOCTL_IS_FM_POWERED_UP _IOWR(FM_IOC_MAGIC, 24, uint32_t*) |
| |
| //IOCTL for FM over BT |
| #define FM_IOCTL_OVER_BT_ENABLE _IOWR(FM_IOC_MAGIC, 29, int32_t*) |
| |
| //IOCTL for FM ANTENNA SWITCH |
| #define FM_IOCTL_ANA_SWITCH _IOWR(FM_IOC_MAGIC, 30, int32_t*) |
| #define FM_IOCTL_GETCAPARRAY _IOWR(FM_IOC_MAGIC, 31, int32_t*) |
| |
| //IOCTL for FM I2S Setting |
| #define FM_IOCTL_I2S_SETTING _IOWR(FM_IOC_MAGIC, 33, struct fm_i2s_setting*) |
| |
| #define FM_IOCTL_RDS_GROUPCNT _IOWR(FM_IOC_MAGIC, 34, struct rds_group_cnt_req*) |
| #define FM_IOCTL_RDS_GET_LOG _IOWR(FM_IOC_MAGIC, 35, struct rds_raw_data*) |
| |
| #define FM_IOCTL_SCAN_GETRSSI _IOWR(FM_IOC_MAGIC, 36, struct fm_rssi_req*) |
| #define FM_IOCTL_SETMONOSTERO _IOWR(FM_IOC_MAGIC, 37, int32_t) |
| #define FM_IOCTL_RDS_BC_RST _IOWR(FM_IOC_MAGIC, 38, int32_t*) |
| #define FM_IOCTL_CQI_GET _IOWR(FM_IOC_MAGIC, 39, struct fm_cqi_req*) |
| #define FM_IOCTL_GET_HW_INFO _IOWR(FM_IOC_MAGIC, 40, struct fm_hw_info*) |
| #define FM_IOCTL_GET_I2S_INFO _IOWR(FM_IOC_MAGIC, 41, fm_i2s_info_t*) |
| #define FM_IOCTL_IS_DESE_CHAN _IOWR(FM_IOC_MAGIC, 42, int32_t*) |
| #define FM_IOCTL_TOP_RDWR _IOWR(FM_IOC_MAGIC, 43, struct fm_top_rw_parm*) |
| #define FM_IOCTL_HOST_RDWR _IOWR(FM_IOC_MAGIC, 44, struct fm_host_rw_parm*) |
| |
| #define FM_IOCTL_PRE_SEARCH _IOWR(FM_IOC_MAGIC, 45,int32_t) |
| #define FM_IOCTL_RESTORE_SEARCH _IOWR(FM_IOC_MAGIC, 46,int32_t) |
| |
| #define FM_IOCTL_SET_SEARCH_THRESHOLD _IOWR(FM_IOC_MAGIC, 47, fm_search_threshold_t*) |
| |
| #define FM_IOCTL_GET_AUDIO_INFO _IOWR(FM_IOC_MAGIC, 48, fm_audio_info_t*) |
| |
| #define FM_IOCTL_SCAN_NEW _IOWR(FM_IOC_MAGIC, 60, struct fm_scan_t*) |
| #define FM_IOCTL_SEEK_NEW _IOWR(FM_IOC_MAGIC, 61, struct fm_seek_t*) |
| #define FM_IOCTL_TUNE_NEW _IOWR(FM_IOC_MAGIC, 62, struct fm_tune_t*) |
| |
| #define FM_IOCTL_SOFT_MUTE_TUNE _IOWR(FM_IOC_MAGIC, 63, struct fm_softmute_tune_t*)/*for soft mute tune*/ |
| #define FM_IOCTL_DESENSE_CHECK _IOWR(FM_IOC_MAGIC, 64, fm_desense_check_t*) |
| |
| //IOCTL for EM |
| #define FM_IOCTL_FULL_CQI_LOG _IOWR(FM_IOC_MAGIC, 70, fm_full_cqi_log_t *) |
| |
| #define FM_IOCTL_DUMP_REG _IO(FM_IOC_MAGIC, 0xFF) |
| |
| // ********** ***********FM IOCTL define end ******************************* |
| |
| enum group_idx { |
| mono = 0, |
| stereo, |
| RSSI_threshold, |
| HCC_Enable, |
| PAMD_threshold, |
| Softmute_Enable, |
| De_emphasis, |
| HL_Side, |
| Demod_BW, |
| Dynamic_Limiter, |
| Softmute_Rate, |
| AFC_Enable, |
| Softmute_Level, |
| Analog_Volume, |
| GROUP_TOTAL_NUMS |
| }; |
| |
| enum item_idx { |
| Sblend_OFF = 0, |
| Sblend_ON, |
| ITEM_TOTAL_NUMS |
| }; |
| |
| struct fm_ctl_parm { |
| uint8_t err; |
| uint8_t addr; |
| uint16_t val; |
| uint16_t rw_flag; // 0:write, 1:read |
| }; |
| |
| struct fm_em_parm { |
| uint16_t group_idx; |
| uint16_t item_idx; |
| uint32_t item_value; |
| }; |
| #endif // __FM_H__ |