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

📄 zjmdmdrv.c

📁 modem卡驱动程序源码modem卡驱动程序源码
💻 C
📖 第 1 页 / 共 3 页
字号:
*********************************************/
void InitModemVariable(struct MdmDesc *p_mdm)
{
	int i;
	if(!p_mdm) return;
	inb(DataPort[p_mdm->mdm_no]);
	inb(StatePort[p_mdm->mdm_no]);
	/* 初始化变量*/
	p_mdm->f_flags = 0;
	p_mdm->writed_head_flag = FALSE;
	atomic_set(&p_mdm->writed_head , p_mdm->writed_head_flag);
	atomic_set(&(p_mdm->expect_read_head),TRUE);
	atomic_set(&p_mdm->is_data_head,FALSE);
	p_mdm->head_at_last = 0;
	p_mdm->next_write_chl_id = 0;
	memset(p_mdm->cmd_buf,0,sizeof(p_mdm->cmd_buf));
	p_mdm->cbuf_readpos = 0;
	p_mdm->cbuf_writepos = 0;
	p_mdm->cmdable_len = 0;
	sema_init(&(p_mdm->cmd_sending_sem),1);
	init_waitqueue_head(&(p_mdm->wait_queue_cmd));
	for (i=0; i<CHL_NUM; i++)
	{
		p_mdm->ch_desc[i].chl_no = i;
		p_mdm->ch_desc[i].mdm_no = p_mdm->mdm_no;
		p_mdm->ch_desc[i].be_open = FALSE;
		/*init wait queue*/
		init_waitqueue_head(&(p_mdm->ch_desc[i].wait_queue_r));
		init_waitqueue_head(&(p_mdm->ch_desc[i].wait_queue_w));
		InitChannelVariable(&(p_mdm->ch_desc[i]));
	}
	return;
}


/**********************************************************
*根据探测modem卡的结果申请必须的内存资源
*并初始化所有资源
***********************************************************/
int InitDriverResource()
{
	int i,count = 0,size;
	struct MdmDesc *p_mdm = NULL;
	gp_mdm_res = NULL;
	g_MdmNum = 0;
	g_CurReadCardCount = 0;
	g_CurWriteCardCount = 0;
#ifdef _DEBUG
	amount_recv_bytes = 0;
	amount_send_bytes = 0;
	no_read_data = 0;
	max_no_read_data = 0;
	recv_first_data = FALSE;
	rbuf_full_times = 0;
	head_err = FALSE;
#endif

	memset(g_MdmNO,INVALID_MDMNO,sizeof(g_MdmNO));
	for (i=0; i<MDM_NUM; i++)
	{
		gp_MdmDesc[i] = NULL;
		if(DetectModem(i))
		{
			g_MdmNO[count++] = (u8)i;
			g_MdmNum++;
		}
	}
	if(g_MdmNum<1) return E_NONE_CARD;
	size = sizeof(struct MdmDesc) * g_MdmNum;
	gp_mdm_res = (char*)kmalloc(size,GFP_KERNEL);
	p_mdm = (struct MdmDesc*)gp_mdm_res;
	for (i=0; i<g_MdmNum; i++)
	{
		gp_MdmDesc[g_MdmNO[i]] = &p_mdm[i];
		gp_MdmDesc[g_MdmNO[i]]->mdm_no = g_MdmNO[i];
		InitModemVariable(gp_MdmDesc[g_MdmNO[i]]);
	}
	return NO_ERROR;
}

/*****************************************************
*释放驱动的相关资源
*****************************************************/
void FreeDriverResource()
{
	if(gp_mdm_res) kfree(gp_mdm_res);
	return;
}

/****************************************************
*Tasklet service routine
****************************************************/
void TastletRoutine(unsigned long arg)
{
	return;
}

/*******************************************************
标记tasklet任务
********************************************************/
void MarkTasklet()
{
	return;
			
}

/*****************************************************
* type:private
* 往命令缓冲中填入一个要发送的命令数据
******************************************************/
BOOL InfillByteToCmdBuff(struct MdmDesc *p_mdm,char data)
{
	if(CheckCmdBufferPointer(p_mdm) == FULL)
	{
#ifdef _DEBUG
		Log(INVALID_MDMNO,INVALID_CHLNO,"Command buffer of card %d is full!\n",p_mdm->mdm_no);
#endif
		return FALSE;
	}
	//d{
	Log(INVALID_MDMNO,INVALID_CHLNO,"Infill cmd 0x%.2x to card %d cbuff, len=%d\n",
			(u8)data,p_mdm->mdm_no,p_mdm->cmdable_len+1);
	//d}
	p_mdm->cmd_buf[p_mdm->cbuf_writepos]= data;
	p_mdm->cbuf_writepos++;
	p_mdm->cmdable_len++;
	return TRUE;
}

/******************************************************
* type:public
* 把要发送的命令数据写到命令缓冲
* 直到命令发送完才返回
******************************************************/
ERRNO SendCmdDataToMdm(char *CmdBuf,int size,u8 mdm_no)
{
	int writed_bytes = 0;	//已写的字节数
	unsigned long flags;
	struct MdmDesc *p_mdm;
	if(mdm_no>7) return -EINVAL;
	p_mdm = gp_MdmDesc[mdm_no];
	if(!p_mdm) return -EINVAL;
	if(down_interruptible(&(p_mdm->cmd_sending_sem)))
	{
#ifdef _DEBUG
		Log(33,33,"Send command failed return on down_interruptible()\n");
#endif
		return  -ERESTARTSYS;/*failure*/
	}
	while(writed_bytes < size)
	{
		if(!InfillByteToCmdBuff(p_mdm,CmdBuf[writed_bytes]))
		{
#ifdef _DEBUG
			Log(33,33,"Send command failed return on InfillByteToCmdBuff()\n");
#endif
			return E_SEND_CMD_FAIL;
		}
		writed_bytes++;
	}
	up(&(p_mdm->cmd_sending_sem));
	
	/*等待命令发完*/
	if(p_mdm->cmdable_len > 0 && !(p_mdm->f_flags & O_NONBLOCK))	//block access
	{
		save_flags(flags);
		cli();
		if(p_mdm->cmdable_len > 0)
		{
			restore_flags(flags);
			if(wait_event_interruptible(p_mdm->wait_queue_cmd,p_mdm->cmdable_len <= 0))
			{
#ifdef _DEBUG
				Log(33,33,"Send command failed return on wait_event_interruptible()\n");
#endif
				return -EFAULT;
			}
		}
		else
		{
			restore_flags(flags);
		}
	}
	return NO_ERROR;
}

/*********************************************
* type:private
* 发送命令给modem卡
**********************************************/
ERRNO SendCmd(u8 cmd_type,u8 mdm_no,u8 chl_no,char *phone)
{
	int len = 0;
	u8 cmd_buf[32];
	struct MdmDesc *p_mdm;
	struct ChannelDesc *p_ch;
	p_mdm = gp_MdmDesc[mdm_no];
	p_ch = &(p_mdm->ch_desc[chl_no]);
	if(!p_ch || !p_mdm) return E_SEND_CMD_FAIL;
	/* 构造命令包*/
	if(cmd_type == CMD_CALLOUT && phone!=NULL)
	{
		len = ConvertStrToBCD(phone,(char*)&(cmd_buf[2]));
	}
	
	if(cmd_type == CMD_REVOVER_HEAD)
	{
		cmd_buf[0] = 0x0;
		len = 1;
	}
	else
	{
		cmd_buf[0] = (len << 4) |chl_no | 0x08;
		cmd_buf[1] = cmd_type;
		len += 2;
	}
	if(SendCmdDataToMdm(cmd_buf,len,mdm_no) != NO_ERROR)
	{
#ifdef _DEBUG
		Log(mdm_no,chl_no,"Send command to channel %d-%d failed!\n",mdm_no,chl_no);
#endif
		return E_SEND_CMD_FAIL;		
	}
	switch(cmd_type)
	{
		case  CMD_CONNECT:
#ifdef _VERBOSE
			Log(mdm_no,chl_no,"Establish connect OK from channel %d-%d\n",mdm_no,chl_no);
#endif
			break;
		case  CMD_DISCONN:
			p_ch->connect = FALSE;
			p_ch->connect_state = INVALID_STATE;
#ifdef _VERBOSE
			Log(mdm_no,chl_no,"Desconnect!\n");
#endif
			break;
		case  CMD_CALLOUT:
#ifdef _VERBOSE
			if(phone)
				Log(mdm_no,chl_no,"Calling to %s ...\n",phone);
			else
				Log(mdm_no,chl_no,"Calling out ...\n");
#endif
			break;
		case  CMD_OPEN_CHL:
			p_ch->be_open = TRUE;
#ifdef _VERBOSE
			Log(mdm_no,chl_no,"Channel open!\n");
#endif
			break;
		case  CMD_SHUT_CHL:
			p_ch->be_open = FALSE;
#ifdef _VERBOSE
			Log(mdm_no,chl_no,"Channel shut down\n");
#endif
			break;
		case  CMD_DETECT:
#ifdef _VERBOSE
			Log(mdm_no,chl_no,"Detecting modem card...\n");
#endif
			break;
		case  CMD_QUERY_STATE:
#ifdef _VERBOSE
			Log(mdm_no,chl_no,"Query hangup state\n");
#endif
			break;
		case  CMD_REVOVER_HEAD:
#ifdef _DEBUG
			Log(mdm_no,chl_no,"Try to recover head error\n");
#endif
			break;		
		default:
#ifdef _DEBUG
			Log(mdm_no,chl_no,"Command error!\n");
#endif
			break;
	}
	return NO_ERROR;
}

/********************************************************
* type:private
* 从卡上读一个字节
********************************************************/
BOOL ReadOneByteFromCard(struct MdmDesc *p_mdm,char *data)
{
	u8 chl_id;
	char char_tmp;
	struct ChannelDesc *p_ch;
	chl_id = 0x07 & (p_mdm->head_at_last);
	p_ch = &(p_mdm->ch_desc[chl_id]);
	if(!(atomic_read(&p_mdm->expect_read_head)) &&	//不希望读到头,希望读到的是数据
		atomic_read(&p_mdm->is_data_head))			//最后一次读到的头是数据头
	{
		if (CheckReadBuffPointer(&(p_mdm->ch_desc[chl_id])) == FULL) //缓冲满,不能再读
		{
#ifdef _DEBUG
			rbuf_full_times++;
			Log(p_mdm->mdm_no,chl_id,"Read buffer full!\n");
#endif
			p_ch->rbuf_max_full_times++;
			if(p_ch->rbuf_max_full_times>MAX_FULL_TIMES)
			{
				CleanReadBuff(p_ch);
				p_mdm->f_flags = p_mdm->f_flags | O_NONBLOCK;
				SendCmd(CMD_DISCONN, p_mdm->mdm_no, chl_id, NULL);
#ifdef _DEBUG
				Log(p_mdm->mdm_no,chl_id,"Clean read buffer by driver!\n");
#endif
			}
			else if(!(p_mdm->f_flags & O_NONBLOCK))
			{
				wake_up_interruptible(&(p_ch->wait_queue_r));
			}
			return FALSE;
		}
	}
	char_tmp = inb(StatePort[p_mdm->mdm_no]);
	if((char_tmp & 0x01) == 1)	//无数据可读,马上返回
	{
#ifdef _DEBUG
		if(recv_first_data)
		{
			no_read_data++;
			if(no_read_data>max_no_read_data)
				max_no_read_data = no_read_data;
		}
#endif
		return FALSE;
	}
	*data = inb(DataPort[p_mdm->mdm_no]);
#ifdef _DEBUG
	if(!recv_first_data)
	{
		max_no_read_data = 0;
		recv_first_data = TRUE;
	}
	no_read_data = 0;
#endif
	if(!(p_mdm->f_flags & O_NONBLOCK) && 
		!(atomic_read(&p_mdm->expect_read_head)) &&
		atomic_read(&p_mdm->is_data_head))
	{
		wake_up_interruptible(&(p_ch->wait_queue_r));
	}
	return TRUE;
}

/**********************************************************
* type:private
* 将收到卡上读到的数据存到读缓冲
**********************************************************/
void PutDataOfCardToReadBuf(struct ChannelDesc *p_ch,char data)
{
//	if(!(p_ch->connect))
//		return;
	p_ch->read_buf[p_ch->rbuf_writepos]= data;
	p_ch->rbuf_writepos++;
	p_ch->readable_len++;
	return;
}

/***********************************************
* type:private
* 处理卡上收到的命令
***********************************************/
void HandleCmdFromCard(struct MdmDesc *p_mdm,char cmd1,char cmd2)
{
	u8 chl_id;
	chl_id = 0x03 & cmd1;
	switch((u8)cmd2)
	{
	case CMD_CONN_SUCCESS:
		InitChannelVariable(&(p_mdm->ch_desc[chl_id]));
		p_mdm->ch_desc[chl_id].connect = TRUE;
		p_mdm->ch_desc[chl_id].connect_state = cmd2;
#ifdef _VERBOSE
		Log(p_mdm->mdm_no,chl_id,"Establish connect success\n");
#endif
		break;
	case CMD_CONN_FAIL:
		p_mdm->ch_desc[chl_id].connect = FALSE;
		p_mdm->ch_desc[chl_id].connect_state = INVALID_STATE;
#ifdef _DEBUG
		Log(p_mdm->mdm_no,chl_id,"Establish connect failed!Cause : Recv 0x%02x\n",(u8)cmd2);
#endif
		break;
	case CMD_HANGUP_BACK:
	case CMD_BRINGUP_BACK:
		p_mdm->ch_desc[chl_id].hangup_state = cmd2;
#ifdef _VERBOSE
		Log(p_mdm->mdm_no,chl_id,"Return hangup state : 0x%.2x\n",(u8)cmd2);
#endif
		break;
	default:
		break;
	}
	return;
}

/********************************************************
* type:private
* 从卡上读到一个有效数据,并分析
*********************************************************/
BOOL ReadAndAnalyseOne()
{
	char ch_recv;
	u8 chl_id;
	struct MdmDesc *p_mdm;
	struct ChannelDesc *p_ch;
	p_mdm = gp_MdmDesc[g_MdmNO[g_CurReadCardCount++]];
	if (!p_mdm)	return FALSE;
	if (p_mdm->mdm_no>=MDM_NUM) return FALSE;
	if(g_CurReadCardCount>=g_MdmNum)
		g_CurReadCardCount = 0;	
	if (!ReadOneByteFromCard(p_mdm,&ch_recv))		//没读到数据
		return FALSE;
	if(atomic_read(&p_mdm->expect_read_head))	//希望读到头
	{
		chl_id = 0x07 & ch_recv;
		if(chl_id>=CHL_NUM)		//头错误,通道号应该在[0,3]
		{
#ifdef _DEBUG
			head_err = TRUE;
			Log(p_mdm->mdm_no,chl_id,"Data head of card %d error!\n",p_mdm->mdm_no);
#endif
			for(chl_id=0; chl_id<CHL_NUM; chl_id++)
			{
				p_ch = &(p_mdm->ch_desc[chl_id]);
				if(!(p_ch->connect))
				{
					CleanReadBuff(p_ch);
					CleanWriteBuff(p_ch);
					p_mdm->f_flags = p_mdm->f_flags | O_NONBLOCK;
					SendCmd(CMD_DISCONN, p_mdm->mdm_no, chl_id, NULL);
#ifdef _DEBUG
					Log(p_mdm->mdm_no,chl_id,"Send \"CMD_DISCONN\" because received error head!\n");
#endif
				}
			}
			return FALSE;
		}
#ifdef _DEBUG
		else if(head_err)
		{
			head_err = FALSE;
			Log(p_mdm->mdm_no,chl_id,"Data head of card %d become to good since error at last!\n",p_mdm->mdm_no);
		}
#endif
		p_mdm->head_at_last = ch_recv;
		atomic_set(&p_mdm->expect_read_head,FALSE);
		if (ch_recv & 0x08)	//是命令头,下一字节是命令字
		{
			atomic_set(&p_mdm->is_data_head,FALSE);
		}
		else		//是数据头,下一字节是数据
		{
			atomic_set(&p_mdm->is_data_head,TRUE);
		}
	}
	else		//是数据或命令
	{
		atomic_set(&p_mdm->expect_read_head,TRUE);
		chl_id = 0x03 & (p_mdm->head_at_last);
		if(atomic_read(&p_mdm->is_data_head))
		{
		
#if defined _VERBOSE && defined _DEBUG
//			Log(p_mdm->mdm_no,chl_id,"Recv: \"0x%02x\", rbuff %d bytes,amount %ld bytes.\n",
	//			(u8)ch_recv,p_mdm->ch_desc[chl_id].readable_len,amount_recv_bytes++);
#endif

			PutDataOfCardToReadBuf(&(p_mdm->ch_desc[chl_id]),ch_recv);
		}
		else
		{
			HandleCmdFromCard(p_mdm, p_mdm->head_at_last, ch_recv);
		}
		p_mdm->head_at_last = 0;
	}
	return TRUE;
}

/******************************************************
* 发送一字节的命令数据
******************************************************/
BOOL SendOneByteCmdData(struct MdmDesc *p_mdm)
{
	char data;
	if (CheckCmdBufferPointer(p_mdm) == EMPTY)
	{
		return FALSE;
	}
	data = p_mdm->cmd_buf[p_mdm->cbuf_readpos];
	/* 向端口写出一个字节*/
	outb(data,DataPort[p_mdm->mdm_no]);
	p_mdm->cbuf_readpos++;
	p_mdm->cmdable_len--;
#ifdef _VERBOSE
	Log(INVALID_MDMNO,INVALID_CHLNO,"Send cmd 0x%.2x to card %d      , len=%d\n",
			(u8)data,p_mdm->mdm_no,p_mdm->cmdable_len);
#endif
	if(p_mdm->cmdable_len<=0 && !(p_mdm->f_flags & O_NONBLOCK))
	{
		wake_up_interruptible(&(p_mdm->wait_queue_cmd));
	}
	return TRUE;
}

/*******************************************************
改变要发送的通道号
*******************************************************/
inline void ChangeSendChlID(struct MdmDesc *p_mdm)
{
	p_mdm->next_write_chl_id++;
	if(p_mdm->next_write_chl_id>=CHL_NUM)
		p_mdm->next_write_chl_id = 0;
}

/******************************************************
* 产生要发送的数据
******************************************************/
BOOL GenerateSendData(struct MdmDesc *p_mdm,char *data)
{
	struct ChannelDesc *p_ch;
	u8 chl_id;
	chl_id = p_mdm->next_write_chl_id & 0x03;
	p_ch = &(p_mdm->ch_desc[chl_id]);
	/*头已经发送出去,数据是无论如何都要发送的,
	所以不做任何判断*/
	if (atomic_read(&p_mdm->writed_head))
	{
		*data = p_ch->write_buf[p_ch->wbuf_readpos];
		p_ch->wbuf_readpos++;
		p_ch->writeable_len--;
		p_ch->wbytes_after_pause++;
		ChangeSendChlID(p_mdm);
#ifdef _VERBOSE
//		Log(p_mdm->mdm_no,chl_id,"Send: \"0x%02x\". wbuf %d bytes,amount %ld bytes\n",
	//		(u8)(*data),p_ch->writeable_len,amount_send_bytes++);
#endif
	}
	else		//要发送头
	{
		if (CheckWriteBufferPointer(p_ch) == EMPTY)

⌨️ 快捷键说明

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