| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 |
- #include <linux/module.h>
- #include <linux/device.h>
- #include <linux/fs.h>
- #include <linux/cdev.h>
- #include <linux/interrupt.h>
- #include <linux/spinlock.h>
- #include <linux/uaccess.h>
- #include <linux/mm.h>
- #include <linux/kfifo.h>
- #include <linux/firmware.h>
- #include <linux/syscalls.h>
- #include <linux/uaccess.h>
- #include <linux/platform_device.h>
- #include <linux/proc_fs.h>
- #include <ccci.h>
- struct ccci_node_t {
- char *name;
- char *type;
- int idx;
- int ext_num;
- };
- struct ccci_node_type_t {
- char *type;
- int major;
- int minor_start;
- int range;
- };
- struct ccci_node_type_table_t {
- int major;
- struct ccci_node_type_t array[CCCI_NODE_TYPE_NUM];
- };
- static struct ccci_node_t ccci1_node_list[] = {
- /* {"ccci_sys_rx", "std chr", 2, 0}, */
- /* {"ccci_sys_tx", "std chr", 3, 0}, */
- {"ccci_pcm_rx", "std chr", 4, 0},
- {"ccci_pcm_tx", "std chr", 5, 0},
- {"ccci_uem_rx", "std chr", 18, 0},
- {"ccci_uem_tx", "std chr", 19, 0},
- {"ccci_md_log_rx", "std chr", 42, 0},
- {"ccci_md_log_tx", "std chr", 43, 0},
- #ifdef CONFIG_MTK_ICUSB_SUPPORT
- {"ttyC", "tty", 0, 4},
- #else
- {"ttyC", "tty", 0, 3},
- #endif
- {"ccci_ipc_1220_0", "ipc", 0, 0}, /* used by AGPS */
- {"ccci_ipc_2", "ipc", 2, 0}, /* used by GPS */
- {"ccci_fs", "fs", 0, 0},
- #if defined(CONFIG_MTK_TC1_FEATURE)
- {"ccci_rpc", "rpc", 0, 0},
- #endif
- {"ccci_monitor", "vir chr", 0, 0},
- {"ccci_ioctl", "vir chr", 1, 5},
- };
- static struct ccci_node_t ccci2_node_list[] = {
- /* {"ccci2_sys_rx", "std chr", 2, 0}, */
- /* {"ccci2_sys_tx", "std chr", 3, 0}, */
- {"ccci2_pcm_rx", "std chr", 4, 0},
- {"ccci2_pcm_tx", "std chr", 5, 0},
- {"ccci2_uem_rx", "std chr", 18, 0},
- {"ccci2_uem_tx", "std chr", 19, 0},
- {"ccci2_md_log_rx", "std chr", 42, 0},
- {"ccci2_md_log_tx", "std chr", 43, 0},
- #ifdef CONFIG_MTK_ICUSB_SUPPORT
- {"ccci2_tty", "tty", 0, 4},
- #else
- {"ccci2_tty", "tty", 0, 3},
- #endif
- {"ccci2_ipc_", "ipc", 0, 1},
- {"ccci2_fs", "fs", 0, 0},
- #if defined(CONFIG_MTK_TC1_FEATURE)
- {"ccci2_rpc", "rpc", 0, 0},
- #endif
- {"ccci2_monitor", "vir chr", 0, 0},
- {"ccci2_ioctl", "vir chr", 1, 5},
- };
- static struct ccci_node_type_table_t ccci_node_type_table[MAX_MD_NUM];
- static void *dev_class;
- static void init_ccci_node_type_table(void)
- {
- int i;
- int curr = 0;
- int major;
- struct ccci_node_type_table_t *curr_table = NULL;
- memset(ccci_node_type_table, 0, sizeof(ccci_node_type_table));
- for (i = 0; i < MAX_MD_NUM; i++) {
- major = get_dev_major_for_md_sys(i);
- curr_table = &ccci_node_type_table[i];
- curr = 0;
- if (major < 0)
- continue;
- curr_table->major = major;
- curr_table->array[0].type = "std chr";
- curr_table->array[0].major = major;
- curr_table->array[0].minor_start = curr;
- curr_table->array[0].range = STD_CHR_DEV_NUM;
- curr += STD_CHR_DEV_NUM;
- curr_table->array[1].type = "ipc";
- curr_table->array[1].major = major;
- curr_table->array[1].minor_start = curr;
- curr_table->array[1].range = IPC_DEV_NUM;
- curr += IPC_DEV_NUM;
- curr_table->array[2].type = "fs";
- curr_table->array[2].major = major;
- curr_table->array[2].minor_start = curr;
- curr_table->array[2].range = FS_DEV_NUM;
- curr += FS_DEV_NUM;
- curr_table->array[3].type = "vir chr";
- curr_table->array[3].major = major;
- curr_table->array[3].minor_start = curr;
- curr_table->array[3].range = VIR_CHR_DEV_NUM;
- curr += VIR_CHR_DEV_NUM;
- curr_table->array[4].type = "tty";
- curr_table->array[4].major = major;
- curr_table->array[4].minor_start = curr;
- curr_table->array[4].range = TTY_DEV_NUM;
- curr += TTY_DEV_NUM;
- #if defined(CONFIG_MTK_TC1_FEATURE)
- curr_table->array[5].type = "rpc";
- curr_table->array[5].major = major;
- curr_table->array[5].minor_start = curr;
- curr_table->array[5].range = RPC_DEV_NUM;
- curr += RPC_DEV_NUM;
- #endif
- }
- }
- int get_md_id_by_dev_major(int dev_major)
- {
- int i;
- for (i = 0; i < MAX_MD_NUM; i++) {
- if (ccci_node_type_table[i].major == dev_major)
- return i;
- }
- return -1;
- }
- int get_dev_id_by_md_id(int md_id, char node_name[], int *major, int *minor)
- {
- int i;
- struct ccci_node_type_table_t *curr_table = NULL;
- curr_table = &ccci_node_type_table[md_id];
- for (i = 0; i < CCCI_NODE_TYPE_NUM; i++) {
- if (curr_table->array[i].type == NULL)
- break;
- if (strcmp(curr_table->array[i].type, node_name) == 0) {
- if (major != NULL)
- *major = curr_table->array[i].major;
- if (minor != NULL)
- *minor = curr_table->array[i].minor_start;
- return 0;
- }
- }
- return -1;
- }
- /***************************************************************************
- * Make device node helper function section
- ***************************************************************************/
- static void *create_dev_class(struct module *owner, const char *name)
- {
- int err = 0;
- struct class *dev_class = class_create(owner, name);
- if (IS_ERR(dev_class)) {
- err = PTR_ERR(dev_class);
- CCCI_MSG("create %s class fail: %d\n", name, err);
- return NULL;
- }
- return dev_class;
- }
- static int register_dev_node(void *dev_class, const char *name, int major_id,
- int minor_start_id, int index)
- {
- int ret = 0;
- dev_t dev;
- struct device *devices;
- if (index >= 0) {
- dev = MKDEV(major_id, minor_start_id) + index;
- devices =
- device_create((struct class *)dev_class, NULL, dev, NULL,
- "%s%d", name, index);
- } else {
- dev = MKDEV(major_id, minor_start_id);
- devices =
- device_create((struct class *)dev_class, NULL, dev, NULL,
- "%s", name);
- }
- if (IS_ERR(devices))
- ret = PTR_ERR(devices);
- return ret;
- }
- static void release_dev_node(void *dev_class, int major_id, int minor_start_id,
- int index)
- {
- dev_t dev;
- if (index >= 0) {
- dev = MKDEV(major_id, minor_start_id) + index;
- device_destroy((struct class *)dev_class, dev);
- } else {
- dev = MKDEV(major_id, minor_start_id);
- device_destroy((struct class *)dev_class, dev);
- }
- }
- /* ccci sysfs kobject */
- struct ccci_info_t {
- struct kobject kobj;
- unsigned int ccci_attr_count;
- };
- struct ccci_attribute_t {
- struct attribute attr;
- ssize_t (*show)(char *buf);
- ssize_t (*store)(const char *buf, size_t count);
- };
- #define CCCI_ATTR(_name, _mode, _show, _store)\
- struct ccci_attribute_t ccci_attr_##_name = {\
- .attr = { .name = __stringify(_name), .mode = _mode },\
- .show = _show,\
- .store = _store,\
- }
- ssize_t show_attr_version(char *buf)
- {
- return snprintf(buf, 16, "%d\n", 2); /* hardcode */
- }
- /* global vars */
- static struct ccci_info_t *ccci_sys_info;
- const struct sysfs_ops ccci_sysfs_ops = {
- .show = ccci_attr_show,
- .store = ccci_attr_store
- };
- CCCI_ATTR(boot, 0660, NULL, NULL);
- CCCI_ATTR(modem_info, 0644, NULL, NULL);
- CCCI_ATTR(md1_postfix, 0644, show_attr_md1_postfix, NULL);
- CCCI_ATTR(md2_postfix, 0644, show_attr_md2_postfix, NULL);
- CCCI_ATTR(version, 0644, show_attr_version, NULL);
- struct attribute *ccci_default_attrs[] = {
- &ccci_attr_boot.attr,
- &ccci_attr_modem_info.attr,
- &ccci_attr_md1_postfix.attr,
- &ccci_attr_md2_postfix.attr,
- &ccci_attr_version.attr,
- NULL
- };
- struct kobj_type ccci_ktype = {
- .release = ccci_attr_release,
- .sysfs_ops = &ccci_sysfs_ops,
- .default_attrs = ccci_default_attrs
- };
- /* common func implement */
- ssize_t ccci_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
- {
- ssize_t len = 0;
- struct ccci_attribute_t *a = container_of(attr, struct ccci_attribute_t, attr);
- if (a->show)
- len = a->show(buf);
- return len;
- }
- ssize_t ccci_attr_store(struct kobject *kobj, struct attribute *attr,
- const char *buf, size_t count)
- {
- ssize_t len = 0;
- struct ccci_attribute_t *a = container_of(attr, struct ccci_attribute_t, attr);
- if (a->store)
- len = a->store(buf, count);
- return len;
- }
- void ccci_attr_release(struct kobject *kobj)
- {
- struct ccci_info_t *ccci_info_temp = container_of(kobj, struct ccci_info_t, kobj);
- kfree(ccci_info_temp);
- ccci_sys_info = NULL;
- }
- ssize_t show_attr_md1_postfix(char *buf)
- {
- get_md_post_fix(MD_SYS1, buf, NULL);
- CCCI_MSG("md1: %s\n", buf);
- return strlen(buf);
- }
- ssize_t show_attr_md2_postfix(char *buf)
- {
- get_md_post_fix(MD_SYS2, buf, NULL);
- CCCI_MSG("md2: %s\n", buf);
- return strlen(buf);
- }
- int register_ccci_attr_func(const char *buf, ssize_t (*show) (char *),
- ssize_t (*store)(const char *, size_t))
- {
- int i = 0;
- struct ccci_attribute_t *ccci_attr_temp = NULL;
- while (ccci_default_attrs[i]) {
- if (!strncmp
- (ccci_default_attrs[i]->name, buf,
- strlen(ccci_default_attrs[i]->name))) {
- ccci_attr_temp =
- container_of(ccci_default_attrs[i],
- struct ccci_attribute_t, attr);
- break;
- }
- i++;
- }
- if (ccci_attr_temp) {
- ccci_attr_temp->show = show;
- ccci_attr_temp->store = store;
- return 0;
- }
- CCCI_MSG("fail to register ccci attibute!\n");
- return -1;
- }
- #define CCCI_KOBJ_NAME "ccci"
- int ccci_attr_install(void)
- {
- int ret = 0;
- ccci_sys_info = kmalloc(sizeof(struct ccci_info_t), GFP_KERNEL);
- if (!ccci_sys_info)
- return -ENOMEM;
- memset(ccci_sys_info, 0, sizeof(struct ccci_info_t));
- ret = kobject_init_and_add(&ccci_sys_info->kobj, &ccci_ktype,
- (struct kobject *)kernel_kobj, CCCI_KOBJ_NAME);
- if (ret < 0) {
- kobject_put(&ccci_sys_info->kobj);
- CCCI_MSG("fail to add ccci kobject in kernel\n");
- return ret;
- }
- ccci_sys_info->ccci_attr_count =
- sizeof(*ccci_default_attrs) / sizeof(struct attribute);
- return ret;
- }
- int init_ccci_dev_node(void)
- {
- int ret = 0;
- init_ccci_node_type_table();
- /* Make device class */
- dev_class = create_dev_class(THIS_MODULE, "ccci_node");
- if (dev_class == NULL)
- return -1;
- ret = ccci_attr_install();
- return ret;
- }
- void release_ccci_dev_node(void)
- {
- if (dev_class)
- class_destroy((struct class *)dev_class);
- if (ccci_sys_info) {
- if (&ccci_sys_info->kobj)
- kobject_put(&ccci_sys_info->kobj);
- kfree(ccci_sys_info);
- ccci_sys_info = NULL;
- }
- }
- int mk_ccci_dev_node(int md_id)
- {
- int i, j, major, minor, num;
- struct ccci_node_t *dev_node;
- int ret = 0;
- if (md_id == MD_SYS1) {
- dev_node = ccci1_node_list;
- num = sizeof(ccci1_node_list) / sizeof(struct ccci_node_t);
- } else if (md_id == MD_SYS2) {
- dev_node = ccci2_node_list;
- num = sizeof(ccci2_node_list) / sizeof(struct ccci_node_t);
- } else {
- return -1;
- }
- for (i = 0; i < num; i++) {
- if (get_dev_id_by_md_id(md_id, dev_node[i].type, &major, &minor)
- < 0)
- break;
- minor = minor + dev_node[i].idx;
- if (dev_node[i].ext_num == 0) {
- ret =
- register_dev_node(dev_class, dev_node[i].name,
- major, minor, -1);
- if (ret < 0)
- CCCI_MSG_INF(md_id, "cci",
- "create %s device fail: %d\n",
- dev_node[i].name, ret);
- } else {
- for (j = 0; j < dev_node[i].ext_num; j++) {
- ret =
- register_dev_node(dev_class,
- dev_node[i].name, major,
- minor, j);
- if (ret < 0) {
- CCCI_MSG_INF(md_id, "cci",
- "create %s device fail: %d\n",
- dev_node[i].name, ret);
- return ret;
- }
- }
- }
- }
- return ret;
- }
- void ccci_dev_node_exit(int md_id)
- {
- int i, j, major, minor, num;
- struct ccci_node_t *dev_node;
- if (md_id == MD_SYS1) {
- dev_node = ccci1_node_list;
- num = sizeof(ccci1_node_list) / sizeof(struct ccci_node_t);
- } else if (md_id == MD_SYS2) {
- dev_node = ccci2_node_list;
- num = sizeof(ccci2_node_list) / sizeof(struct ccci_node_t);
- } else {
- return;
- }
- for (i = 0; i < num; i++) {
- if (get_dev_id_by_md_id(md_id, dev_node[i].type, &major, &minor)
- < 0)
- break;
- minor = minor + dev_node[i].idx;
- if (dev_node[i].ext_num == 0) {
- release_dev_node(dev_class, major, minor, -1);
- } else {
- for (j = 0; j < dev_node[i].ext_num; j++)
- release_dev_node(dev_class, major, minor, j);
- }
- }
- }
|