Gemalto: support for voicecall
v3 cover Gemalto: support for voicecall
This series of patches adds a vendor-specific voicecall atom for gemaltomodem, and then adds it to the plugin, along with all other call-related atoms.
related to the previous versions submitted for RFC, it integrates the comments from Denis and Jonas, uses the required URCs (leaving out, for example, RING), and doesn't check the memory allocation
anymore: g_new0 instead of g_try_new0.
From the second version, it fixes also a problem with the initial version, where the SLCC URC was parsed exactly like the AT+CLCC command:
now the code takes into account that the URC function is called for each line, and not for all together (unlike CLCC parsing, where all lines are available at once).
Giacinto Cifelli (2):
Gemalto: voicecall atom
plugins/gemalto: added voice support
Makefile.am | 3 +- drivers/gemaltomodem/gemaltomodem.c | 3 + drivers/gemaltomodem/gemaltomodem.h | 3 + drivers/gemaltomodem/voicecall.c | 729 ++++++++++++++++++++++++++++ plugins/gemalto.c | 12 + 5 files changed, 749 insertions(+), 1 deletion(-) create mode 100644 drivers/gemaltomodem/voicecall.c
Signature · 1 line
2.17.1
PATCH v3 1/2 Gemalto: voicecall atom
Added voicecall atom specific for Gemalto modems.
This atom uses the URC ^SLCC to monitor the call status, as well as incoming calls.
Note the use in the atom of the variable GemaltoVtsQuotes: this is needed to support future modules, as of today not yet available in the plugin.
--- Makefile.am | 3 +- drivers/gemaltomodem/gemaltomodem.c | 3 + drivers/gemaltomodem/gemaltomodem.h | 3 + drivers/gemaltomodem/voicecall.c | 729 ++++++++++++++++++++++++++++ 4 files changed, 737 insertions(+), 1 deletion(-) create mode 100644 drivers/gemaltomodem/voicecall.c
Makefile.am +2 -1
@@ -397,7 +397,8 @@ builtin_modules += gemaltomodem builtin_sources += drivers/atmodem/atutil.h \ drivers/gemaltomodem/gemaltomodem.h \ drivers/gemaltomodem/gemaltomodem.c \ - drivers/gemaltomodem/location-reporting.c + drivers/gemaltomodem/location-reporting.c \ + drivers/gemaltomodem/voicecall.c builtin_modules += xmm7modem builtin_sources += drivers/atmodem/atutil.h \
drivers/gemaltomodem/gemaltomodem.c +3 -0
@@ -3,6 +3,7 @@* oFono - Open Source Telephony * * Copyright (C) 2017 Vincent Cesson. All rights reserved. +* Copyright (C) 2018 Gemalto M2M * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as
@@ -35,12 +36,14 @@static int gemaltomodem_init (void ) {gemalto_location_reporting_init (); +gemalto_voicecall_init ();return 0 ; }static void gemaltomodem_exit (void ) { +gemalto_voicecall_exit ();gemalto_location_reporting_exit (); }
drivers/gemaltomodem/gemaltomodem.h +3 -0
@@ -3,6 +3,7 @@* oFono - Open Source Telephony * * Copyright (C) 2017 Vincent Cesson. All rights reserved. +* Copyright (C) 2018 Gemalto M2M * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as
@@ -23,3 +24,5 @@extern void gemalto_location_reporting_init ();extern void gemalto_location_reporting_exit (); +extern void gemalto_voicecall_init (); +extern void gemalto_voicecall_exit ();
drivers/gemaltomodem/voicecall.c new file +729 -0
729 lines not on this page · raw message
Signature · 1 line
2.17.1
Re: [PATCH v3 1/2] Gemalto: voicecall atom
Hi Giacinto,
<snip>
drivers/gemaltomodem/voicecall.c line 52
Quoted 6 lines
drivers/gemaltomodem/voicecall.c new file +6
-0+static const char *none_prefix[] = {NULL }; + +/* According to 27.007 COLP is an intermediate status for ATD */ +static const char *atd_prefix[] = {"+COLP:" ,NULL }; + +#define FLAG_NEED_CLIP 1
Do you even need this?
drivers/gemaltomodem/voicecall.c line 58
Quoted 6 lines
drivers/gemaltomodem/voicecall.c new file +6
-0+ +struct voicecall_data { +GAtChat *chat; +GSList *calls; +unsigned int local_release; +unsigned int vendor;
Why?
drivers/gemaltomodem/voicecall.c line 59
Quoted 1 line
drivers/gemaltomodem/voicecall.c new file +1
-0+unsigned char flags;
Which flags do you use?
Quoted 210 lines
drivers/gemaltomodem/voicecall.c new file +210
-0+GSList *new_calls; +}; + +struct release_id_req { +struct ofono_voicecall *vc; +ofono_voicecall_cb_t cb; +void *data; +int id; +}; + +struct change_state_req { +struct ofono_voicecall *vc; +ofono_voicecall_cb_t cb; +void *data; +int affected_types; +}; + +static void generic_cb (gboolean ok,GAtResult *result,gpointer user_data) +{ +struct change_state_req *req = user_data; +struct voicecall_data *vd =ofono_voicecall_get_data (req->vc); +struct ofono_error error; + +decode_at_error (&error,g_at_result_final_response (result)); + +if (ok && req->affected_types) { +GSList *l; +struct ofono_call *call; + +for (l = vd->calls; l; l = l->next) { + call = l->data; + +if (req->affected_types & (1 << call->status)) + vd->local_release |= (1 << call->id); + } + } + + req->cb (&error, req->data); +} + +static void gemalto_call_common (const char *cmd,struct ofono_voicecall *vc, +GAtResultFunc result_cb,unsigned int affected_types, +ofono_voicecall_cb_t cb,void *data) +{ +struct voicecall_data *vd =ofono_voicecall_get_data (vc); + struct change_state_req *req = g_new0(struct change_state_req, 1); + + req->vc = vc; + req->cb = cb; + req->data = data; + req->affected_types = affected_types; + +if (g_at_chat_send (vd->chat, cmd, none_prefix, + result_cb, req, g_free) >0 ) +return ; + +g_free (req); +CALLBACK_WITH_FAILURE (cb, data); +} + +static void gemalto_answer (struct ofono_voicecall *vc, +ofono_voicecall_cb_t cb,void *data) +{ +gemalto_call_common ("ATA" , vc, generic_cb,0 , cb, data); +} + +static void gemalto_hangup_all (struct ofono_voicecall *vc, +ofono_voicecall_cb_t cb,void *data) +{ +unsigned int affected = (1 <<CALL_STATUS_INCOMING ) | + (1 <<CALL_STATUS_DIALING ) | + (1 <<CALL_STATUS_ALERTING ) | + (1 <<CALL_STATUS_WAITING ) | + (1 <<CALL_STATUS_HELD ) | + (1 <<CALL_STATUS_ACTIVE ); + +/* Hangup all calls */ +gemalto_call_common ("AT+CHUP" , vc, generic_cb, affected, cb, data); +} + +static void gemalto_hangup (struct ofono_voicecall *vc, +ofono_voicecall_cb_t cb,void *data) +{ +unsigned int affected = (1 <<CALL_STATUS_ACTIVE ); + +/* Hangup current active call */ +gemalto_call_common ("AT+CHLD=1" , vc, generic_cb, affected, cb, data); +} + +static void gemalto_hold_all_active (struct ofono_voicecall *vc, +ofono_voicecall_cb_t cb,void *data) +{ +unsigned int affected = (1 <<CALL_STATUS_ACTIVE ); +gemalto_call_common ("AT+CHLD=2" , vc, generic_cb, affected, cb, data); +} + +static void gemalto_release_all_held (struct ofono_voicecall *vc, +ofono_voicecall_cb_t cb,void *data) +{ +unsigned int affected = (1 <<CALL_STATUS_INCOMING ) | + (1 <<CALL_STATUS_WAITING ); + +gemalto_call_common ("AT+CHLD=0" , vc, generic_cb, affected, cb, data); +} + +static void gemalto_set_udub (struct ofono_voicecall *vc, +ofono_voicecall_cb_t cb,void *data) +{ +unsigned int affected = (1 <<CALL_STATUS_INCOMING ) | + (1 <<CALL_STATUS_WAITING ); + +gemalto_call_common ("AT+CHLD=0" , vc, generic_cb, affected, cb, data); +} + +static void gemalto_release_all_active (struct ofono_voicecall *vc, +ofono_voicecall_cb_t cb,void *data) +{ +unsigned int affected = (1 <<CALL_STATUS_ACTIVE ); + +gemalto_call_common ("AT+CHLD=1" , vc, generic_cb, affected, cb, data); +} + +static void release_id_cb (gboolean ok,GAtResult *result, +gpointer user_data) +{ +struct release_id_req *req = user_data; +struct voicecall_data *vd =ofono_voicecall_get_data (req->vc); +struct ofono_error error; + +decode_at_error (&error,g_at_result_final_response (result)); + +if (ok) + vd->local_release =1 << req->id; + + req->cb (&error, req->data); +} + +static void gemalto_release_specific (struct ofono_voicecall *vc,int id, +ofono_voicecall_cb_t cb,void *data) +{ +struct voicecall_data *vd =ofono_voicecall_get_data (vc); + struct release_id_req *req = g_new0(struct release_id_req, 1); +char buf[32 ]; + + req->vc = vc; + req->cb = cb; + req->data = data; + req->id = id; + +snprintf (buf,sizeof (buf),"AT+CHLD=1%d" , id); + +if (g_at_chat_send (vd->chat, buf, none_prefix, + release_id_cb, req, g_free) >0 ) +return ; + +g_free (req); +CALLBACK_WITH_FAILURE (cb, data); +} + +static void gemalto_private_chat (struct ofono_voicecall *vc,int id, +ofono_voicecall_cb_t cb,void *data) +{ +char buf[32 ]; + +snprintf (buf,sizeof (buf),"AT+CHLD=2%d" , id); +gemalto_call_common (buf, vc, generic_cb,0 , cb, data); +} + +static void gemalto_create_multiparty (struct ofono_voicecall *vc, +ofono_voicecall_cb_t cb,void *data) +{ +gemalto_call_common ("AT+CHLD=3" , vc, generic_cb,0 , cb, data); +} + +static void gemalto_transfer (struct ofono_voicecall *vc, +ofono_voicecall_cb_t cb,void *data) +{ +/* Held & Active */ +unsigned int affected = (1 <<CALL_STATUS_ACTIVE ) | + (1 <<CALL_STATUS_HELD ); + +/* Transfer can puts held & active calls together and disconnects +* from both. However, some networks support transferring of +* dialing/ringing calls as well. +*/ + affected |= (1 <<CALL_STATUS_DIALING ) | + (1 <<CALL_STATUS_ALERTING ); + +gemalto_call_common ("AT+CHLD=4" , vc, generic_cb, affected, cb, data); +} + +static void gemalto_send_dtmf (struct ofono_voicecall *vc,const char *dtmf, +ofono_voicecall_cb_t cb,void *data) +{ +struct voicecall_data *vd =ofono_voicecall_get_data (vc); +int len =strlen (dtmf); +int s; +int i; +char *buf; +struct ofono_modem *modem =ofono_voicecall_get_modem (vc); +int use_quotes =ofono_modem_get_integer (modem,"GemaltoVtsQuotes" ); + +/* strlen("+VTS=\"T\";") = 9 + initial AT + null */ + buf =g_new (char, len *9 +3 ); + +if (use_quotes) + s =sprintf (buf,"AT+VTS=\"%c\"" , dtmf[0 ]); +else + s =sprintf (buf,"AT+VTS=%c" , dtmf[0 ]); +
drivers/gemaltomodem/voicecall.c line 279
Quoted 10 lines
drivers/gemaltomodem/voicecall.c new file +10
-0+for (i =1 ; i < len; i++) { + +if (use_quotes) + s +=sprintf (buf + s,";+VTS=\"%c\"" , dtmf[i]); +else + s +=sprintf (buf + s,";+VTS=%c" , dtmf[i]); + } + +g_at_chat_send (vd->chat, buf,NULL ,NULL ,NULL ,NULL ); +g_free (buf);
No callback?
Quoted 19 lines
drivers/gemaltomodem/voicecall.c new file +19
-0+} + +static struct ofono_call *create_call (struct ofono_voicecall *vc,int type, +int direction,int status, +const char *num,int num_type,int clip) +{ +struct voicecall_data *d =ofono_voicecall_get_data (vc); +struct ofono_call *call; + +/* Generate a call structure for the waiting call */ + call = g_new(struct ofono_call, 1); +ofono_call_init (call); + call->id =ofono_voicecall_get_next_callid (vc); + call->type = type; + call->direction = direction; + call->status = status; + +if (clip !=2 ) { + strncpy(call->phone_number.number, num,
drivers/gemaltomodem/voicecall.c line 308
Quoted 10 lines
drivers/gemaltomodem/voicecall.c new file +10
-0+ OFONO_MAX_PHONE_NUMBER_LENGTH); + call->phone_number.type = num_type; + } + + call->clip_validity = clip; + call->cnap_validity =CNAP_VALIDITY_NOT_AVAILABLE ; + + d->calls =g_slist_insert_sorted (d->calls, call, at_util_call_compare); + +return call;
This function might be a candidate to put into atutil.c
Quoted 6 lines
drivers/gemaltomodem/voicecall.c new file +6
-0+} + +static void atd_cb (gboolean ok,GAtResult *result,gpointer user_data) +{ +struct cb_data *cbd = user_data; +struct ofono_voicecall *vc = cbd->user;
drivers/gemaltomodem/voicecall.c line 324
Quoted 10 lines
drivers/gemaltomodem/voicecall.c new file +10
-0+struct voicecall_data *vd =ofono_voicecall_get_data (vc); +ofono_voicecall_cb_t cb = cbd->cb; +GAtResultIter iter; +const char *num; +int type =128 ; +int validity =2 ; +struct ofono_error error; +struct ofono_call *call; +GSList *l; +
This version of ATD deals with the 27.007 default which only returns when the call has been accepted. If your firmware supports an immediate return to ATD with dialing, alerting, etc states reported via ^SLCC, then this is actually not what you want at all... Again, see drivers/calypsomodem or drivers/ifxmodem for details.
Quoted 76 lines
drivers/gemaltomodem/voicecall.c new file +76
-0+decode_at_error (&error,g_at_result_final_response (result)); + +if (!ok) + goto out; + +/* On a success, make sure to put all active calls on hold */ +for (l = vd->calls; l; l = l->next) { + call = l->data; + +if (call->status !=CALL_STATUS_ACTIVE ) +continue ; + + call->status =CALL_STATUS_HELD ; +ofono_voicecall_notify (vc, call); + } + +g_at_result_iter_init (&iter, result); + +if (g_at_result_iter_next (&iter,"+COLP:" )) { +g_at_result_iter_next_string (&iter, &num); +g_at_result_iter_next_number (&iter, &type); + +if (strlen (num) >0 ) + validity =0 ; +else + validity =2 ; + +DBG ("colp_notify: %s %d %d" , num, type, validity); + } + +/* Generate a voice call that was just dialed, we guess the ID */ + call =create_call (vc,0 ,0 ,CALL_STATUS_DIALING , num, type, validity); +if (call ==NULL ) { +ofono_error ("Unable to malloc, call tracking will fail!" ); +return ; + } + +/* oFono core will generate a call with the dialed number +* inside its dial callback. Unless we got COLP information +* we do not need to communicate that a call is being +* dialed +*/ +if (validity !=2 ) +ofono_voicecall_notify (vc, call); + +out: +cb (&error, cbd->data); +} + +static void gemalto_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); +char buf[256 ]; +size_t len; + + cbd->user = vc; + +if (ph->type ==145 ) + len =snprintf (buf,sizeof (buf),"ATD+%s" , ph->number); +else + len =snprintf (buf,sizeof (buf),"ATD%s" , ph->number); + +switch (clir) { +case OFONO_CLIR_OPTION_INVOCATION : + len +=snprintf (buf+len,sizeof (buf)-len,"I" ); +break ; +case OFONO_CLIR_OPTION_SUPPRESSION : + len +=snprintf (buf+len,sizeof (buf)-len,"i" ); +break ; +default : +break ; + }
drivers/gemaltomodem/voicecall.c line 410
Quoted 10 lines
drivers/gemaltomodem/voicecall.c new file +10
-0+ +snprintf (buf+len,sizeof (buf)-len,";" ); + +if (g_at_chat_send (vd->chat, buf, atd_prefix, + atd_cb, cbd, g_free) >0 ) +return ; + +g_free (cbd); + +CALLBACK_WITH_FAILURE (cb, data);
The basic atd might also be a good candidate for atutil.c :)
Quoted 61 lines
drivers/gemaltomodem/voicecall.c new file +61
-0+} + +static gboolean gemalto_parse_slcc (GAtResult *result,GSList **l, +unsigned int *ret_mpty_ids) +{ +GAtResultIter iter; +int id, dir, status, type; +ofono_bool_t mpty; +struct ofono_call *call; +unsigned int mpty_ids =0 ; +gboolean last = TRUE; +const char *str ="" ; +int number_type =129 ; + +g_at_result_iter_init (&iter, result); + +g_at_result_iter_next (&iter,"^SLCC:" ); + +if (!g_at_result_iter_next_number (&iter, &id)) + goto finish; + + last = FALSE; + +if (id ==0 ) + goto finish; + +if (!g_at_result_iter_next_number (&iter, &dir)) + goto finish; + +if (!g_at_result_iter_next_number (&iter, &status)) + goto finish; + +if (status >5 ) + goto finish; + +if (!g_at_result_iter_next_number (&iter, &type)) + goto finish; + +if (!g_at_result_iter_next_number (&iter, &mpty)) + goto finish; + +/* skip 'Reserved=0' parameter, only difference from CLCC */ +if (!g_at_result_iter_skip_next (&iter)) + goto finish; + +if (g_at_result_iter_next_string (&iter, &str)) +g_at_result_iter_next_number (&iter, &number_type); + + call = g_new0(struct ofono_call, 1); +ofono_call_init (call); + call->id = id; + call->direction = dir; + call->status = status; + call->type = type; +strncpy (call->phone_number.number, str, +OFONO_MAX_PHONE_NUMBER_LENGTH ); + call->phone_number.type = number_type; + +if (strlen (call->phone_number.number) >0 ) + call->clip_validity =0 ; +else
drivers/gemaltomodem/voicecall.c line 481
Quoted 10 lines
drivers/gemaltomodem/voicecall.c new file +10
-0+ call->clip_validity =2 ; + + *l =g_slist_insert_sorted (*l, call, at_util_call_compare); + +if (mpty) + mpty_ids |=1 << id; + +if (ret_mpty_ids) + *ret_mpty_ids = mpty_ids; +
This part makes no sense. CLCC parser returns a list of ids in the mpty call as a bitfield, but it parses the entire call list. Here you're parsing things piecemeal. So this whole mpty_ids thing makes no sense. Just use a boolean out parameter for the mpty status and be done with it.
drivers/gemaltomodem/voicecall.c line 483
Quoted 2 lines
drivers/gemaltomodem/voicecall.c new file +2
-0+finish: +return last;
This is really weird. You're returning TRUE/FALSE whether this SLCC entry is the last or not. But really it should return whether parsing succeeded or not.
Quoted 63 lines
drivers/gemaltomodem/voicecall.c new file +63
-0+} + +static void clcc_cb (gboolean ok,GAtResult *result,gpointer user_data) +{ +struct ofono_voicecall *vc = user_data; +struct voicecall_data *vd =ofono_voicecall_get_data (vc); +GSList *l; + +if (!ok) +return ; + + vd->calls =at_util_parse_clcc (result,NULL ); + +for (l = vd->calls; l; l = l->next) +ofono_voicecall_notify (vc, l->data); +} + +/* +* ^SLCC, except for one RFU parameter (see above in the parsing), is identical +* to +CLCC, but as URC it is parsed line by line, and the last line is +* indicated by an empty "^SLCC:" (equivalent to the "OK" for CLCC). +*/ +static void slcc_notify (GAtResult *result,gpointer user_data) +{ +struct ofono_voicecall *vc = user_data; +struct voicecall_data *vd =ofono_voicecall_get_data (vc); +GSList *n, *o; +struct ofono_call *nc, *oc; + +gboolean last =gemalto_parse_slcc (result, &vd->new_calls,NULL ); + +if (!last) +return ; + + n = vd->new_calls; + o = vd->calls; + +while (n || o) { + + nc = n ? n->data :NULL ; + oc = o ? o->data :NULL ; + +if (oc && (nc ==NULL || (nc->id > oc->id))) { +enum ofono_disconnect_reason reason; + +if (vd->local_release & (1 << oc->id)) + reason =OFONO_DISCONNECT_REASON_LOCAL_HANGUP ; +else + reason =OFONO_DISCONNECT_REASON_REMOTE_HANGUP ; + +if (!oc->type) +ofono_voicecall_disconnected (vc, oc->id, + reason,NULL ); + + o = o->next; + }else if (nc && (oc ==NULL || (nc->id < oc->id))) { + +if (nc->type ==0 )/* new call, signal it */ +ofono_voicecall_notify (vc, nc); + + n = n->next; + }else { +/*
drivers/gemaltomodem/voicecall.c line 556
Quoted 10 lines
drivers/gemaltomodem/voicecall.c new file +10
-0+* Always use the clip_validity from old call +* the only place this is truly told to us is +* in the CLIP notify, the rest are fudged +* anyway. Useful when RING, CLIP is used, +* and we're forced to use CLCC/SLCC and clip_validity +* is 1 +*/ +if (oc->clip_validity ==1 ) + nc->clip_validity = oc->clip_validity; +
All of this logic is likely not useful for you
drivers/gemaltomodem/voicecall.c line 564
Quoted 8 lines
drivers/gemaltomodem/voicecall.c new file +8
-0+/* +* CNAP doesn't arrive as part of CLCC, always +* re-use from the old call +*/ +strncpy (nc->name, oc->name, +OFONO_MAX_CALLER_NAME_LENGTH ); + nc->name[OFONO_MAX_CALLER_NAME_LENGTH ] ='\0' ; + nc->cnap_validity = oc->cnap_validity;
Or this since it doesn't look like you support CNAP
Quoted 9 lines
drivers/gemaltomodem/voicecall.c new file +9
-0+ +/* +* CDIP doesn't arrive as part of CLCC, always +* re-use from the old call +*/ +memcpy (&nc->called_number, &oc->called_number, +sizeof (oc->called_number)); + +/*
drivers/gemaltomodem/voicecall.c line 583
Quoted 10 lines
drivers/gemaltomodem/voicecall.c new file +10
-0+* If the CLIP is not provided and the CLIP never +* arrives, or RING is used, then signal the call +* here +*/ +if (nc->status ==CALL_STATUS_INCOMING && + (vd->flags &FLAG_NEED_CLIP )) { +if (nc->type ==0 ) +ofono_voicecall_notify (vc, nc); + + vd->flags &= ~FLAG_NEED_CLIP ;
Or this..
Quoted 137 lines
drivers/gemaltomodem/voicecall.c new file +136
-0+ }else if (memcmp (nc, oc,sizeof (*nc)) && nc->type ==0 ) +ofono_voicecall_notify (vc, nc); + + n = n->next; + o = o->next; + } + } + +g_slist_free_full (vd->calls, g_free); + + vd->calls = vd->new_calls; + vd->new_calls =NULL ; + + vd->local_release =0 ; +} + +static void cssi_notify (GAtResult *result,gpointer user_data) +{ +struct ofono_voicecall *vc = user_data; +GAtResultIter iter; +int code, index; + +g_at_result_iter_init (&iter, result); + +if (!g_at_result_iter_next (&iter,"+CSSI:" )) +return ; + +if (!g_at_result_iter_next_number (&iter, &code)) +return ; + +if (!g_at_result_iter_next_number (&iter, &index)) + index =0 ; + +ofono_voicecall_ssn_mo_notify (vc,0 , code, index); +} + +static void cssu_notify (GAtResult *result,gpointer user_data) +{ +struct ofono_voicecall *vc = user_data; +GAtResultIter iter; +int code; +int index; +const char *num; +struct ofono_phone_number ph; + + ph.number[0 ] ='\0' ; + ph.type =129 ; + +g_at_result_iter_init (&iter, result); + +if (!g_at_result_iter_next (&iter,"+CSSU:" )) +return ; + +if (!g_at_result_iter_next_number (&iter, &code)) +return ; + +if (!g_at_result_iter_next_number_default (&iter,-1 , &index)) + goto out; + +if (!g_at_result_iter_next_string (&iter, &num)) + goto out; + +strncpy (ph.number, num,OFONO_MAX_PHONE_NUMBER_LENGTH ); + +if (!g_at_result_iter_next_number (&iter, &ph.type)) +return ; + +out: +ofono_voicecall_ssn_mt_notify (vc,0 , code, index, &ph); +} + +static void gemalto_voicecall_initialized (gboolean ok,GAtResult *result, +gpointer user_data) +{ +struct ofono_voicecall *vc = user_data; +struct voicecall_data *vd =ofono_voicecall_get_data (vc); + +DBG ("voicecall_init: registering to notifications" ); + +/* NO CARRIER, NO ANSWER, BUSY, NO DIALTONE are handled through SLCC */ +g_at_chat_register (vd->chat,"^SLCC:" , slcc_notify, FALSE, vc,NULL ); +g_at_chat_register (vd->chat,"+CSSI:" , cssi_notify, FALSE, vc,NULL ); +g_at_chat_register (vd->chat,"+CSSU:" , cssu_notify, FALSE, vc,NULL ); + +ofono_voicecall_register (vc); + +/* Populate the call list */ +g_at_chat_send (vd->chat,"AT+CLCC" , clcc_prefix, clcc_cb, vc,NULL ); +} + +static int gemalto_voicecall_probe (struct ofono_voicecall *vc, +unsigned int vendor,void *data) +{ +GAtChat *chat = data; +struct voicecall_data *vd; + + vd = g_new0(struct voicecall_data, 1); + vd->chat =g_at_chat_clone (chat); + vd->vendor = vendor; +ofono_voicecall_set_data (vc, vd); +g_at_chat_send (vd->chat,"AT+CSSN=1,1" ,NULL ,NULL ,NULL ,NULL ); +g_at_chat_send (vd->chat,"AT^SLCC=1" ,NULL , + gemalto_voicecall_initialized, vc,NULL ); +return 0 ; +} + +static void gemalto_voicecall_remove (struct ofono_voicecall *vc) +{ +struct voicecall_data *vd =ofono_voicecall_get_data (vc); + +ofono_voicecall_set_data (vc,NULL ); + +g_at_chat_unref (vd->chat); +g_free (vd); +} + +static struct ofono_voicecall_driver driver = { + .name ="gemaltomodem" , + .probe = gemalto_voicecall_probe, + .remove = gemalto_voicecall_remove, + .dial = gemalto_dial, + .answer = gemalto_answer, + .hangup_all = gemalto_hangup_all, + .hangup_active = gemalto_hangup, + .hold_all_active = gemalto_hold_all_active, + .release_all_held = gemalto_release_all_held, + .set_udub = gemalto_set_udub, + .release_all_active = gemalto_release_all_active, + .release_specific = gemalto_release_specific, + .private_chat = gemalto_private_chat, + .create_multiparty = gemalto_create_multiparty, + .transfer = gemalto_transfer, + .deflect =NULL , + .swap_without_accept =NULL , + .send_tones = gemalto_send_dtmf +};
drivers/gemaltomodem/voicecall.c line 729
Quoted 10 lines
drivers/gemaltomodem/voicecall.c new file +10
-0+ +void gemalto_voicecall_init (void ) +{ +ofono_voicecall_driver_register (&driver); +} + +void gemalto_voicecall_exit (void ) +{ +ofono_voicecall_driver_unregister (&driver); +}
Regards,
-Denis
PATCH v3 2/2 plugins/gemalto: added voice support
In reply to Giacinto CifelliThe plugin for Gemalto modems is enriched with all voice-related atoms, as well as USSD.
All except the voicecall itself are from the atmodem, while the voicecall is from gemaltomodem.
--- plugins/gemalto.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
plugins/gemalto.c +12 -0
@@ -3,6 +3,7 @@* oFono - Open Source Telephony * * Copyright (C) 2017 Vincent Cesson. All rights reserved. +* Copyright (C) 2018 Gemalto M2M * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as
@@ -571,6 +572,10 @@ static void gemalto_pre_sim(struct ofono_modem *modem)ofono_devinfo_create (modem,0 ,"atmodem" , data->app);ofono_location_reporting_create (modem,0 ,"gemaltomodem" , data->app); + +ofono_modem_set_integer (modem,"GemaltoVtsQuotes" ,1 ); +ofono_voicecall_create (modem,0 ,"gemaltomodem" , data->app); + data->sim =ofono_sim_create (modem,OFONO_VENDOR_GEMALTO ,"atmodem" , data->app);
@@ -597,6 +602,13 @@ static void gemalto_post_sim(struct ofono_modem *modem)if (gprs && gc)ofono_gprs_add_context (gprs, gc); +ofono_ussd_create (modem,0 ,"atmodem" , data->app); + +ofono_call_forwarding_create (modem,0 ,"atmodem" , data->app); +ofono_call_settings_create (modem,0 ,"atmodem" , data->app); +ofono_call_meter_create (modem,0 ,"atmodem" , data->app); +ofono_call_barring_create (modem,0 ,"atmodem" , data->app); +if (!g_strcmp0 (model, GEMALTO_MODEL_ALS3_PLS8x))ofono_lte_create (modem,OFONO_VENDOR_CINTERION ,"atmodem" , data->app);
Signature · 1 line
2.17.1