⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smscoreapi.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
 * return client handle or NULL. * * @param coredev pointer to a coredev object returned by *                smscore_register_device * @param data_type client data type (SMS_DONT_CARE for all types) * @param id client id (SMS_DONT_CARE for all id) * */static structsmscore_client_t *smscore_find_client(struct smscore_device_t *coredev,				      int data_type, int id){	struct smscore_client_t *client = NULL;	struct list_head *next, *first;	unsigned long flags;	struct list_head *firstid, *nextid;	spin_lock_irqsave(&coredev->clientslock, flags);	first = &coredev->clients;	for (next = first->next;	     (next != first) && !client;	     next = next->next) {		firstid = &((struct smscore_client_t *)next)->idlist;		for (nextid = firstid->next;		     nextid != firstid;		     nextid = nextid->next) {			if ((((struct smscore_idlist_t *)nextid)->id == id) &&			    (((struct smscore_idlist_t *)nextid)->data_type == data_type ||			    (((struct smscore_idlist_t *)nextid)->data_type == 0))) {				client = (struct smscore_client_t *) next;				break;			}		}	}	spin_unlock_irqrestore(&coredev->clientslock, flags);	return client;}/** * find client by response id/type, call clients onresponse handler * return buffer to pool on error * * @param coredev pointer to a coredev object returned by *                smscore_register_device * @param cb pointer to response buffer descriptor * */void smscore_onresponse(struct smscore_device_t *coredev,			struct smscore_buffer_t *cb){	struct SmsMsgHdr_ST *phdr =		(struct SmsMsgHdr_ST *)((u8 *) cb->p + cb->offset);	struct smscore_client_t *client =		smscore_find_client(coredev, phdr->msgType, phdr->msgDstId);	int rc = -EBUSY;#if 1	static unsigned long last_sample_time; /* = 0; */	static int data_total; /* = 0; */	unsigned long time_now = jiffies_to_msecs(jiffies);	if (!last_sample_time)		last_sample_time = time_now;	if (time_now - last_sample_time > 10000) {		sms_debug("\ndata rate %d bytes/secs",			  (int)((data_total * 1000) /				(time_now - last_sample_time)));		last_sample_time = time_now;		data_total = 0;	}	data_total += cb->size;#endif	/* If no client registered for type & id,	 * check for control client where type is not registered */#if 0	if (!client)		client = smscore_find_client(coredev, 0, phdr->msgDstId);#endif	if (client)		rc = client->onresponse_handler(client->context, cb);	if (rc < 0) {		switch (phdr->msgType) {		case MSG_SMS_GET_VERSION_EX_RES:		{			struct SmsVersionRes_ST *ver =				(struct SmsVersionRes_ST *) phdr;			sms_debug("MSG_SMS_GET_VERSION_EX_RES "				  "id %d prots 0x%x ver %d.%d",				  ver->FirmwareId, ver->SupportedProtocols,				  ver->RomVersionMajor, ver->RomVersionMinor);			coredev->mode = ver->FirmwareId == 255 ?				DEVICE_MODE_NONE : ver->FirmwareId;			coredev->modes_supported = ver->SupportedProtocols;			complete(&coredev->version_ex_done);			break;		}		case MSG_SMS_INIT_DEVICE_RES:			sms_debug("MSG_SMS_INIT_DEVICE_RES");			complete(&coredev->init_device_done);			break;		case MSG_SW_RELOAD_START_RES:			sms_debug("MSG_SW_RELOAD_START_RES");			complete(&coredev->reload_start_done);			break;		case MSG_SMS_DATA_DOWNLOAD_RES:			complete(&coredev->data_download_done);			break;		case MSG_SW_RELOAD_EXEC_RES:			sms_debug("MSG_SW_RELOAD_EXEC_RES");			break;		case MSG_SMS_SWDOWNLOAD_TRIGGER_RES:			sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES");			complete(&coredev->trigger_done);			break;		case MSG_SMS_SLEEP_RESUME_COMP_IND:			complete(&coredev->resume_done);			break;		default:#if 0			sms_info("no client (%p) or error (%d), "				 "type:%d dstid:%d", client, rc,				 phdr->msgType, phdr->msgDstId);#endif			break;		}		smscore_putbuffer(coredev, cb);	}}/** * return pointer to next free buffer descriptor from core pool * * @param coredev pointer to a coredev object returned by *                smscore_register_device * * @return pointer to descriptor on success, NULL on error. */struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev){	struct smscore_buffer_t *cb = NULL;	unsigned long flags;	spin_lock_irqsave(&coredev->bufferslock, flags);	if (!list_empty(&coredev->buffers)) {		cb = (struct smscore_buffer_t *) coredev->buffers.next;		list_del(&cb->entry);	}	spin_unlock_irqrestore(&coredev->bufferslock, flags);	return cb;}/** * return buffer descriptor to a pool * * @param coredev pointer to a coredev object returned by *                smscore_register_device * @param cb pointer buffer descriptor * */void smscore_putbuffer(struct smscore_device_t *coredev,		       struct smscore_buffer_t *cb){	list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock);}static int smscore_validate_client(struct smscore_device_t *coredev,				   struct smscore_client_t *client,				   int data_type, int id){	struct smscore_idlist_t *listentry;	struct smscore_client_t *registered_client;	if (!client) {		sms_err("bad parameter.");		return -EFAULT;	}	registered_client = smscore_find_client(coredev, data_type, id);	if (registered_client == client)		return 0;	if (registered_client) {		sms_err("The msg ID already registered to another client.");		return -EEXIST;	}	listentry = kzalloc(sizeof(struct smscore_idlist_t), GFP_KERNEL);	if (!listentry) {		sms_err("Can't allocate memory for client id.");		return -ENOMEM;	}	listentry->id = id;	listentry->data_type = data_type;	list_add_locked(&listentry->entry, &client->idlist,			&coredev->clientslock);	return 0;}/** * creates smsclient object, check that id is taken by another client * * @param coredev pointer to a coredev object from clients hotplug * @param initial_id all messages with this id would be sent to this client * @param data_type all messages of this type would be sent to this client * @param onresponse_handler client handler that is called to *                           process incoming messages * @param onremove_handler client handler that is called when device is removed * @param context client-specific context * @param client pointer to a value that receives created smsclient object * * @return 0 on success, <0 on error. */int smscore_register_client(struct smscore_device_t *coredev,			    struct smsclient_params_t *params,			    struct smscore_client_t **client){	struct smscore_client_t *newclient;	/* check that no other channel with same parameters exists */	if (smscore_find_client(coredev, params->data_type,				params->initial_id)) {		sms_err("Client already exist.");		return -EEXIST;	}	newclient = kzalloc(sizeof(struct smscore_client_t), GFP_KERNEL);	if (!newclient) {		sms_err("Failed to allocate memory for client.");		return -ENOMEM;	}	INIT_LIST_HEAD(&newclient->idlist);	newclient->coredev = coredev;	newclient->onresponse_handler = params->onresponse_handler;	newclient->onremove_handler = params->onremove_handler;	newclient->context = params->context;	list_add_locked(&newclient->entry, &coredev->clients,			&coredev->clientslock);	smscore_validate_client(coredev, newclient, params->data_type,				params->initial_id);	*client = newclient;	sms_debug("%p %d %d", params->context, params->data_type,		  params->initial_id);	return 0;}/** * frees smsclient object and all subclients associated with it * * @param client pointer to smsclient object returned by *               smscore_register_client * */void smscore_unregister_client(struct smscore_client_t *client){	struct smscore_device_t *coredev = client->coredev;	unsigned long flags;	spin_lock_irqsave(&coredev->clientslock, flags);	while (!list_empty(&client->idlist)) {		struct smscore_idlist_t *identry =			(struct smscore_idlist_t *) client->idlist.next;		list_del(&identry->entry);		kfree(identry);	}	sms_info("%p", client->context);	list_del(&client->entry);	kfree(client);	spin_unlock_irqrestore(&coredev->clientslock, flags);}/** * verifies that source id is not taken by another client, * calls device handler to send requests to the device * * @param client pointer to smsclient object returned by *               smscore_register_client * @param buffer pointer to a request buffer * @param size size (in bytes) of request buffer * * @return 0 on success, <0 on error. */int smsclient_sendrequest(struct smscore_client_t *client,			  void *buffer, size_t size){	struct smscore_device_t *coredev;	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) buffer;	int rc;	if (client == NULL) {		sms_err("Got NULL client");		return -EINVAL;	}	coredev = client->coredev;	/* check that no other channel with same id exists */	if (coredev == NULL) {		sms_err("Got NULL coredev");		return -EINVAL;	}	rc = smscore_validate_client(client->coredev, client, 0,				     phdr->msgSrcId);	if (rc < 0)		return rc;	return coredev->sendrequest_handler(coredev->context, buffer, size);}#if 0/** * return the size of large (common) buffer * * @param coredev pointer to a coredev object from clients hotplug * * @return size (in bytes) of the buffer */int smscore_get_common_buffer_size(struct smscore_device_t *coredev){	return coredev->common_buffer_size;}/** * maps common buffer (if supported by platform) * * @param coredev pointer to a coredev object from clients hotplug * @param vma pointer to vma struct from mmap handler * * @return 0 on success, <0 on error. */static int smscore_map_common_buffer(struct smscore_device_t *coredev,				     struct vm_area_struct *vma){	unsigned long end = vma->vm_end,		      start = vma->vm_start,		      size = PAGE_ALIGN(coredev->common_buffer_size);	if (!(vma->vm_flags & (VM_READ | VM_SHARED)) ||	     (vma->vm_flags & VM_WRITE)) {		sms_err("invalid vm flags");		return -EINVAL;	}	if ((end - start) != size) {		sms_err("invalid size %d expected %d",			 (int)(end - start), (int) size);		return -EINVAL;	}	if (remap_pfn_range(vma, start,			    coredev->common_buffer_phys >> PAGE_SHIFT,			    size, pgprot_noncached(vma->vm_page_prot))) {		sms_err("remap_page_range failed");		return -EAGAIN;	}	return 0;}#endifstatic int __init smscore_module_init(void){	int rc = 0;	INIT_LIST_HEAD(&g_smscore_notifyees);	INIT_LIST_HEAD(&g_smscore_devices);	kmutex_init(&g_smscore_deviceslock);	INIT_LIST_HEAD(&g_smscore_registry);	kmutex_init(&g_smscore_registrylock);	/* USB Register */	rc = smsusb_register();	/* DVB Register */	rc = smsdvb_register();	sms_debug("rc %d", rc);	return rc;}static void __exit smscore_module_exit(void){	kmutex_lock(&g_smscore_deviceslock);	while (!list_empty(&g_smscore_notifyees)) {		struct smscore_device_notifyee_t *notifyee =			(struct smscore_device_notifyee_t *)				g_smscore_notifyees.next;		list_del(&notifyee->entry);		kfree(notifyee);	}	kmutex_unlock(&g_smscore_deviceslock);	kmutex_lock(&g_smscore_registrylock);	while (!list_empty(&g_smscore_registry)) {		struct smscore_registry_entry_t *entry =			(struct smscore_registry_entry_t *)				g_smscore_registry.next;		list_del(&entry->entry);		kfree(entry);	}	kmutex_unlock(&g_smscore_registrylock);	/* DVB UnRegister */	smsdvb_unregister();	/* Unregister USB */	smsusb_unregister();	sms_debug("");}module_init(smscore_module_init);module_exit(smscore_module_exit);MODULE_DESCRIPTION("Driver for the Siano SMS1XXX USB dongle");MODULE_AUTHOR("Siano Mobile Silicon,,, (doronc@siano-ms.com)");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -