diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2016-11-23 23:42:46 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2017-01-04 14:11:17 +0100 |
commit | d50059ead40d9e6c18d4ff5cd8daaf2cea965d74 (patch) | |
tree | e26a645fb1424faa4ed9ffbc2914f65e187ba0fb | |
parent | 938a53e7c64751d045e9fe1b11f9de774f3878f3 (diff) |
cinterion: setup per-interface configuration settings
Define the relationship between PDP context, SWWAN index and USB
interface number in one single place.
-rw-r--r-- | plugins/cinterion/mm-broadband-bearer-cinterion.c | 196 |
1 files changed, 103 insertions, 93 deletions
diff --git a/plugins/cinterion/mm-broadband-bearer-cinterion.c b/plugins/cinterion/mm-broadband-bearer-cinterion.c index 2c13d465..ebd1a60b 100644 --- a/plugins/cinterion/mm-broadband-bearer-cinterion.c +++ b/plugins/cinterion/mm-broadband-bearer-cinterion.c @@ -32,10 +32,62 @@ G_DEFINE_TYPE (MMBroadbandBearerCinterion, mm_broadband_bearer_cinterion, MM_TYPE_BROADBAND_BEARER) /*****************************************************************************/ -/* Common enums and structs */ +/* WWAN interface mapping */ + +typedef struct { + guint swwan_index; + guint usb_iface_num; + guint pdp_context; +} UsbInterfaceConfig; + +/* Map SWWAN index, USB interface number and preferred PDP context. + * + * The expected USB interface mapping is: + * INTERFACE=usb0 -> ID_USB_INTERFACE_NUM=0a + * INTERFACE=usb1 -> ID_USB_INTERFACE_NUM=0c + * + * The preferred PDP context CIDs are: + * INTERFACE=usb0 -> PDP CID #3 + * INTERFACE=usb1 -> PDP CID #1 + * + * The PDP context mapping is as suggested by Cinterion, although it looks like + * this isn't strictly enforced by the modem; i.e. SWWAN could work fine with + * any PDP context vs SWWAN interface mapping. + */ +static const UsbInterfaceConfig usb_interface_configs[] = { + { + .swwan_index = 1, + .usb_iface_num = 0x0a, + .pdp_context = 3 + }, + { + .swwan_index = 2, + .usb_iface_num = 0x0c, + .pdp_context = 1 + }, +}; + +static gint +get_usb_interface_config_index (MMPort *data, + GError **error) +{ + guint usb_iface_num; + guint i; + + usb_iface_num = mm_kernel_device_get_property_as_int_hex (mm_port_peek_kernel_device (data), "ID_USB_INTERFACE_NUM"); + + for (i = 0; i < G_N_ELEMENTS (usb_interface_configs); i++) { + if (usb_interface_configs[i].usb_iface_num == usb_iface_num) + return (gint) i; + } -#define FIRST_USB_INTERFACE 1 -#define SECOND_USB_INTERFACE 2 + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Unsupported WWAN interface: unexpected interface number: 0x%02x", usb_iface_num); + return -1; +} + +/*****************************************************************************/ +/* Common enums and structs */ typedef enum { BEARER_CINTERION_AUTH_UNKNOWN = -1, @@ -66,6 +118,7 @@ typedef struct { MMBaseModem *modem; MMPortSerialAt *primary; MMPort *data; + gint usb_interface_config_index; Connect3gppContextStep connect; MMBearerIpConfig *ipv4_config; GCancellable *cancellable; @@ -77,13 +130,14 @@ typedef struct { MMBaseModem *modem; MMPortSerialAt *primary; MMPort *data; + gint usb_interface_config_index; Disconnect3gppContextStep disconnect; GSimpleAsyncResult *result; } Disconnect3gppContext; struct _MMBroadbandBearerCinterionPrivate { - guint network_disconnect_pending_id;/* Flag for network-initiated disconnect */ - guint pdp_cid;/* Mapping for PDP Context to network (SWWAN) interface */ + /* Flag for network-initiated disconnect */ + guint network_disconnect_pending_id; }; /*****************************************************************************/ @@ -96,23 +150,6 @@ static void disconnect_3gpp_context_complete_and_free (Disconnect3gppContext *ct /*****************************************************************************/ /* Common - Helper Functions*/ -static void -pdp_cid_map (MMBroadbandBearerCinterion *self, const gchar *bearer_interface) -{ - /* Map PDP context from the current Bearer. USB0 -> 3rd context, USB1 -> 1st context. - * Note - Cinterion told me specifically to map the contexts to the interfaces this way, though - * I've seen that SWWAN appear's to work fine with any PDP to any interface */ - - if (g_strcmp0 (bearer_interface, "0a") == 0) - self->priv->pdp_cid = 3; - else if (g_strcmp0 (bearer_interface, "0c") == 0) - self->priv->pdp_cid = 1; - else - /* Shouldn't be able to create a bearer for SWWAN and not be able to - * find the net interface. Otherwise connects/disconnects will get wrecked */ - g_assert_not_reached (); -} - static gint verify_connection_state_from_swwan_response (GList *result, GError **error) { @@ -199,25 +236,6 @@ connect_3gpp_finish (MMBroadbandBearer *self, return mm_bearer_connect_result_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res))); } - - -static void -pdp_cid_connect (Connect3gppContext *ctx) -{ - const gchar *bearer_interface; - - /* For E: INTERFACE=usb0 -> E: ID_USB_INTERFACE_NUM=0a - * For E: INTERFACE=usb1 -> E: ID_USB_INTERFACE_NUM=0c */ - - /* Look up the net port to associate with this bearer */ - bearer_interface = mm_kernel_device_get_property (mm_port_peek_kernel_device (ctx->data), - "ID_USB_INTERFACE_NUM"); - - pdp_cid_map (ctx->self, bearer_interface); - - return; -} - static void get_cmd_write_response_ctx_connect (MMBaseModem *modem, GAsyncResult *res, @@ -333,9 +351,8 @@ build_cinterion_auth_string (Connect3gppContext *ctx) * ERROR * +CME ERROR: <err> */ - - command = g_strdup_printf ("^SGAUTH=%i,%i,%s,%s", - ctx->self->priv->pdp_cid, + command = g_strdup_printf ("^SGAUTH=%u,%i,%s,%s", + usb_interface_configs[ctx->usb_interface_config_index].pdp_context, encoded_auth, passwd, user); @@ -353,9 +370,9 @@ build_cinterion_pdp_context_string (Connect3gppContext *ctx) /* TODO: Get IP type if protocol was specified. Hardcoded to IPV4 for now */ - command = g_strdup_printf ("+CGDCONT=%i,\"IP\",\"%s\"", - ctx->self->priv->pdp_cid, - apn == NULL ? "" : apn); + command = g_strdup_printf ("+CGDCONT=%u,\"IP\",\"%s\"", + usb_interface_configs[ctx->usb_interface_config_index].pdp_context, + apn ? apn : ""); return command; } @@ -366,10 +383,9 @@ handle_cancel_connect (Connect3gppContext *ctx) gchar *command; /* 3rd context -> 1st wwan adapt / 1st context -> 2nd wwan adapt */ - command = g_strdup_printf ("^SWWAN=%s,%i,%i", - "0", - ctx->self->priv->pdp_cid, - ctx->self->priv->pdp_cid == 3 ? FIRST_USB_INTERFACE : SECOND_USB_INTERFACE); + command = g_strdup_printf ("^SWWAN=0,%u,%u", + usb_interface_configs[ctx->usb_interface_config_index].pdp_context, + usb_interface_configs[ctx->usb_interface_config_index].swwan_index); /* Disconnect, may not succeed. Will not check response on cancel */ mm_base_modem_at_command_full (ctx->modem, @@ -445,10 +461,9 @@ send_swwan_connect_command_ctx_connect (Connect3gppContext *ctx) { /* 3rd context -> 1st wwan adapt / 1st context -> 2nd wwan adapt */ gchar *command; - command = g_strdup_printf ("^SWWAN=%s,%i,%i", - "1", - ctx->self->priv->pdp_cid, - ctx->self->priv->pdp_cid == 3 ? FIRST_USB_INTERFACE : SECOND_USB_INTERFACE); + command = g_strdup_printf ("^SWWAN=1,%u,%u", + usb_interface_configs[ctx->usb_interface_config_index].pdp_context, + usb_interface_configs[ctx->usb_interface_config_index].swwan_index); send_write_command_ctx_connect(ctx, &command); @@ -460,10 +475,9 @@ send_swwan_disconnect_command_ctx_connect (Connect3gppContext *ctx) { /* 3rd context -> 1st wwan adapt / 1st context -> 2nd wwan adapt */ gchar *command; - command = g_strdup_printf ("^SWWAN=%s,%i,%i", - "0", - ctx->self->priv->pdp_cid, - ctx->self->priv->pdp_cid == 3 ? FIRST_USB_INTERFACE : SECOND_USB_INTERFACE); + command = g_strdup_printf ("^SWWAN=0,%u,%u", + usb_interface_configs[ctx->usb_interface_config_index].pdp_context, + usb_interface_configs[ctx->usb_interface_config_index].swwan_index); send_write_command_ctx_connect(ctx, &command); @@ -548,9 +562,6 @@ connect_3gpp_context_step (Connect3gppContext *ctx) /* Setup bearer */ create_cinterion_bearer (ctx); - /* Clear context */ - ctx->self->priv->pdp_cid = 0; - connect_3gpp_context_complete_and_free (ctx); return; } @@ -567,6 +578,8 @@ connect_3gpp (MMBroadbandBearer *self, { Connect3gppContext *ctx; MMPort *port; + gint usb_interface_config_index; + GError *error = NULL; g_assert (primary != NULL); @@ -582,11 +595,22 @@ connect_3gpp (MMBroadbandBearer *self, return; } + /* Validate configuration */ + usb_interface_config_index = get_usb_interface_config_index (port, &error); + if (usb_interface_config_index < 0) { + g_simple_async_report_take_gerror_in_idle (G_OBJECT (self), + callback, + user_data, + error); + return; + } + /* Setup connection context */ ctx = g_slice_new0 (Connect3gppContext); ctx->self = g_object_ref (self); ctx->modem = g_object_ref (modem); ctx->data = g_object_ref (port); + ctx->usb_interface_config_index = usb_interface_config_index; ctx->result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, @@ -594,9 +618,6 @@ connect_3gpp (MMBroadbandBearer *self, ctx->cancellable = g_object_ref (cancellable); ctx->primary = g_object_ref (primary); - /* Maps Bearer-> Net Interface-> PDP Context */ - pdp_cid_connect (ctx); - /* Initialize */ ctx->connect = CONNECT_3GPP_CONTEXT_STEP_INIT; @@ -609,23 +630,6 @@ connect_3gpp (MMBroadbandBearer *self, /* Disconnect - Helper Functions*/ static void -pdp_cid_disconnect(Disconnect3gppContext *ctx) -{ - const gchar *bearer_interface; - - /* For E: INTERFACE=usb0 -> E: ID_USB_INTERFACE_NUM=0a - * For E: INTERFACE=usb1 -> E: ID_USB_INTERFACE_NUM=0c */ - - /* Look up the net port to associate with this bearer */ - bearer_interface = mm_kernel_device_get_property (mm_port_peek_kernel_device (ctx->data), - "ID_USB_INTERFACE_NUM"); - - pdp_cid_map (ctx->self, bearer_interface); - - return; -} - -static void get_cmd_write_response_ctx_disconnect (MMBaseModem *modem, GAsyncResult *res, Disconnect3gppContext *ctx) @@ -685,10 +689,9 @@ send_swwan_disconnect_command_ctx_disconnect (Disconnect3gppContext *ctx) { /* 3rd context -> 1st wwan adapt / 1st context -> 2nd wwan adapt */ gchar *command; - command = g_strdup_printf ("^SWWAN=%s,%i,%i", - "0", - ctx->self->priv->pdp_cid, - ctx->self->priv->pdp_cid == 3 ? FIRST_USB_INTERFACE : SECOND_USB_INTERFACE); + command = g_strdup_printf ("^SWWAN=0,%u,%u", + usb_interface_configs[ctx->usb_interface_config_index].pdp_context, + usb_interface_configs[ctx->usb_interface_config_index].swwan_index); mm_base_modem_at_command_full (ctx->modem, ctx->primary, @@ -761,8 +764,6 @@ disconnect_3gpp_context_step (Disconnect3gppContext *ctx) case DISCONNECT_3GPP_CONTEXT_STEP_FINISH: - ctx->self->priv->pdp_cid = 0; - g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); disconnect_3gpp_context_complete_and_free (ctx); @@ -781,10 +782,22 @@ disconnect_3gpp (MMBroadbandBearer *self, gpointer user_data) { Disconnect3gppContext *ctx; + gint usb_interface_config_index; + GError *error = NULL; g_assert (primary != NULL); g_assert (data != NULL); + /* Validate configuration */ + usb_interface_config_index = get_usb_interface_config_index (data, &error); + if (usb_interface_config_index < 0) { + g_simple_async_report_take_gerror_in_idle (G_OBJECT (self), + callback, + user_data, + error); + return; + } + /* Setup connection context */ ctx = g_slice_new0 (Disconnect3gppContext); ctx->self = g_object_ref (self); @@ -793,12 +806,9 @@ disconnect_3gpp (MMBroadbandBearer *self, callback, user_data, disconnect_3gpp); - ctx->data = g_object_ref (data); ctx->primary = g_object_ref (primary); - - /* Maps Bearer->Net Interface-> PDP Context - * We can't disconnect if we don't know which context to disconnect from. */ - pdp_cid_disconnect (ctx); + ctx->data = g_object_ref (data); + ctx->usb_interface_config_index = usb_interface_config_index; /* Initialize */ ctx->disconnect = DISCONNECT_3GPP_CONTEXT_STEP_STOP_SWWAN; |