usock.c.svn-base

来自「Linux下gsm/gprs modem的看守程序。支持短信发送与接受。」· SVN-BASE 代码 · 共 1,745 行 · 第 1/4 页

SVN-BASE
1,745
字号
	struct gsmd_signal_quality gsq;	char *comma;	gsq.rssi = atoi(resp + 6);	comma = strchr(resp, ',');	if (!comma ++)		return -EIO;	gsq.ber = atoi(comma);	return gsmd_ucmd_submit(ctx, GSMD_MSG_NETWORK, GSMD_NETWORK_SIGQ_GET,			cmd->id, sizeof(gsq), &gsq);}static int network_oper_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){	struct gsmd_user *gu = ctx;	const char *end, *opname;	int format, s, ret;	char *buf;	/* Format: <mode>[,<format>,<oper>] */	/* In case we're not registered, return an empty string.  */	if (sscanf(resp, "+COPS: %*i,%i,\"%n", &format, &s) <= 0)		end = opname = resp;	else {		/* If the phone returned the opname in a short or numeric		 * format, then it probably doesn't know the operator's full		 * name or doesn't support it.  Return any information we		 * have in this case.  */		if (format != 0)			gsmd_log(GSMD_NOTICE, "+COPS response in a format "					" different than long alphanumeric - "					" returning as is!\n");		opname = resp + s;		end = strchr(opname, '"');		if (!end)			return -EINVAL;	}	buf = strndup(opname, end - opname);	ret = gsmd_ucmd_submit(gu, GSMD_MSG_NETWORK, GSMD_NETWORK_OPER_GET,			cmd->id, end - opname + 1, buf);	free(buf);	return ret;}static int network_oper_n_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){	struct gsmd_user *gu = ctx;	char buf[16+1] = {'\0'};	struct gsm_extrsp *er;	er = extrsp_parse(cmd, resp);	if ( !er )		return -ENOMEM;	//extrsp_dump(er);		/* Format: <mode>[,<format>,<oper>] */	if ( er->num_tokens == 1 &&			er->tokens[0].type == GSMD_ECMD_RTT_NUMERIC ) {				/* In case we're not registered, return an empty string */		buf[0] = '\0';	}	else if ( er->num_tokens >= 3 &&			er->tokens[0].type == GSMD_ECMD_RTT_NUMERIC &&			er->tokens[1].type == GSMD_ECMD_RTT_NUMERIC &&			er->tokens[2].type == GSMD_ECMD_RTT_STRING ) {		strlcpy(buf, er->tokens[2].u.string, sizeof(buf));	}	else {		DEBUGP("Invalid Input : Parse error\n");		return -EINVAL;	}		talloc_free(er);	return gsmd_ucmd_submit(gu, GSMD_MSG_NETWORK, GSMD_NETWORK_OPER_N_GET,			cmd->id, sizeof(buf), buf);}static int network_opers_parse(const char *str, struct gsmd_msg_oper **out){	int len = 0;	struct gsm_extrsp *er;	char buf[64];	char *head, *tail, *ptr;	struct gsmd_msg_oper *out2;	if (strncmp(str, "+COPS: ", 7))		return -EINVAL;	/*	 * string ",," means the begginig of extended parameters and we	 * don't want to scan them for operators.	 */	ptr = strstr(str, ",,");	if(ptr)		ptr[0] = '\0';	ptr = (char *) str;	while (*str) {		if ( *str == '(' && isdigit(*(str+1)) ) {			len++;				str+=2;		}		else			str++;	}	*out = talloc_size(__gu_ctx, sizeof(struct gsmd_msg_oper) * (len + 1));	if (!out)		return -ENOMEM;	out2 = *out;	str = ptr;	while (*str) {		if ( *str == '(' )			head = (char *) str;		else if ( *str == ')' ) {			tail = (char *) str;						memset(buf, '\0', sizeof(buf));			strncpy(buf, head+1, (tail-head-1));			DEBUGP("buf: %s\n", buf);			er = extrsp_parse(gsmd_tallocs, buf);			if ( !er )				return -ENOMEM;			//extrsp_dump(er);								if ( er->num_tokens >= 4 &&					er->tokens[0].type == GSMD_ECMD_RTT_NUMERIC &&					er->tokens[1].type == GSMD_ECMD_RTT_STRING &&					er->tokens[2].type == GSMD_ECMD_RTT_STRING &&					er->tokens[3].type == GSMD_ECMD_RTT_STRING ) {								/*				 * +COPS=? +COPS: [list of supported (<stat>,long alphanumeric <oper>				 *       ,short alphanumeric <oper>,numeric <oper>)s]				 */								out2->stat = er->tokens[0].u.numeric;				strlcpy(out2->opname_longalpha, er->tokens[1].u.string,					sizeof(out2->opname_longalpha));				strlcpy(out2->opname_shortalpha, er->tokens[2].u.string,					sizeof(out2->opname_shortalpha));				strlcpy(out2->opname_num, er->tokens[3].u.string,					sizeof(out2->opname_num));			}			else {				DEBUGP("Invalid Input : Parse error\n");				talloc_free(*out);				return -EINVAL;			}			talloc_free(er);			out2->is_last = 0;			out2 ++;		}		str ++;	}	out2->is_last = 1;	return len;}static int network_opers_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){	struct gsmd_user *gu = ctx;	struct gsmd_msg_oper *buf = NULL;	int len, ret;	len = network_opers_parse(resp, &buf);	if(len < 0)		return len;	/* error we got from network_opers_parse */	ret = gsmd_ucmd_submit(gu, GSMD_MSG_NETWORK, GSMD_NETWORK_OPER_LIST,			cmd->id, sizeof(*buf) * (len + 1), buf);	talloc_free(buf);	return ret;}static int network_pref_opers_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){	struct gsmd_user *gu = (struct gsmd_user *) ctx;	struct gsmd_msg_prefoper entry;	int index;	char opname[17];	if (cmd->ret && cmd->ret != -255)		return 0;	/* TODO: Send a response */	if (sscanf(resp, "+CPOL: %i,0,\"%16[^\"]\"", &index, opname) < 2)		return -EINVAL;	/* TODO: Send a response */	entry.index = index;	entry.is_last = (cmd->ret == 0);	memcpy(entry.opname_longalpha, opname, sizeof(entry.opname_longalpha));	return gsmd_ucmd_submit(gu, GSMD_MSG_NETWORK, GSMD_NETWORK_PREF_LIST,			cmd->id, sizeof(entry), &entry);}static int network_pref_num_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){	struct gsmd_user *gu = (struct gsmd_user *) ctx;	int min_index, max_index, size;	if (cmd->ret)		return 0;	/* TODO: Send a response */	/* This is not a full general case, theoretically the range string	 * can include commas and more dashes, but we have no full parser for	 * ranges yet.  */	if (sscanf(resp, "+CPOL: (%i-%i)", &min_index, &max_index) < 2)		return -EINVAL;	/* TODO: Send a response */	size = max_index - min_index + 1;	return gsmd_ucmd_submit(gu, GSMD_MSG_NETWORK, GSMD_NETWORK_PREF_SPACE,			cmd->id, sizeof(size), &size);}static int network_ownnumbers_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){	struct gsmd_user *gu = (struct gsmd_user *) ctx;	struct gsmd_own_number *num;	int len, ret, type;	char dummy;	if (cmd->ret && cmd->ret != -255)		return 0;	/* TODO: Send a response */	if (sscanf(resp, "+CNUM: \"%*[^\"]\"%c%n", &dummy, &len) > 0)		len -= strlen("+CNUM: \"\",");	else		len = 0;	num = talloc_size(__gu_ctx, sizeof(*num) + len + 1);	if (len)		ret = sscanf(resp, "+CNUM: \"%[^\"]\",\"%32[^\"]\",%i,%*i,%i,",				num->name, num->addr.number,				&type, &num->service) - 1;	else		ret = sscanf(resp, "+CNUM: ,\"%32[^\"]\",%i,%*i,%i,",				num->addr.number,				&type, &num->service);	if (ret < 2) {		talloc_free(num);		return -EINVAL;	/* TODO: Send a response */	}	if (ret < 3)		num->service = GSMD_SERVICE_UNKNOWN;	num->name[len] = 0;	num->addr.type = type;	num->is_last = (cmd->ret == 0);	ret = gsmd_ucmd_submit(gu, GSMD_MSG_NETWORK, GSMD_NETWORK_GET_NUMBER,			cmd->id, sizeof(*num) + len + 1, num);	talloc_free(num);	return ret;}static int usock_rcv_network(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, 			     int len){	struct gsmd_atcmd *cmd;	struct gsmd_voicemail *vmail = (struct gsmd_voicemail *) gph->data;	gsmd_oper_numeric *oper = (gsmd_oper_numeric *) gph->data;	char buffer[15 + sizeof(gsmd_oper_numeric)];	int cmdlen;	switch (gph->msg_subtype) {	case GSMD_NETWORK_REGISTER:		if ((*oper)[0])			cmdlen = sprintf(buffer, "AT+COPS=1,2,\"%.*s\"",					sizeof(gsmd_oper_numeric), (char *)oper);		else			cmdlen = sprintf(buffer, "AT+COPS=0");		cmd = atcmd_fill(buffer, cmdlen + 1, &null_cmd_cb, gu, 0, NULL);		break;	case GSMD_NETWORK_DEREGISTER:		cmd = atcmd_fill("AT+COPS=2", 9+1, &null_cmd_cb, gu, 0, NULL);		break;	case GSMD_NETWORK_QUERY_REG:		cmd = atcmd_fill("AT+CREG?", 8+1, &network_query_reg_cb, gu, 0, NULL);		break;	case GSMD_NETWORK_VMAIL_GET:		cmd = atcmd_fill("AT+CSVM?", 8+1, &network_vmail_cb, gu, 0, NULL);		break;	case GSMD_NETWORK_VMAIL_SET:		cmdlen = sprintf(buffer, "AT+CSVM=1,\"%s\",%d",			vmail->addr.number, vmail->addr.type);		cmd = atcmd_fill(buffer, cmdlen + 1, &network_vmail_cb, gu, 0, NULL);		break;	case GSMD_NETWORK_SIGQ_GET:		cmd = atcmd_fill("AT+CSQ", 6+1, &network_sigq_cb, gu, 0, NULL);		break;	case GSMD_NETWORK_OPER_GET:		/* Set long alphanumeric format */		atcmd_submit(gu->gsmd, atcmd_fill("AT+COPS=3,0", 11+1,					&null_cmd_cb, gu, 0, NULL));		cmd = atcmd_fill("AT+COPS?", 8+1, &network_oper_cb, gu, 0, NULL);		break;	case GSMD_NETWORK_OPER_N_GET:		/* Set numeric format */		atcmd_submit(gu->gsmd, atcmd_fill("AT+COPS=3,2", 11+1,					&null_cmd_cb, gu, 0, NULL));		cmd = atcmd_fill("AT+COPS?", 8+1, &network_oper_n_cb, gu, 0, NULL);		break;	case GSMD_NETWORK_OPER_LIST:		cmd = atcmd_fill("AT+COPS=?", 9+1, &network_opers_cb, gu, 0, NULL);		break;	case GSMD_NETWORK_PREF_LIST:		/* Set long alphanumeric format */		atcmd_submit(gu->gsmd, atcmd_fill("AT+CPOL=,0", 10 + 1,					&null_cmd_cb, gu, 0, NULL));		cmd = atcmd_fill("AT+CPOL?", 8 + 1,				&network_pref_opers_cb, gu, 0, NULL);		break;	case GSMD_NETWORK_PREF_DEL:		cmdlen = sprintf(buffer, "AT+CPOL=%i", *(int *) gph->data);		cmd = atcmd_fill(buffer, cmdlen + 1, &null_cmd_cb, gu, 0, NULL);		break;	case GSMD_NETWORK_PREF_ADD:		cmdlen = sprintf(buffer, "AT+CPOL=,2,\"%.*s\"",				sizeof(gsmd_oper_numeric), (char *)oper);		cmd = atcmd_fill(buffer, cmdlen + 1, &null_cmd_cb, gu, 0, NULL);		break;	case GSMD_NETWORK_PREF_SPACE:		cmd = atcmd_fill("AT+CPOL=?", 9 + 1,				&network_pref_num_cb, gu, 0, NULL);		break;	case GSMD_NETWORK_GET_NUMBER:		cmd = atcmd_fill("AT+CNUM", 7 + 1,				&network_ownnumbers_cb, gu, 0, NULL);		break;	default:		return -EINVAL;	}	if (!cmd)		return -ENOMEM;	return atcmd_submit(gu->gsmd, cmd);}static int phonebook_find_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){	struct gsmd_user *gu = ctx;	struct gsmd_phonebooks gps;	struct gsm_extrsp *er;	DEBUGP("resp: %s\n", resp);	er = extrsp_parse(cmd, resp);	if ( !er )		return -ENOMEM;	gps.is_last = (cmd->ret == 0 || cmd->ret == 4)? 1:0;	if ( !strncmp(resp, "OK", 2) ) {		/* The record is empty or could not read yet */		gps.pb.index = 0;	}	else if ( !strncmp(resp, "+CME", 4) ) {		DEBUGP("== +CME error\n");		/* +CME ERROR: 21 */		gps.pb.index = 0 - atoi(strpbrk(resp, "0123456789"));	}	else if ( er->num_tokens == 4 &&			er->tokens[0].type == GSMD_ECMD_RTT_NUMERIC &&			er->tokens[1].type == GSMD_ECMD_RTT_STRING &&			er->tokens[2].type == GSMD_ECMD_RTT_NUMERIC &&			er->tokens[3].type == GSMD_ECMD_RTT_STRING ) {		/*		 * [+CPBR: <index1>,<number>,<type>,<text>[[...]		 * <CR><LF>+CPBR: <index2>,<unmber>,<type>,<text>]]		 */		gps.pb.index = er->tokens[0].u.numeric;		strlcpy(gps.pb.numb, er->tokens[1].u.string, GSMD_PB_NUMB_MAXLEN+1);		gps.pb.type = er->tokens[2].u.numeric;		strlcpy(gps.pb.text, er->tokens[3].u.string, GSMD_PB_TEXT_MAXLEN+1);	}	else {		DEBUGP("Invalid Input : Parse error\n");		return -EINVAL;	}		talloc_free(er);	return gsmd_ucmd_submit(gu, GSMD_MSG_PHONEBOOK, GSMD_PHONEBOOK_FIND,			cmd->id, sizeof(gps), &gps);}static int phonebook_read_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){	struct gsmd_user *gu = ctx;	struct gsmd_phonebook gp;	struct gsm_extrsp *er;	DEBUGP("resp: %s\n", resp);		er = extrsp_parse(cmd, resp);	if ( !er )		return -ENOMEM;		if ( !strncmp(resp, "OK", 2) ) {		/* The record is empty or could not read yet */		gp.index = 0;	}	else if ( !strncmp(resp, "+CME", 4) ) {		DEBUGP("+CME error\n");		/* +CME ERROR: 21 */		gp.index = 0 - atoi(strpbrk(resp, "0123456789"));	}	else if ( er->num_tokens == 4 &&			er->tokens[0].type == GSMD_ECMD_RTT_NUMERIC &&			er->tokens[1].type == GSMD_ECMD_RTT_STRING &&			er->tokens[2].type == GSMD_ECMD_RTT_NUMERIC &&			er->tokens[3].type == GSMD_ECMD_RTT_STRING ) {		/*		 * [+CPBR: <index1>,<number>,<type>,<text>[[...]

⌨️ 快捷键说明

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