Open Source Telephony
 help / color / mirror / Atom feed
From: piggz1@gmail.com
To: denkenz@gmail.com,adam@piggz.co.uk,ofono@lists.linux.dev
Subject: Re: [PATCH v3 1/4] qmimodem: voicecall: Implement call dialing
Date: Thu, 4 Apr 2024 21:22:33 +0000	[thread overview]
Message-ID: <a28170.sbfspn.2v2btf-qmf@smtp.gmail.com> (raw)
In-Reply-To: <d79f7d16-9c77-4359-833f-0d6b3c1f1b36@gmail.com>



On Thursday, 4 April 2024, Denis Kenzior wrote:
> Hi Adam,
> 
> On 4/2/24 16:25, Adam Pigg wrote:
> > Add voicecall dialling to the qmimodem driver
> > Includes required infratructure and setup of the QMI services
> > 
> > Call State Handling
> > ===================
> > On initialisation, register the all_call_status_ind callback to be
> > called for QMI_VOICE_IND_ALL_STATUS.  This will handle notificatiof of
> > call status to the rest of the system
> > 
> > Dial Handling
> > =============
> > The dial function sets up the parameters for the QMI_VOICE_DIAL_CALL
> > service.  The parameters are the number to be called and the call type,
> > which is currently hard coded to be QMI_VOICE_CALL_TYPE_VOICE.  The
> > dial_cb callback wi then be called and will receive the call-id.
> > ---
> >   drivers/qmimodem/voice.h     |  17 ++
> >   drivers/qmimodem/voicecall.c | 479 ++++++++++++++++++++++++++++++++++-
> >   2 files changed, 495 insertions(+), 1 deletion(-)
> > 
> 
> <snip>
> 
> Couple of general comments:
> 
> - There's still an empty line @ EOF in this commit, please fix that.
> - After applying just this patch, compilation fails:
> 
> [denkenz@archdev ofono]$ make
> make --no-print-directory all-am
>    CC       drivers/qmimodem/voicecall.o
> drivers/qmimodem/voicecall.c: In function ‘all_call_status_ind’:
> drivers/qmimodem/voicecall.c:355:32: error: unused variable ‘vd’ 
> [-Werror=unused-variable]
>    355 |         struct voicecall_data *vd = ofono_voicecall_get_data(vc);
>        |                                ^~
> drivers/qmimodem/voicecall.c: At top level:
> drivers/qmimodem/voicecall.c:262:16: error: ‘ofono_to_qmi_direction’ defined but 
> not used [-Werror=unused-function]
>    262 | static uint8_t ofono_to_qmi_direction(enum call_direction ofono_direction)
>        |                ^~~~~~~~~~~~~~~~~~~~~~
> drivers/qmimodem/voicecall.c:97:13: error: ‘ofono_call_compare_by_status’ 
> defined but not used [-Werror=unused-function]
>     97 | static bool ofono_call_compare_by_status(const void *a, const void *b)
>        |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
> cc1: all warnings being treated as errors
> make[1]: *** [Makefile:4094: drivers/qmimodem/voicecall.o] Error 1
> make: *** [Makefile:2402: all] Error 2
> 
> Ideally, each patch should compile and run cleanly to help with 'git bisect'.
> 
> <snip>

Thanks for this, i think the issue might be compiler differences. It all builds ok for me, but sailfish is using gcc 8 atm, so i guess defaults have changed.


> 
> > +
> > +static bool ofono_call_compare_by_status(const void *a, const void *b)
> > +{
> > +	const struct ofono_call *call = a;
> > +	int status = L_PTR_TO_INT(b);
> > +
> > +	return status == call->status;
> > +}
> > +
> 
> This function belongs in patch 2.  It isn't used in this commit and is causing a 
> compiler warning / error.
> 
> <snip>
> 
> > +static uint8_t ofono_to_qmi_direction(enum call_direction ofono_direction)
> > +{
> > +	return ofono_direction + 1;
> > +}
> 
> This function isn't used, get rid of it
> 
> <snip>
> 
> > +static int qmi_voice_call_status(struct qmi_result *qmi_result,
> > +					struct qmi_voice_all_call_status_ind *result)
> 
> Right now you have this function producing an intermediate structure which 
> points to memory owned by struct qmi_result and is only valid as long as 
> qmi_result is valid.  all_call_status_ind() then converts this intermediate 
> structure into an l_queue with ofono_call objects.  The intermediate structure 
> is never needed after or used elsewhere.  No other caller uses this intermediate 
> structure.
> 
> Have you thought about having this function return an allocated l_queue with 
> ofono_call objects as contents instead and getting rid of struct 
> qmi_voice_all_call_status_ind completely?
> 
> > +{
> > +	int offset;
> > +	uint16_t len;
> > +	bool status = true;
> > +	const struct qmi_voice_remote_party_number *remote_party_number;
> > +	const struct qmi_voice_call_information *call_information;
> > +
> > +	static const uint8_t QMI_VOICE_ALL_CALL_STATUS_CALL_INFORMATION = 0x01;
> > +	static const uint8_t QMI_VOICE_ALL_CALL_STATUS_REMOTE_NUMBER = 0x10;
> > +	static const uint8_t QMI_VOICE_ALL_CALL_INFO_CALL_INFORMATION = 0x10;
> > +	static const uint8_t QMI_VOICE_ALL_CALL_INFO_REMOTE_NUMBER = 0x11;
> > +
> > +	/* mandatory */
> > +	call_information = qmi_result_get(
> > +		qmi_result, QMI_VOICE_ALL_CALL_STATUS_CALL_INFORMATION, &len);
> > +
> > +	if (!call_information) {
> > +		call_information = qmi_result_get(
> > +			qmi_result, QMI_VOICE_ALL_CALL_INFO_CALL_INFORMATION,
> > +			&len);
> > +		status = false;
> > +	}
> > +
> > +	if (call_information) {
> > +		/* verify the length */
> > +		if (len < sizeof(call_information->size))
> > +			return -EMSGSIZE;
> > +
> > +		if (len !=
> > +			call_information->size *
> > +			sizeof(struct qmi_voice_call_information_instance) +
> > +			sizeof(call_information->size))
> > +			return -EMSGSIZE;
> 
> doc/coding-style.txt item M4
> 
> > +
> > +		result->call_information_set = 1;
> > +		result->call_information = call_information;
> > +	} else
> > +		return -EBADMSG;
> 
> Easier to bail early and not nest or need the if condition:
> 
> if (!call_information)
> 	return -EBADMSG;
> 
> if (len < sizeof(call_information->size))
> 	return -EMSGSIZE;
> 
> ...
> 
> > +
> > +	/* mandatory */
> > +	remote_party_number = qmi_result_get(
> > +		qmi_result,
> > +		status ? QMI_VOICE_ALL_CALL_STATUS_REMOTE_NUMBER :
> > +			 QMI_VOICE_ALL_CALL_INFO_REMOTE_NUMBER,
> > +		&len);
> > +
> > +	if (remote_party_number) {
> > +		const struct qmi_voice_remote_party_number_instance *instance;
> > +		int instance_size =
> > +			sizeof(struct qmi_voice_remote_party_number_instance);
> > +		int i;
> > +
> > +		/* verify the length */
> > +		if (len < sizeof(remote_party_number->size))
> > +			return -EMSGSIZE;
> > +
> > +		for (i = 0, offset = sizeof(remote_party_number->size);
> > +			offset <= len && i < 16 && i < remote_party_number->size;
> > +			i++) {
> > +			if (offset == len)
> > +				break;
> > +			else if (offset + instance_size > len)
> > +				return -EMSGSIZE;
> > +
> > +			instance = (void *)remote_party_number + offset;
> > +			result->remote_party_number[i] = instance;
> > +			offset +=
> > +				sizeof(struct qmi_voice_remote_party_number_instance) +
> > +				instance->number_size;
> > +		}
> > +		result->remote_party_number_set = 1;
> > +		result->remote_party_number_size = remote_party_number->size;
> > +	} else
> > +		return -EBADMSG;
> 
> Same here:
> 
> if (!remote_party_number)
> 	return -EBADMSG;
> 
> if (len < ...)
> 
> for (...)
> 
> See doc/coding-style.txt item O2
> 
> > +
> > +	return 0;
> > +}
> > +
> > +static void all_call_status_ind(struct qmi_result *result, void *user_data)
> > +{
> > +	struct ofono_voicecall *vc = user_data;
> > +	struct voicecall_data *vd = ofono_voicecall_get_data(vc);
> > +	struct l_queue *calls = l_queue_new();
> > +	int i;
> > +	int size = 0;
> > +	struct qmi_voice_all_call_status_ind status_ind;
> > +
> > +	DBG("");
> 
> doc/coding-style.txt Item M1
> 
> > +	if (qmi_voice_call_status(result, &status_ind) != 0) {
> 
> nit: Prefer < 0 check for functions that return -errno.
> 
> > +		DBG("Parsing of all call status indication failed");
> > +		goto error;
> > +	}
> > +
> > +	if (!status_ind.remote_party_number_set ||
> > +	    !status_ind.call_information_set) {
> 
> Incorrect indentation
> 
> > +		DBG("Some required fields are not set");
> > +		goto error;
> > +	}
> > +
> > +	size = status_ind.call_information->size;
> > +	if (!size) {
> > +		DBG("No call informations received!");
> > +		goto error;
> > +	}
> > +
> > +	/* expect we have valid fields for every call */
> > +	if (size != status_ind.remote_party_number_size) {
> > +		DBG("Not all fields have the same size");
> > +		goto error;
> > +	}
> > +
> > +	for (i = 0; i < size; i++) {
> > +		struct qmi_voice_call_information_instance call_info;
> > +		struct ofono_call *call;
> > +		const struct qmi_voice_remote_party_number_instance
> > +			*remote_party = status_ind.remote_party_number[i];
> > +		int number_size;
> > +
> > +		call_info = status_ind.call_information->instance[i];
> > +		call = l_new(struct ofono_call, 1);
> > +		call->id = call_info.id;
> > +		call->direction = qmi_to_ofono_direction(call_info.direction);
> > +
> > +		if (qmi_to_ofono_status(call_info.state, &call->status)) {
> > +			DBG("Ignore call id %d, because can not convert QMI state 0x%x to ofono.",
> > +				call_info.id, call_info.state);
> > +			l_free(call);
> > +			continue;
> > +		}
> > +		DBG("Call %d in state %s(%d)", call_info.id,
> > +			qmi_voice_call_state_name(call_info.state),
> > +			call_info.state);
> > +
> > +		call->type = 0; /* always voice */
> > +		number_size = remote_party->number_size + 1;
> > +		if (number_size > OFONO_MAX_PHONE_NUMBER_LENGTH)
> > +			number_size = OFONO_MAX_PHONE_NUMBER_LENGTH;
> > +		l_strlcpy(call->phone_number.number, remote_party->number,
> > +				number_size);
> > +
> > +		if (strlen(call->phone_number.number) > 0)
> > +			call->clip_validity = 0;
> > +		else
> > +			call->clip_validity = 2;
> > +
> > +		l_queue_push_tail(calls, call);
> > +		DBG("%d", l_queue_length(calls));
> > +	}
> > +
> > +	ofono_call_list_notify(vc, calls);
> > +
> > +	return;
> > +error:
> > +	l_queue_destroy(calls, l_free);
> > +}
> > +
> > +static void dial_cb(struct qmi_result *result, void *user_data)
> > +{
> > +	struct cb_data *cbd = user_data;
> > +	struct ofono_voicecall *vc = cbd->user;
> > +	ofono_voicecall_cb_t cb = cbd->cb;
> > +	uint16_t error;
> > +	uint8_t call_id;
> > +	bool call_id_set = false;
> > +
> > +	static const uint8_t QMI_VOICE_DIAL_RESULT_CALL_ID = 0x10;
> > +
> > +	DBG("");
> > +
> > +	if (qmi_result_set_error(result, &error)) {
> > +		DBG("QMI Error %d", error);
> > +		CALLBACK_WITH_FAILURE(cb, cbd->data);
> > +		return;
> > +	}
> > +
> > +	if (qmi_result_get_uint8(result, QMI_VOICE_DIAL_RESULT_CALL_ID,
> > +					&call_id))
> > +		call_id_set = true;
> > +	else {
> > +		DBG("Received invalid Result");
> > +		CALLBACK_WITH_FAILURE(cb, cbd->data);
> > +		return;
> > +	}
> > +
> > +	if (!call_id_set) {
> > +		DBG("Didn't receive a call id");
> > +		CALLBACK_WITH_FAILURE(cb, cbd->data);
> > +		return;
> > +	}
> 
> This if looks like a dead branch.  The only way call_id_set is false here is if 
> qmi_result_get_uint8 earlier failed.  In fact, the above section can be 
> rewritten as:
> 
> if (!qmi_result_get_uint8(...)) {
> 	ofono_error("No call id in dial result");
> 	CALLBACK_WITH_FAILURE(...);
> 	return;
> }
> 
> No need for call_id_set variable either.
> 
> > +
> > +	DBG("New call QMI id %d", call_id);
> > +	ofono_call_list_dial_callback(vc, call_id);
> > +
> > +	CALLBACK_WITH_SUCCESS(cb, cbd->data);
> > +}
> > +
> 
> <snip>
> 
> > +static void dial(struct ofono_voicecall *vc,
> > +			const struct ofono_phone_number *ph,
> > +			enum ofono_clir_option clir, ofono_voicecall_cb_t cb,
> > +			void *data)
> > +{
> > +	struct voicecall_data *vd = ofono_voicecall_get_data(vc);
> > +	struct cb_data *cbd = cb_data_new(cb, data);
> > +	struct qmi_param *param;
> > +	const char *calling_number = phone_number_to_string(ph);
> > +
> > +	static const uint8_t QMI_VOICE_DIAL_CALL_NUMBER = 0x01;
> > +	static const uint8_t QMI_VOICE_DIAL_CALL_TYPE = 0x10;
> > +	static const uint8_t QMI_VOICE_CALL_TYPE_VOICE = 0x00;
> > +
> > +	DBG("");
> > +
> > +	cbd->user = vc;
> > +	memcpy(&vd->dialed, ph, sizeof(*ph));
> > +
> > +	param = qmi_param_new();
> > +	if (!param)
> > +		goto error;
> > +
> > +	if (!qmi_param_append(param, QMI_VOICE_DIAL_CALL_NUMBER,
> > +				strlen(calling_number), calling_number)) {
> > +		goto error;
> > +	}
> 
> No need for {}
> 
> > +
> > +	qmi_param_append_uint8(param, QMI_VOICE_DIAL_CALL_TYPE,
> > +				QMI_VOICE_CALL_TYPE_VOICE);
> > +
> > +	if (qmi_service_send(vd->voice, QMI_VOICE_DIAL_CALL, param, dial_cb,
> > +				cbd, l_free) > 0)
> > +		return;
> > +
> > +error:
> > +	CALLBACK_WITH_FAILURE(cb, data);
> > +	l_free(cbd);
> > +	l_free(param);
> > +}
> > +
> >   static void create_voice_cb(struct qmi_service *service, void *user_data)
> >   {
> >   	struct ofono_voicecall *vc = user_data;
> 
> <snip>
> 
> > @@ -92,13 +566,16 @@ static void qmi_voicecall_remove(struct ofono_voicecall *vc)
> >   
> >   	qmi_service_unref(data->voice);
> >   
> > +	l_queue_destroy(data->call_list, l_free);
> >   	l_free(data);
> >   }
> >   
> >   static const struct ofono_voicecall_driver driver = {
> >   	.probe		= qmi_voicecall_probe,
> >   	.remove		= qmi_voicecall_remove,
> > +	.dial		= dial,
> >   };
> >   
> >   OFONO_ATOM_DRIVER_BUILTIN(voicecall, qmimodem, &driver)
> >   
> > +
> 
> Empty line at EOF I mentioned earlier is here
> 
> Regards,
> -Denis
>

-- 
Sent from my Sailfish device

  reply	other threads:[~2024-04-04 21:22 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-02 21:25 [PATCH v3 1/4] qmimodem: voicecall: Implement call dialing Adam Pigg
2024-04-02 21:25 ` [PATCH v3 2/4] qmimodem: voicecall: Implement call answer Adam Pigg
2024-04-04 20:58   ` Denis Kenzior
2024-04-02 21:25 ` [PATCH v3 3/4] qmimodem: voicecall: Implement active call hangup Adam Pigg
2024-04-04 21:03   ` Denis Kenzior
2024-04-02 21:25 ` [PATCH v3 4/4] qmimodem: voicecall: Implement DTMF tones Adam Pigg
2024-04-04 21:33   ` Denis Kenzior
2024-04-02 21:46 ` [PATCH v3 1/4] qmimodem: voicecall: Implement call dialing Adam Pigg
2024-04-04 20:43 ` Denis Kenzior
2024-04-04 21:22   ` piggz1 [this message]
2024-04-04 21:38     ` Denis Kenzior

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=a28170.sbfspn.2v2btf-qmf@smtp.gmail.com \
    --to=piggz1@gmail.com \
    --cc=adam@piggz.co.uk \
    --cc=denkenz@gmail.com \
    --cc=ofono@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox