static ssize_t dsm_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct dsm_client *client = file->private_data; size_t copy_size = 0; DSM_LOG_DEBUG("%s enter\n",__func__); if(!client) { DSM_LOG_ERR("client not bind\n"); goto out; } if(dsm_client_readable(client)) { copy_size = min(count, (client->used_size -client->read_size)); if(copy_to_user(buf, &client->dump_buff[client->read_size], copy_size)) DSM_LOG_ERR("copy to user failed\n"); client->read_size += copy_size; if(client->read_size >= client->used_size) dsm_client_set_idle(client); DSM_LOG_DEBUG("%d bytes read to user\n", copy_size); } out: DSM_LOG_DEBUG("%s exit\n",__func__); return copy_size; }
static int dsm_open(struct inode *inode, struct file *file) { DSM_LOG_DEBUG("%s enter\n",__func__); file->private_data = NULL; DSM_LOG_DEBUG("%s exit\n",__func__); return 0; }
/* notify work */ static void dsm_work_func(struct work_struct *work) { int i; struct dsm_client *client; DSM_LOG_DEBUG("%s enter\n", __func__); mutex_lock(&g_dsm_server.mtx_lock); smp_rmb(); for(i=0; i<CLIENT_SIZE; i++){ /* whether it is a valid client */ if(test_bit(DSM_CLIENT_VAILD_BIT, &g_dsm_server.client_flag[i])){ DSM_LOG_DEBUG("No.%d client name %s flag 0x%lx\n", i, g_dsm_server.client_list[i]->client_name, g_dsm_server.client_flag[i]); /* whether the client report error msg, clear a bit and return its old value */ if(!test_and_clear_bit(DSM_CLIENT_NOTIFY_BIT, &g_dsm_server.client_flag[i])) continue; client = g_dsm_server.client_list[i]; if(client == NULL){ DSM_LOG_INFO("%d client is null client.\n",i); continue; } /* wake up wait queue */ wake_up_interruptible_all(&client->waitq); DSM_LOG_INFO("%s finish notify\n", client->client_name); } } mutex_unlock(&g_dsm_server.mtx_lock); DSM_LOG_DEBUG("%s exit\n", __func__); return; }
static int dsm_close(struct inode *inode, struct file *file) { struct dsm_client *client = file->private_data; DSM_LOG_DEBUG("%s enter\n",__func__); if(client) dsm_unbind_client(client); DSM_LOG_DEBUG("%s exit\n",__func__); return 0; }
//cnotify format: |client name|,|error no|,|contents| static ssize_t dsm_cnotify_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { char client_name[CLIENT_NAME_LEN]= {0}; int size; int error_no = 0; struct dsm_client *client = NULL; char *strings = NULL; char *ptr; DSM_LOG_DEBUG("%s enter\n",__func__); strings = (char *)kzalloc(count, GFP_KERNEL); if(!strings) { DSM_LOG_ERR("dsm write malloc failed\n"); goto out; } memcpy(strings, buf, count); /*get client name*/ ptr = dsm_strtok(strings, ","); if(ptr) { size = strlen(ptr); size = (size < CLIENT_NAME_LEN) ? size : (CLIENT_NAME_LEN - 1); memcpy(client_name, ptr, size); } /*get error no*/ ptr = dsm_strtok(NULL, ","); if(ptr) error_no = dsm_atoi(ptr); /*get notify content*/ ptr = dsm_strtok(NULL, NULL); DSM_LOG_INFO("client name - %s, error no - %d\n", client_name, error_no); if(ptr) DSM_LOG_INFO("content - %s\n", ptr); client = dsm_find_client(client_name); if(client && (!dsm_client_ocuppy(client))) { DSM_LOG_DEBUG("dsm write find client - %s\n", client_name); if(ptr) dsm_client_copy(client, ptr, strlen(ptr)); dsm_client_notify(client, error_no); } else DSM_LOG_INFO("dsm notify can't find client - %s\n", client_name); out: if(strings) kfree(strings); DSM_LOG_DEBUG("%s exit\n",__func__); return count; }
static ssize_t dsm_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char client_name[CLIENT_NAME_LEN]={0}; int size; struct dsm_client *client = NULL; char *buff = NULL; char *ptr; DSM_LOG_DEBUG("%s enter\n",__func__); buff = (char *)kzalloc(count, GFP_KERNEL); if(!buff){ DSM_LOG_ERR("dsm write malloc failed\n"); goto out; } if(copy_from_user(buff, buf, count)){ DSM_LOG_ERR("dsm write copy failed\n"); goto out; } ptr = buff; while(*ptr){ if(*ptr == '\n') break; ptr++; } if(*ptr == '\n'){ size = ptr - buff; size = (size < CLIENT_NAME_LEN) ? size : (CLIENT_NAME_LEN - 1); memcpy(client_name, buff, size); client = dsm_find_client(client_name); if(client && (!dsm_client_ocuppy(client))){ DSM_LOG_DEBUG("dsm write find client - %s\n", client_name); ptr++;//ignore '/n' size = count - (ptr - buff); dsm_client_copy(client, ptr, size); dsm_client_notify(client, 20203); }else DSM_LOG_INFO("dsm write can't find client - %s\n", client_name); }else DSM_LOG_ERR("dsm write can't find client name\n"); out: if(buff) kfree(buff); DSM_LOG_DEBUG("%s exit\n",__func__); return count; }
struct dsm_client *dsm_find_client(char *cname) { int i; struct dsm_client * client = NULL; if (g_dsm_server.server_state != DSM_SERVER_INITED) { goto out; } mutex_lock(&g_dsm_server.mtx_lock); smp_rmb(); for(i=0; i<CLIENT_SIZE; i++) { if((test_bit(DSM_CLIENT_VAILD_BIT, &g_dsm_server.client_flag[i])) && (g_dsm_server.client_list[i]->client_name) && (!strncasecmp( g_dsm_server.client_list[i]->client_name, cname, CLIENT_NAME_LEN))) { client = g_dsm_server.client_list[i]; break; } } mutex_unlock(&g_dsm_server.mtx_lock); DSM_LOG_DEBUG("cname: %s find %s\n", cname, client?"success":"failed"); out: return client; }
static unsigned int dsm_poll(struct file *file, poll_table *wait) { struct dsm_client *client = file->private_data; unsigned int mask = 0; DSM_LOG_DEBUG("%s enter\n",__func__); if(!client){ DSM_LOG_ERR("dsm can't poll without client\n"); goto out; } DSM_LOG_DEBUG("client name :%s\n", client->client_name); poll_wait(file, &client->waitq, wait); if(test_bit(CBUFF_READY_BIT, &client->buff_flag)) mask = POLLIN | POLLRDNORM; out: DSM_LOG_DEBUG("%s exit, mask:%d\n",__func__, mask); return mask; }
static inline int copy_int_to_user(void __user *argp, int val) { int ret; int size; char buff[UINT_BUF_MAX]= {0}; size = snprintf(buff, UINT_BUF_MAX, "%d\n", val); ret = copy_to_user(argp, buff, size); DSM_LOG_DEBUG("%s result %d\n",__func__, ret); return ret; }
static void dsm_work_func(struct work_struct *work) { int i; struct dsm_client *client; DSM_LOG_DEBUG("%s enter\n", __func__); mutex_lock(&g_dsm_server.mtx_lock); smp_rmb(); for(i=0; i<CLIENT_SIZE; i++) { if(test_bit(DSM_CLIENT_VAILD_BIT, &g_dsm_server.client_flag[i])) { DSM_LOG_DEBUG("No.%d client name %s flag 0x%lx\n", i, g_dsm_server.client_list[i]->client_name, g_dsm_server.client_flag[i]); if(!test_and_clear_bit(DSM_CLIENT_NOTIFY_BIT, &g_dsm_server.client_flag[i])) continue; client = g_dsm_server.client_list[i]; wake_up_interruptible_all(&client->waitq); DSM_LOG_INFO("%s finish notify\n", client->client_name); } } mutex_unlock(&g_dsm_server.mtx_lock); DSM_LOG_DEBUG("%s exit\n", __func__); return; }
static void __init dsm_register_public_client(void) { int index; struct dsm_client *client = NULL; for(index = 0; index < ARRAY_SIZE(dsm_pub_clients); index++){ client = dsm_register_client(&dsm_pub_clients[index]); if(client) DSM_LOG_DEBUG("register %d public client - %s success\n", index, dsm_pub_clients[index].name); else DSM_LOG_ERR("register %d public client - %s failed\n", index, dsm_pub_clients[index].name); } }
static long dsm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; struct dsm_client *client = (struct dsm_client *)file->private_data; long ret = 0; int error = 0; char buff[CLIENT_NAME_LEN]= {0}; struct dsm_extern_client tmp_ext_client; DSM_LOG_DEBUG("%s enter,\n",__func__); switch (cmd) { case DSM_IOCTL_GET_CLIENT_COUNT: mutex_lock(&g_dsm_server.mtx_lock); error = g_dsm_server.client_count; mutex_unlock(&g_dsm_server.mtx_lock); DSM_LOG_INFO("client count :%d\n", error); ret = copy_int_to_user(argp, error); break; case DSM_IOCTL_BIND: if (copy_from_user(buff, argp, CLIENT_NAME_LEN)) { DSM_LOG_ERR("copy from user failed\n"); ret = -EFAULT; } else { DSM_LOG_DEBUG("try bind client %s\n", buff); client = dsm_find_client(buff); if(client) { dsm_bind_client(client); file->private_data = (void *)client; } else { ret = -ENXIO; } } break; case DSM_IOCTL_POLL_CLIENT_STATE: if(client && client->cops && client->cops->poll_state) { error = client->cops->poll_state(); DSM_LOG_INFO("poll %s state result :%d\n", client->client_name, error); ret = copy_int_to_user(argp, error); } else { DSM_LOG_ERR("dsm client not bound or poll not support\n"); ret = -ENXIO; } break; case DSM_IOCTL_FORCE_DUMP: if (copy_from_user(buff, argp, UINT_BUF_MAX)) { DSM_LOG_ERR("copy from user failed\n"); ret = -EFAULT; } else { if(client && client->cops && client->cops->dump_func) { if(!dsm_client_ocuppy(client)) { client->error_no = dsm_atoi(buff); client->used_size = client->cops->dump_func(client->error_no, (void *)client->dump_buff, (int)client->buff_size); set_bit(CBUFF_READY_BIT, &client->buff_flag); } else { DSM_LOG_INFO("client %s's buff ocuppy failed\n", client->client_name); ret = -EBUSY; } } else { DSM_LOG_ERR("dsm client not bound or dump not support\n"); ret = -ENXIO; } } break; case DSM_IOCTL_GET_CLIENT_ERROR: if(client) ret = copy_int_to_user(argp, client->error_no); else { DSM_LOG_ERR("dsm find client failed\n"); ret = -ENXIO; } break; case DSM_IOCTL_GET_DEVICE_NAME: if (client && client->device_name) { ret = copy_to_user(argp, client->device_name, DSM_MAX_DEVICE_NAME_LEN); } else { ret = -ENXIO; } break; case DSM_IOCTL_GET_IC_NAME: if (client && client->ic_name) { ret = copy_to_user(argp, client->ic_name, DSM_MAX_IC_NAME_LEN); } else { ret = -ENXIO; } break; case DSM_IOCTL_GET_MODULE_NAME: if (client && client->module_name) { ret = copy_to_user(argp, client->module_name, DSM_MAX_MODULE_NAME_LEN); } else { ret = -ENXIO; } break; case DSM_IOCTL_REGISTER_EXTERN_CLIENT: if (copy_from_user(&tmp_ext_client, (struct dsm_extern_client *)arg, sizeof(struct dsm_extern_client))) { ret = -EFAULT; } else { dsm_register_extern_client(&tmp_ext_client); } break; default: DSM_LOG_ERR("unknown ioctl command :%d\n", cmd); ret = -EINVAL; break; } DSM_LOG_DEBUG("%s exit\n",__func__); return ret; }
static ssize_t dsm_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char client_name[CLIENT_NAME_LEN]= {'\0'}; int size, error_no = 0; struct dsm_client *client = NULL; char *buff = NULL; char *ptr = NULL; #ifdef CONFIG_HUAWEI_SDCARD_VOLD char err_string[20] = {0}; int err; #endif DSM_LOG_DEBUG("%s enter\n",__func__); buff = (char *)kzalloc(count, GFP_KERNEL); if(!buff) { DSM_LOG_ERR("dsm write malloc failed\n"); goto out; } if(copy_from_user(buff, buf, count)) { DSM_LOG_ERR("dsm write copy failed\n"); goto out; } /*get client name*/ ptr = dsm_strtok(buff, ","); if(ptr) { size = strlen(ptr); size = (size < CLIENT_NAME_LEN) ? size : (CLIENT_NAME_LEN - 1); memcpy(client_name, ptr, size); } /*get error no*/ ptr = dsm_strtok(NULL, ","); if(ptr) { error_no = dsm_atoi(ptr); } /*get notify content*/ ptr = dsm_strtok(NULL, NULL); DSM_LOG_INFO("client name - %s, error no - %d\n", client_name, error_no); if(ptr) { DSM_LOG_INFO("content - %s\n", ptr); } client = dsm_find_client(client_name); #ifdef CONFIG_HUAWEI_SDCARD_VOLD if(client && !strncasecmp("sdcard_vold",client_name,size)&&(!dsm_client_ocuppy(client))) { DSM_LOG_DEBUG("dsm write find sdcard_vold\n"); ptr++; while(*ptr) { if(*ptr == '\n') break; ptr++; } if(*ptr == '\n') { memcpy(err_string,ptr-SDCARD_ERR_LEN,SDCARD_ERR_LEN); err_string[SDCARD_ERR_LEN] = '\0'; sscanf(err_string,"%d",&err); dsm_client_copy(client, ptr+1, (count - (ptr+1-buff))); dsm_client_notify(client, err); } } else if(client && (!dsm_client_ocuppy(client))) { #else if(client && (!dsm_client_ocuppy(client))) { #endif DSM_LOG_DEBUG("dsm write find client - %s\n", client_name); if(ptr) dsm_client_copy(client, ptr, strlen(ptr)); dsm_client_notify(client, error_no); } else { DSM_LOG_INFO("dsm notify can't find client - %s\n", client_name); } out: if(buff) kfree(buff); DSM_LOG_DEBUG("%s exit\n",__func__); return count; } static unsigned int dsm_poll(struct file *file, poll_table *wait) { struct dsm_client *client = file->private_data; unsigned int mask = 0; DSM_LOG_DEBUG("%s enter\n",__func__); if(!client) { DSM_LOG_ERR("dsm can't poll without client\n"); goto out; } DSM_LOG_DEBUG("client name :%s\n", client->client_name); poll_wait(file, &client->waitq, wait); if(test_bit(CBUFF_READY_BIT, &client->buff_flag)) mask = POLLIN | POLLRDNORM; out: DSM_LOG_DEBUG("%s exit, mask:%d\n",__func__, mask); return mask; } static int dsm_open(struct inode *inode, struct file *file) { DSM_LOG_DEBUG("%s enter\n",__func__); file->private_data = NULL; DSM_LOG_DEBUG("%s exit\n",__func__); return 0; }
/* sysfs write function */ static ssize_t dsm_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char client_name[CLIENT_NAME_LEN]={0}; int size; struct dsm_client *client = NULL; char *buff = NULL; char *ptr; char err_string[20] = {0}; int err; DSM_LOG_INFO("%s enter\n",__func__); /* try to get control of the write buffer */ if (down_trylock(&dsm_wbs)) { /* somebody else has it now; * if we're non-blocking, then exit... */ if (file->f_flags & O_NONBLOCK) { return -EAGAIN; } /* ...or if we want to block, then do so here */ if (down_interruptible(&dsm_wbs)) { /* something went wrong with wait */ return -ERESTARTSYS; } } buff = (char *)kzalloc(count, GFP_KERNEL); if(!buff){ DSM_LOG_ERR("dsm write malloc failed\n"); goto out; } if(copy_from_user(buff, buf, count)){ DSM_LOG_ERR("dsm write copy failed\n"); goto out; } buff[count-1] = '\0'; ptr = buff; while(*ptr){ if(*ptr == '\n') break; ptr++; } /* get the client name */ if(*ptr == '\n') { size = ptr - buff; size = (size < CLIENT_NAME_LEN) ? size : (CLIENT_NAME_LEN - 1); memcpy(client_name, buff, size); DSM_LOG_INFO( "%s client name is: %s \n", __func__ ,client_name ); client = dsm_find_client(client_name); if( client ) { /* found client name */ DSM_LOG_DEBUG("dsm write find client - %s\n", client_name); ptr++; while(*ptr) { if(*ptr == '\n') break; ptr++; } /* get error number */ if(*ptr == '\n') { memcpy(err_string,ptr-DSM_ERR_LEN,DSM_ERR_LEN); err_string[DSM_ERR_LEN] = '\0'; sscanf(err_string,"%d",&err); DSM_LOG_INFO( "%s error number is: %d \n", __func__ ,err ); /* judge if the err number is legal */ if( (err >= DMS_ERR_NUM_MIN ) && (err < DMS_ERR_NUM_MAX) ) { /* report the error */ dsm_client_copy(client, ptr+1, (count - (ptr+1-buff))); dsm_client_notify(client, err); } else { DSM_LOG_ERR("dsm write err number is not legal! err:%d\n", err); } } } else { DSM_LOG_INFO("dsm write can't find client - %s\n", client_name); } } else { DSM_LOG_ERR("dsm write can't find client name\n"); } out: if(buff) kfree(buff); DSM_LOG_DEBUG("%s exit\n", __func__); /* release the write buffer and wake anyone who's waiting for it */ up(&dsm_wbs); return count; }