static void usb_headset_detect(int type) { int state_h2w = 0; int state_usb = 0; HS_DBG(); mutex_lock(&hi->mutex_lock); state_h2w = switch_get_state(&hi->sdev_h2w); switch (type) { case USB_NO_HEADSET: hi->usb_headset.type = USB_NO_HEADSET; hi->usb_headset.status = STATUS_DISCONNECTED; state_h2w &= ~MASK_USB_HEADSET; state_usb = GOOGLE_USB_AUDIO_UNPLUG; HS_LOG_TIME("Remove USB_HEADSET (state %d, %d)", state_h2w, state_usb); break; case USB_AUDIO_OUT: hi->usb_headset.type = USB_AUDIO_OUT; hi->usb_headset.status = STATUS_CONNECTED_ENABLED; state_h2w |= BIT_USB_AUDIO_OUT; state_usb = GOOGLE_USB_AUDIO_ANLG; HS_LOG_TIME("Insert USB_AUDIO_OUT (state %d, %d)", state_h2w, state_usb); break; default: HS_LOG("Unknown headset type"); } switch_set_state(&hi->sdev_h2w, state_h2w); switch_set_state(&hi->sdev_usb_audio, state_usb); mutex_unlock(&hi->mutex_lock); }
void headset_ext_detect(int type) { HS_DBG(); switch (type) { case H2W_NO_HEADSET: /* Release Key */ case H2W_HEADSET: case H2W_35MM_HEADSET: case H2W_REMOTE_CONTROL: case H2W_USB_CRADLE: case H2W_UART_DEBUG: case H2W_TVOUT: break; case USB_NO_HEADSET: /* Release Key */ case USB_AUDIO_OUT: #ifdef CONFIG_SUPPORT_USB_SPEAKER case USB_AUDIO_OUT_DGTL: #endif usb_headset_detect(type); break; default: HS_LOG("Unknown headset type"); } }
static void headset_notifier_update(int id) { if (!hi) { HS_LOG("HS_MGR driver is not ready"); return; } switch (id) { case HEADSET_REG_HPIN_GPIO: break; case HEADSET_REG_REMOTE_ADC: update_mic_status(HS_DEF_MIC_DETECT_COUNT); break; case HEADSET_REG_REMOTE_KEYCODE: case HEADSET_REG_RPC_KEY: break; case HEADSET_REG_MIC_STATUS: update_mic_status(HS_DEF_MIC_DETECT_COUNT); break; case HEADSET_REG_MIC_BIAS: case HEADSET_REG_MIC_SELECT: case HEADSET_REG_KEY_INT_ENABLE: case HEADSET_REG_KEY_ENABLE: case HEADSET_REG_INDICATOR_ENABLE: break; default: break; } }
static struct file *openFile(char *path,int flag,int mode) { mm_segment_t old_fs; old_fs = get_fs(); set_fs(KERNEL_DS); fp=filp_open(path, flag, mode); set_fs(old_fs); if(IS_ERR(fp)) HS_LOG("File Open Error:%s",path); if(!fp->f_op) HS_LOG("File Operation Method Error!!"); if (fp) return fp; else return NULL; }
int hs_notify_key_event(int key_code) { struct button_work *work; HS_DBG(); if (hi->hs_35mm_type == HEADSET_UNKNOWN_MIC || hi->hs_35mm_type == HEADSET_NO_MIC || hi->h2w_35mm_type == HEADSET_NO_MIC) update_mic_status(HS_DEF_MIC_DETECT_COUNT); else if (!hs_hpin_stable()) { HS_LOG("The HPIN is unstable, SKIP THE BUTTON EVENT."); return 1; } else { work = kzalloc(sizeof(struct button_work), GFP_KERNEL); if (!work) { HS_ERR("Failed to allocate button memory"); return 1; } work->key_code = key_code; INIT_DELAYED_WORK(&work->key_work, button_35mm_work_func); queue_delayed_work(button_wq, &work->key_work, HS_JIFFIES_BUTTON); } return 1; }
static void onewire_init_work_func(struct work_struct *work) { HS_LOG("Open %s", hi->pdata.onewire_tty_dev); fp = openFile(hi->pdata.onewire_tty_dev,O_CREAT|O_RDWR|O_NONBLOCK,0666); if (fp != NULL) { if (!fp->private_data) HS_LOG("No private data"); else { HS_LOG("Private data exist"); closeFile(fp); return; } } else HS_LOG("%s, openFile is NULL pointer\n", __func__); closeFile(fp); }
int headset_notifier_register(struct headset_notifier *notifier) { if (!notifier->func) { HS_LOG("NULL register function"); return 0; } switch (notifier->id) { case HEADSET_REG_HPIN_GPIO: HS_LOG("Register HPIN_GPIO notifier"); hs_mgr_notifier.hpin_gpio = notifier->func; break; case HEADSET_REG_REMOTE_ADC: HS_LOG("Register REMOTE_ADC notifier"); hs_mgr_notifier.remote_adc = notifier->func; break; case HEADSET_REG_RPC_KEY: HS_LOG("Register RPC_KEY notifier"); hs_mgr_notifier.rpc_key = notifier->func; break; case HEADSET_REG_MIC_STATUS: HS_LOG("Register MIC_STATUS notifier"); hs_mgr_notifier.mic_status = notifier->func; break; case HEADSET_REG_MIC_BIAS: HS_LOG("Register MIC_BIAS notifier"); hs_mgr_notifier.mic_bias_enable = notifier->func; break; case HEADSET_REG_MIC_SELECT: HS_LOG("Register MIC_SELECT notifier"); hs_mgr_notifier.mic_select = notifier->func; break; case HEADSET_REG_KEY_INT_ENABLE: HS_LOG("Register KEY_INT_ENABLE notifier"); hs_mgr_notifier.key_int_enable = notifier->func; break; case HEADSET_REG_KEY_ENABLE: HS_LOG("Register KEY_ENABLE notifier"); hs_mgr_notifier.key_enable = notifier->func; break; default: HS_LOG("Unknown register ID"); return 0; } return 1; }
static void hs_1wire_deinit(void) { char all_zero = 0xaa; if (fp) { if (hi->pdata.tx_level_shift_en) gpio_set_value_cansleep(hi->pdata.tx_level_shift_en, 0); hr_msleep(20); writeFile(fp, &all_zero, 1); HS_LOG("Write 0xaa to unblock"); hr_msleep(10); HS_LOG("close file"); closeFile(fp); fp = NULL; if (hi->pdata.tx_level_shift_en) gpio_set_value_cansleep(hi->pdata.tx_level_shift_en, 1); } }
void headset_button_event(int is_press, int type) { HS_DBG(); if (!hs_hpin_stable()) { HS_LOG("The HPIN is unstable, SKIP THE BUTTON EVENT."); return; } if (!get_mic_state()) { HS_LOG("IGNORE key %d (Not support MIC)", type); return; } if (!is_press) button_released(type); else if (!atomic_read(&hi->btn_state)) button_pressed(type); }
static void irq_init_work_func(struct work_struct *work) { HS_DBG(); if (hi->pdata.hpin_gpio) { HS_LOG("Enable detect IRQ"); set_irq_type(hi->hpin_irq, IRQF_TRIGGER_LOW); enable_irq(hi->hpin_irq); } if (hi->pdata.key_gpio) { HS_LOG("Enable button IRQ"); hi->key_irq_type = IRQF_TRIGGER_LOW; set_irq_type(hi->key_irq, hi->key_irq_type); enable_irq(hi->key_irq); } }
static int headset_1wire_parse_dt(struct htc_hs_1wire_data *wire) { int i,ret = 0; const char *ttyname; u32 remoteadc[6] = {0}; struct device_node *dt = wire->dev->of_node; HS_LOG("%s", __func__); wire->pdata->tx_level_shift_en = of_get_named_gpio(dt, "hs_1wire,tx_level_shift_en", 0); if (gpio_is_valid(wire->pdata->tx_level_shift_en)) { HS_LOG("tx_lv_en:%d", wire->pdata->tx_level_shift_en); } else HS_LOG("tx_lv_en parser err"); ret = of_property_read_u32_array(dt, "hs_1wire,one_wire_remote", remoteadc, 6); if (ret < 0) { HS_LOG("remote parser failure"); } else { for (i = 0; i < ARRAY_SIZE(remoteadc); i++) { wire->pdata->one_wire_remote[i] = (char)remoteadc[i]; } HS_LOG("remote: %#x %#x %#x", remoteadc[0], remoteadc[1], remoteadc[2]); } ret = of_property_read_string(dt, "hs_1wire,onewire_tty_dev", &ttyname); if (ret < 0) { HS_LOG("tty_dev string parser failue"); } else { snprintf(wire->pdata->onewire_tty_dev, 15, "/dev/%s", ttyname); HS_LOG("tty=%s", wire->pdata->onewire_tty_dev); } return 0; }
static int hs_read_aid(void) { char in_buf[10]; int read_count, i; read_count = readFile(fp, in_buf, 10); HS_LOG("[1wire]read_count = %d", read_count); if (read_count > 0) { for (i = 0; i < read_count; i++) { HS_LOG("[1wire]in_buf[%d] = 0x%x", i, in_buf[i]); if ((in_buf[i] & 0xF0) == 0x80 && in_buf[i] > 0x80) { hi->aid = in_buf[i]; return 0; } } } return -1; }
static int hs_gpio_request_irq(unsigned int gpio, unsigned int *irq, irq_handler_t handler, unsigned long flags, const char *name, unsigned int wake) { int ret = 0; HS_DBG(); ret = gpio_request(gpio, name); if (ret < 0) return ret; ret = gpio_direction_input(gpio); if (ret < 0) { gpio_free(gpio); return ret; } if (!(*irq)) { ret = gpio_to_irq(gpio); if (ret < 0) { gpio_free(gpio); return ret; } HS_LOG("gpio_to_irq ret = %d", ret); *irq = (unsigned int) ret; } HS_LOG("[HS] irq=%d", *irq); ret = request_irq(*irq, handler, flags, name, NULL); if (ret < 0) { gpio_free(gpio); return ret; } ret = set_irq_wake(*irq, wake); if (ret < 0) { free_irq(*irq, 0); gpio_free(gpio); return ret; } return 1; }
static void hs_gpio_uart_set(int value) { value = !!value; if (value != headset_uart_enable) { headset_uart_enable = value; HS_LOG("%s headset uart", value? "enable": "disable"); gpio_set_value(hi->pdata.uart_gpio, value); } }
static struct file *openFile(char *path,int flag,int mode) { mm_segment_t old_fs; mutex_lock(&hi->mutex_lock); old_fs = get_fs(); set_fs(KERNEL_DS); HS_LOG("Open: fp count = %d", ++fp_count); fp=filp_open(path, flag, mode); set_fs(old_fs); if (!fp) return NULL; if(IS_ERR(fp)) HS_LOG("File Open Error:%s",path); if(!fp->f_op) HS_LOG("File Operation Method Error!!"); return fp; }
static int hs_1wire_report_type(char **string) { const int type_num = 3; /*How many 1-wire accessories supported*/ char *hs_type[] = { "headset_beats_20", "headset_mic_midtier", "headset_beats_solo_20", }; hi->aid &= 0x7f; HS_LOG("[1wire]AID = 0x%x", hi->aid); if (hi->aid > type_num || hi->aid < 1) { *string = "1wire_unknown"; return 14; }else { *string = hs_type[hi->aid - 1]; HS_LOG("Report %s type, size %d", *string, sizeof(hs_type[hi->aid -1])); return sizeof(hs_type[hi->aid -1]); } }
int closeFile(struct file *fp) { mm_segment_t old_fs; old_fs = get_fs(); set_fs(KERNEL_DS); HS_LOG("Close: fp count = %d", --fp_count); filp_close(fp,NULL); set_fs(old_fs); return 0; }
static int hs_8x60_remote_adc(int *adc) { int ret = 0; HS_DBG(); ret = pm8058_htc_config_mpp_and_adc_read(adc, 1, CHANNEL_ADC_HDSET, hi->pdata.adc_mpp, hi->pdata.adc_amux); if (ret) { *adc = -1; HS_LOG("Failed to read remote ADC"); return 0; } HS_LOG("Remote ADC %d (0x%X)", *adc, *adc); return 1; }
static int hs_1wire_report_type(char **string) { const int type_num = 3; char *hs_type[] = { "headset_mic_1wire", "headset_mic_midtier", "headset_mic_oneseg", }; hi->aid &= 0x7f; HS_LOG("[1wire]AID = 0x%x", hi->aid); if (hi->aid > type_num || hi->aid < 1) { *string = "1wire_unknown"; return 14; } else { *string = hs_type[hi->aid - 1]; HS_LOG("Report %s type, size %d", *string, sizeof(hs_type[hi->aid -1])); return sizeof(hs_type[hi->aid -1]); } }
/*One-wire button event handler*/ int button_1wire_work_func() { int cnt = 0; char a_buf[20]; int count = 0; int r,bflag; int key = 99; while(1){ bflag=0; r=readFile(fp,a_buf,10); if(r>0){ HS_LOG("Read %d bytes, count:%d, %s",r,count,a_buf); for(cnt = 0; cnt < r; cnt++){ HS_LOG("0x%x \n", (int) a_buf[cnt]); if ((int)a_buf[cnt]==123){ key = 3; bflag=1; } if ((int)a_buf[cnt]==125){ key = 1; bflag=1; } if ((int)a_buf[cnt]==126){ key = 2; bflag=1; } if ((int)a_buf[cnt]==127){ key = 0; bflag=1; } } } count++; if(bflag == 1 || count == CHECK_COUNT) break; msleep(1); } return key; }
static int hs_pmic_remote_threshold(uint32_t adc) { int i = 0; int ret = 0; uint32_t status; struct hs_pmic_rpc_request req; struct hs_pmic_rpc_reply rep; HS_DBG_LOG(); if (!(pmic_info->pdata.driver_flag & DRIVER_HS_PMIC_DYNAMIC_THRESHOLD)) return 0; req.hs_controller = cpu_to_be32(pmic_info->pdata.hs_controller); req.hs_switch = cpu_to_be32(pmic_info->pdata.hs_switch); req.current_uA = cpu_to_be32(HS_PMIC_HTC_CURRENT_THRESHOLD); for (i = 0; i < ARRAY_SIZE(current_threshold_lut); i++) { if (adc >= current_threshold_lut[i].adc_min && adc <= current_threshold_lut[i].adc_max) req.current_uA = cpu_to_be32(current_threshold_lut[i]. current_uA); } ret = msm_rpc_call_reply(endpoint_current, HS_PMIC_RPC_CLIENT_PROC_THRESHOLD, &req, sizeof(req), &rep, sizeof(rep), HS_RPC_TIMEOUT); if (ret < 0) { HS_LOG("Failed to send remote threshold RPC"); return 0; } else { status = be32_to_cpu(rep.status); if (status != HS_PMIC_RPC_ERR_SUCCESS) { HS_LOG("Failed to set remote threshold"); return 0; } } return 1; }
int hs_notify_key_event(int key_code) { struct button_work *work; HS_DBG(); if (hi->hs_35mm_type == HEADSET_INDICATOR) { HS_LOG("Not support remote control"); return 1; } if (hi->hs_35mm_type == HEADSET_UNKNOWN_MIC || hi->hs_35mm_type == HEADSET_NO_MIC || hi->h2w_35mm_type == HEADSET_NO_MIC) update_mic_status(HS_DEF_MIC_DETECT_COUNT); else if (hi->hs_35mm_type == HEADSET_UNSTABLE) update_mic_status(0); else if (!hs_hpin_stable()) { HS_LOG("IGNORE key %d (Unstable HPIN)", key_code); return 1; } else if (hi->hs_35mm_type == HEADSET_UNPLUG && hi->is_ext_insert == 1) { HS_LOG("MIC status is changed from float, re-polling to decide accessory type"); update_mic_status(HS_DEF_MIC_DETECT_COUNT); return 1; } else if (hi->hs_35mm_type == HEADSET_UNPLUG && hi->is_ext_insert == 1) { HS_LOG("MIC status is changed from float, re-polling to decide accessory type"); update_mic_status(HS_DEF_MIC_DETECT_COUNT); return 1; } else { work = kzalloc(sizeof(struct button_work), GFP_KERNEL); if (!work) { HS_ERR("Failed to allocate button memory"); return 1; } work->key_code = key_code; INIT_DELAYED_WORK(&work->key_work, button_35mm_work_func); queue_delayed_work(button_wq, &work->key_work, HS_JIFFIES_BUTTON); } return 1; }
static void enable_metrico_headset(int enable) { HS_DBG(); if (enable && !hi->metrico_status) { #if 0 enable_mos_test(1); #endif hi->metrico_status = 1; HS_LOG("Enable metrico headset"); } if (!enable && hi->metrico_status) { #if 0 enable_mos_test(0); #endif hi->metrico_status = 0; HS_LOG("Disable metrico headset"); } }
void headset_button_event(int is_press, int type) { HS_DBG(); if (hi->hs_35mm_type == HEADSET_UNPLUG && hi->h2w_35mm_type == HEADSET_UNPLUG) { HS_LOG("IGNORE key %d (HEADSET_UNPLUG)", type); return; } if (!hs_hpin_stable()) { HS_LOG("IGNORE key %d (Unstable HPIN)", type); return; } if (!is_press) button_released(type); else if (!atomic_read(&hi->btn_state)) button_pressed(type); }
static void button_35mm_work_func(struct work_struct *work) { int key; struct button_work *works; wake_lock_timeout(&hi->hs_wake_lock, HS_WAKE_LOCK_TIMEOUT); HS_DBG(); works = container_of(work, struct button_work, key_work.work); hi->key_level_flag = works->key_code; if (hi->key_level_flag) { switch (hi->key_level_flag) { case 1: HS_LOG("3.5mm RC: Play Pressed"); key = HS_MGR_KEYCODE_MEDIA; break; case 2: HS_LOG("3.5mm RC: BACKWARD Pressed"); key = HS_MGR_KEYCODE_BACKWARD; break; case 3: HS_LOG("3.5mm RC: FORWARD Pressed"); key = HS_MGR_KEYCODE_FORWARD; break; default: HS_LOG("3.5mm RC: WRONG Button Pressed"); kfree(works); return; } headset_button_event(1, key); } else { /* key release */ if (atomic_read(&hi->btn_state)) headset_button_event(0, atomic_read(&hi->btn_state)); else HS_LOG("3.5mm RC: WRONG Button Release"); } kfree(works); }
static void update_mic_status(int count) { HS_DBG(); if (hi->is_ext_insert) { HS_LOG("Start MIC status polling (%d)", count); cancel_delayed_work_sync(&mic_detect_work); hi->mic_detect_counter = count; queue_delayed_work(detect_wq, &mic_detect_work, HS_JIFFIES_MIC_DETECT); } }
static int hs_pmic_remote_adc(int *adc) { int ret = 0; struct rpc_request_hdr req; struct hs_rpc_client_rep_adc rep; HS_DBG_LOG(); ret = msm_rpc_call_reply(endpoint_adc, HS_RPC_CLIENT_PROC_ADC, &req, sizeof(req), &rep, sizeof(rep), HS_RPC_TIMEOUT); if (ret < 0) { HS_LOG("Failed to read remote ADC"); return 0; } *adc = (int) be32_to_cpu(rep.adc); HS_LOG("Remote ADC %d (0x%X)", *adc, *adc); return 1; }
int closeFile(struct file *fp) { mm_segment_t old_fs; old_fs = get_fs(); set_fs(KERNEL_DS); HS_LOG("Close: fp count = %d", --fp_count); filp_close(fp,NULL); set_fs(old_fs); mutex_unlock(&hi->mutex_lock); wake_unlock(&onewire_open_wake_lock); return 0; }
/*One-wire button event handler*/ int button_1wire_work_func() { int cnt = 0; char a_buf[20]; int count = 0; int r,bflag; while(1){ bflag=0; r=readFile(fp,a_buf,10); if(r>0){ HS_LOG("Read %d bytes, count:%d, %s",r,count,a_buf); for(cnt = 0; cnt < r; cnt++){ HS_LOG("0x%x \n", (int) a_buf[cnt]); if ((int)a_buf[cnt]==49){ hi->key_level_flag = 3; bflag=1; } if ((int)a_buf[cnt]==50){ hi->key_level_flag = 1; bflag=1; } if ((int)a_buf[cnt]==51){ hi->key_level_flag = 2; bflag=1; } if ((int)a_buf[cnt]==52) bflag=1; } } count++; if(bflag == 1 || count == CHECK_COUNT) break; msleep(1); } return 1; }
static void cancel_button_work_func(struct work_struct *work) { int counter = 10, ret = 0; HS_DBG(); ret = cancel_delayed_work(&button_gpio_work); if (ret) HS_LOG("cancel_delayed_work &button_gpio_work ok"); while(counter--) { if(queue_delayed_work(button_wq, &button_gpio_work, unstable_jiffies)) { HS_LOG("queue_delayed_work &button_gpio_work ok"); break; } msleep(2); } queue_delayed_work(button_wq, &hs_key_irq_enable, irq_delay); }