static int radio_hci_smd_register_dev(struct radio_data *hsmd) { struct radio_hci_dev *hdev; int rc; hdev = kmalloc(sizeof(struct radio_hci_dev), GFP_KERNEL); hsmd->hdev = hdev; tasklet_init(&hsmd->rx_task, radio_hci_smd_recv_event, (unsigned long) hsmd); hdev->send = radio_hci_smd_send_frame; hdev->destruct = radio_hci_smd_destruct; /* Open the SMD Channel and device and register the callback function */ rc = smd_named_open_on_edge("APPS_FM", SMD_APPS_WCNSS, &hsmd->fm_channel, hdev, radio_hci_smd_notify_cmd); if (rc < 0) { FMDERR("Cannot open the command channel"); return -ENODEV; } smd_disable_read_intr(hsmd->fm_channel); if (radio_hci_register_dev(hdev) < 0) { FMDERR("Can't register HCI device"); return -ENODEV; } return 0; }
static void radio_hci_smd_notify_cmd(void *data, unsigned int event) { struct radio_hci_dev *hdev = hs.hdev; if (!hdev) { FMDERR("Frame for unknown HCI device (hdev=NULL)"); return; } switch (event) { case SMD_EVENT_DATA: tasklet_schedule(&hs.rx_task); break; case SMD_EVENT_OPEN: break; case SMD_EVENT_CLOSE: reset_worker = kzalloc(sizeof(*reset_worker), GFP_ATOMIC); if (!reset_worker) { FMDERR("Out of memory"); break; } INIT_WORK(reset_worker, send_disable_event); schedule_work(reset_worker); break; default: break; } }
static ssize_t fm_sinr_samples_write(struct file *filp, const char __user *userbuf, size_t count, loff_t *ppos) { char sinr_samples[10] = {0}; FMDBG("fm_sinr_samples_write enter. count:%d\n", (int)count); if (NULL == userbuf) { FMDERR("[%s]: Invlid value.line:%d\n",__FUNCTION__,__LINE__); return -EFAULT; } if ( 10 < count) { FMDERR("count value too much."); return -EFAULT; } if (copy_from_user(sinr_samples, userbuf, count)) return -EFAULT; g_sinr_samples = simple_strtol(sinr_samples, NULL, 10); FMDBG("fm_sinr_samples_write exit g_sinr_samples:%d\n", g_sinr_samples); return count; }
static char *get_bt_fm_device_name(void) { int i = 0; int arry_size = sizeof(bt_device_array)/sizeof(bt_device_array[0]); const char *bt_fm_chip_type = "BT_FM_UNKNOWN_DEVICE"; /* get bt/fm chip type from the device feature configuration (.xml file) */ bt_fm_chip_type = get_bt_fm_device_type(); FMDBG("get_bt_fm_device_name bt_fm_chip_type:%s", bt_fm_chip_type); if (NULL == bt_fm_chip_type) { FMDERR("BT-FM, Get chip type fail.\n"); return bt_device_array[arry_size - 1].dev_name; } /* lookup bt_device_model in bt_device_array[] */ for (i = 0; i < arry_size; i++) { if (0 == strncmp(bt_fm_chip_type,bt_device_array[i].chip_type,strlen(bt_device_array[i].chip_type))) { break; } } /* If we get invalid type name, return "Unknown".*/ if ( i == arry_size) { FMDERR("BT-FM, Get chip type fail.\n"); return bt_device_array[arry_size - 1].dev_name; } return bt_device_array[i].dev_name; }
static int fm_sinr_threshold_proc_show(struct seq_file *m, void *v) { int sinr_threshold = FM_SINR_MAX; int ret ; FMDBG("fm_sinr_threshold_proc_show enter\n"); ret = get_fm_sinr_threshold_string(&sinr_threshold); if (-1 == ret) { // 7 is the default value FMDERR("Get FM Sinr Threshold failed and will use default value 7.\n"); sinr_threshold = FM_SINR_7; } FMDBG("fm_sinr_threshold_proc_show g_sinr_threshold = %d .\n",g_sinr_threshold); /* if we changed the sinr value, get the new value. used for debug */ if (FM_SINR_MAX != g_sinr_threshold) { sinr_threshold = g_sinr_threshold; } FMDBG("fm_sinr_threshold_proc_show ,g_sinr_threshold = %d, sinr_threshold:%d\n", g_sinr_threshold, sinr_threshold); seq_printf(m, "%d", sinr_threshold); return 0; }
static int radio_hci_smd_send_frame(struct sk_buff *skb) { int len = 0; len = smd_write(hs.fm_channel, skb->data, skb->len); if (len < skb->len) { FMDERR("Failed to write Data %d", len); return -ENODEV; } return 0; }
const void *get_bt_fm_device_type(void) { int chip_type_len; struct device_node *dp = NULL; dp = of_find_node_by_path("/huawei_bt_info"); if (!of_device_is_available(dp)) { FMDERR("device is not available!\n"); return NULL; } return of_get_property(dp,"bt,chiptype", &chip_type_len); }
static void send_disable_event(struct work_struct *worker) { struct sk_buff *skb; unsigned char buf[6] = { 0x0f, 0x04, 0x01, 0x02, 0x4c, 0x00 }; int len = sizeof(buf); skb = alloc_skb(len, GFP_ATOMIC); if (!skb) { FMDERR("Memory not allocated for the socket"); return; } FMDERR("FM INSERT DISABLE Rx Event"); memcpy(skb_put(skb, len), buf, len); skb_orphan(skb); skb->dev = (struct net_device *)hs.hdev; radio_hci_recv_frame(skb); kfree(worker); }
int get_fm_sinr_samples(int *sinr) { int sinr_samples_len; struct device_node *dp = NULL; const char *psinr_samples = NULL; int sinr_samples; dp = of_find_node_by_path("/huawei_fm_info"); if (!dp) { FMDERR("device is not available!\n"); return -1; } psinr_samples = of_get_property(dp,"fm,sinr_samples", &sinr_samples_len); if (NULL == psinr_samples) { FMDERR("get sinr threshold value failed .\n"); return -1; } sinr_samples = simple_strtol(psinr_samples,NULL,10); *sinr = sinr_samples; return 0; }
static void radio_hci_smd_recv_event(unsigned long temp) { int len; int rc; struct sk_buff *skb; unsigned char *buf; struct radio_data *hsmd = &hs; len = smd_read_avail(hsmd->fm_channel); while (len) { skb = alloc_skb(len, GFP_KERNEL); if (!skb) { FMDERR("Memory not allocated for the socket"); return; } buf = kmalloc(len, GFP_KERNEL); if (!buf) { kfree_skb(skb); FMDERR("Error in allocating buffer memory"); return; } rc = smd_read_from_cb(hsmd->fm_channel, (void *)buf, len); memcpy(skb_put(skb, len), buf, len); skb_orphan(skb); skb->dev = (struct net_device *)hs.hdev; rc = radio_hci_recv_frame(skb); kfree(buf); len = smd_read_avail(hsmd->fm_channel); } }
static int bt_power_level_proc_show(struct seq_file *m, void *v) { const char *bt_power_level = NULL; bt_power_level = get_bt_power_level(); if (NULL != bt_power_level) { FMDBG("%s enter bt_power_level:%s;\n", __func__, bt_power_level); seq_printf(m, "%s", bt_power_level); } else { FMDERR("%s get bt_power_level failed;\n", __func__); } return 0; }
const void *get_bt_power_level(void) { int bt_power_level_len; struct device_node *dp = NULL; dp = of_find_node_by_path("/huawei_bt_info"); if (!dp) { FMDERR("device is not available!\n"); return NULL; } else { FMDBG("%s:dp->name:%s,dp->full_name:%s;\n", __func__, dp->name, dp->full_name); } return of_get_property(dp,"bt,power_level", &bt_power_level_len); }
static int bt_fm_ver_proc_show(struct seq_file *m, void *v) { const char *bt_fm_fw_ver = NULL; bt_fm_fw_ver = get_bt_fm_fw_ver(); if ( NULL != bt_fm_fw_ver ) { FMDBG("%s enter wifi_device_type:%s;\n", __func__,bt_fm_fw_ver); seq_printf(m,"%s",bt_fm_fw_ver); } else { FMDERR("%s get bt_fm_fw_ver failed;\n", __func__); } return 0; }
static int radio_hci_smd_init(void) { int ret; if (chan_opened) { FMDBG("Channel is already opened"); return 0; } /* this should be called with fm_smd_enable lock held */ ret = radio_hci_smd_register_dev(&hs); if (ret < 0) { FMDERR("Failed to register smd device"); chan_opened = false; return ret; } chan_opened = true; return ret; }
static void radio_hci_smd_notify_cmd(void *data, unsigned int event) { struct radio_hci_dev *hdev = hs.hdev; if (!hdev) { FMDERR("Frame for unknown HCI device (hdev=NULL)"); return; } switch (event) { case SMD_EVENT_DATA: tasklet_schedule(&hs.rx_task); break; case SMD_EVENT_OPEN: case SMD_EVENT_CLOSE: break; default: break; } }
static int fm_sinr_samples_proc_show(struct seq_file *m, void *v) { unsigned int sinr_samples = FM_SINR_SAMPLES_MAX; int ret; FMDBG("fm_sinr_samples_proc_show enter.\n"); ret = get_fm_sinr_samples(&sinr_samples); if (-1 == ret) { FMDERR("Get FM Sinr Samples failed and will use default value 10.\n"); sinr_samples = FM_SINR_SAMPLES_10; } if (FM_SINR_SAMPLES_MAX != g_sinr_samples) { sinr_samples = g_sinr_samples; } FMDBG("fm_sinr_samples_proc_show ,g_sinr_samples = %d, sinr_samples:%d\n", g_sinr_samples, sinr_samples); seq_printf(m, "%d", sinr_samples); return 0; }
/** * Initializes the module. * @return On success, 0. On error, -1, and <code>errno</code> is set * appropriately. */ static int __init featuretransfer_init(void) { int retval = 0; struct proc_dir_entry *ent = NULL; FMDBG("BT DEVICE FEATURE VERSION: %s", VERSION); /* Driver Register */ retval = platform_driver_register(&featuretransfer_driver); if (0 != retval) { FMDERR("[%s],featurntransfer driver register fail.",LOG_TAG); return retval; } /* create device_feature directory for bt chip info */ device_dir = proc_mkdir("device_feature", NULL); if (NULL == device_dir) { FMDERR("Unable to create /proc/device_feature directory"); return -ENOMEM; } /* create bt_feature for bluetooth feature */ bt_dir = proc_mkdir("bt_feature", device_dir); if (NULL == bt_dir) { FMDERR("Unable to create /proc/%s directory", PROC_DIR); return -ENOMEM; } /* Creating read/write "chiptype" entry for bluetooth chip type*/ ent = proc_create("chiptype", 0, bt_dir, &chiptype_proc_fops); if (NULL == ent) { FMDERR("Unable to create /proc/%s/chiptype entry", PROC_DIR); retval = -ENOMEM; goto fail; } /* Creating read/write "bt_fm_fw_ver" entry */ ent = proc_create("bt_fm_fw_ver", 0, bt_dir, &bt_fm_ver_proc_fops); if (NULL == ent) { FMDERR("Unable to create /proc/%s/bt_fm_fw_ver entry", PROC_DIR); retval = -ENOMEM; goto fail; } /* Creating read/write "bt_power_level" entry */ ent = proc_create("power_level", 0, bt_dir, &bt_power_level_proc_fops); if (NULL == ent) { FMDERR("Unable to create /proc/%s/power_level entry", PROC_DIR); retval = -ENOMEM; goto fail; } /* create fm_feature for fm feature */ fm_dir = proc_mkdir("fm_feature", device_dir); if (NULL == fm_dir) { FMDERR("Unable to create /proc/%s directory", PROC_DIR); return -ENOMEM; } /* Creating read/write "sinr" entry for bluetooth chip type*/ ent = proc_create("sinr_threshold", 0, fm_dir, &fm_sinr_threshold_proc_fops); if (NULL == ent) { FMDERR("Unable to create /proc/%s/sinr_threshold entry", PROC_DIR); retval = -ENOMEM; goto fail; } /* Creating read/write "rssi" entry for bcm4330 fm*/ ent = proc_create("sinr_samples", 0, fm_dir, &fm_sinr_samples_proc_fops); if (NULL == ent) { FMDERR("Unable to create /proc/%s/sinr_samples entry", PROC_DIR); retval = -ENOMEM; goto fail; } return 0; fail: remove_proc_entry("chiptype", bt_dir); remove_proc_entry("bt_fm_fw_ver", bt_dir); remove_proc_entry("power_level", bt_dir); remove_proc_entry("sinr_threshold", fm_dir); remove_proc_entry("sinr_samples", fm_dir); remove_proc_entry("bt_feature", device_dir); remove_proc_entry("fm_feature", device_dir); remove_proc_entry("device_feature", 0); return retval; }