<HTML><HEAD></HEAD><BODY id="enrich@telit.com"><!--?xml version="1.0" encoding="UTF-8"?-->
<p><br />
<table style="height: 80%;" border="0" cellspacing="0" cellpadding="0" width="95%" id="imp_template" class="enrich@telit.com">
<tbody>
<tr height="80%">
<td id="etexttd" class="mceNonEditable mceNonResizeable" style="padding:10px;" width="100%" valign="top">
<div id="imp_emailtext" class="mceNonEditable mceNonResizeable">Hi Aleksander,<br /><br />thanks for the review. I agree with all the changes, but regarding the usage of the secondary port, the reason is that I couldn't get unsolicited messages from the primary port when the modem is connected to a network. The same problem does not occur when not connected, namely I get all the unsolicited.<br /><br />I also checked with a USB sniffer and the modem is always sending the unsolicited, just I can't see it on MM. Instead, using the secondary port this issue does not occur.<br /><br />Consider that the modem sends QSS only from the port where it's been set, so I can't set it on the primary and listen on the secondary.<br /><br /><br />On giovedì 30 giugno 2016 16:06:23 CEST Aleksander Morgado wrote:<br />> Hey,<br />> <br />> ><br />> > sorry but I sent the previous email before completing it. This<br />> > proposal is based on two patches.<br />> > The first, in the previous e-mail, adds the core logic for modems that<br />> > support SIM hot swap,<br />> > The second in this e-mail, is the plugin side implementation for a Telit modem.<br />> ><br />> > Carlo<br />> ><br />> > ---<br />> ><br />> > MMBroadbandModemTelit:<br />> > * added SIM_HOT_SWAP property and updated init function accordingly<br />> > * added function to enable QSS unsolicited<br />> > * added QSS unsolicited handler<br />> > ---<br />> > plugins/dell/mm-plugin-dell.c | 3 +-<br />> > plugins/telit/mm-broadband-modem-telit.c | 185 ++++++++++++++++++++++++++++++-<br />> > plugins/telit/mm-broadband-modem-telit.h | 7 +-<br />> > plugins/telit/mm-plugin-telit.c | 3 +-<br />> > 4 files changed, 191 insertions(+), 4 deletions(-)<br />> ><br />> > diff --git a/plugins/dell/mm-plugin-dell.c b/plugins/dell/mm-plugin-dell.c<br />> > index 2ed4375..9275a04 100644<br />> > --- a/plugins/dell/mm-plugin-dell.c<br />> > +++ b/plugins/dell/mm-plugin-dell.c<br />> > @@ -424,7 +424,8 @@ create_modem (MMPlugin *self,<br />> > drivers,<br />> ><br />> > mm_plugin_get_name (self),<br />> > vendor,<br />> > - product));<br />> > + product,<br />> > + TRUE /*<br />> > SIM hot swap supported */));<br />> <br />> If SIM hotswap always supported, what's the purpose of having the<br />> additional argument in mm_broadband_modem_telit_new()? I would just<br />> remove the additional argument.<br />> <br />> <br />> > }<br />> ><br />> > mm_dbg ("Dell-branded generic modem found...");<br />> > diff --git a/plugins/telit/mm-broadband-modem-telit.c<br />> > b/plugins/telit/mm-broadband-modem-telit.c<br />> > index 8baf2cf..b8ca965 100644<br />> > --- a/plugins/telit/mm-broadband-modem-telit.c<br />> > +++ b/plugins/telit/mm-broadband-modem-telit.c<br />> > @@ -42,6 +42,131 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModemTelit,<br />> > mm_broadband_modem_telit, MM_TYPE<br />> > G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM,<br />> > iface_modem_init)<br />> > G_IMPLEMENT_INTERFACE<br />> > (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init));<br />> ><br />> > +<br />> > +struct _MMBroadbandModemTelitPrivate {<br />> > + gboolean is_sim_hot_swap_supported;<br />> <br />> This gboolean is the one providing the value to the property; it<br />> should go in MMBroadbandModem so that all modems have the boolean, not<br />> just the Telit one.<br />> <br />> You can then g_object_get() the property in the plugin to know the value.<br />> <br />> > + GAsyncReadyCallback sim_swap_callback;<br />> > +};<br />> > +<br />> > +enum {<br />> > + PROP_FIRST,<br />> > + PROP_IS_SIM_HOT_SWAP_SUPPORTED,<br />> > + PROP_LAST<br />> > +};<br />> > +<br />> > +/*****************************************************************************/<br />> > +/* Setup SIM hot swap (Modem interface) */<br />> > +<br />> > +static void<br />> > +telit_qss_unsolicited_handler (MMPortSerialAt *port,<br />> > + GMatchInfo *match_info,<br />> > + MMBroadbandModemTelit *self)<br />> > +{<br />> > + guint qss;<br />> > + gboolean is_sim_missing;<br />> > +<br />> > + if (!mm_get_uint_from_match_info (match_info, 1, &qss))<br />> > + return;<br />> > +<br />> > + switch(qss) {<br />> <br />> Missing whitespaces before open-parenthesis; please review the whole<br />> patch fixing those, they're in multiple places.<br />> <br />> > + case 0:<br />> > + mm_info("QSS: SIM removed");<br />> > + break;<br />> > + case 1:<br />> > + mm_info("QSS: SIM inserted");<br />> > + break;<br />> > + case 2:<br />> > + mm_info("QSS: SIM inserted and PIN unlocked");<br />> > + break;<br />> > + case 3:<br />> > + mm_info("QSS: SIM inserted and PIN locked");<br />> > + break;<br />> > + default:<br />> > + mm_warn("QSS: unknown QSS value %d", qss);<br />> > + break;<br />> > + }<br />> > +<br />> > + is_sim_missing = (qss == 0) ? TRUE : FALSE;<br />> > + mm_broadband_modem_update_sim_hot_swap_status (MM_BROADBAND_MODEM<br />> > (self), is_sim_missing);<br />> > +}<br />> > +<br />> > +typedef struct {<br />> > + MMBroadbandModemTelit *self;<br />> > + GSimpleAsyncResult *result;<br />> > +} ToggleQssUnsolicitedContext;<br />> > +<br />> > +static void<br />> > +toggle_qss_unsolicited_context_complete_and_free<br />> > (ToggleQssUnsolicitedContext *ctx)<br />> > +{<br />> > + g_simple_async_result_complete (ctx->result);<br />> > + g_object_unref (ctx->result);<br />> > + g_object_unref (ctx->self);<br />> > + g_slice_free (ToggleQssUnsolicitedContext, ctx);<br />> > +}<br />> > +<br />> > +static gboolean<br />> > +modem_setup_sim_hot_swap_finish (MMIfaceModem *self,<br />> > + GAsyncResult *res,<br />> > + GError **error)<br />> > +{<br />> > + return !g_simple_async_result_propagate_error<br />> > (G_SIMPLE_ASYNC_RESULT (res), error);<br />> > +}<br />> > +<br />> > +static void<br />> > +telit_qss_toggle_ready (MMBaseModem *self,<br />> > + GAsyncResult *res,<br />> > + ToggleQssUnsolicitedContext *ctx)<br />> > +{<br />> > + GError *error = NULL;<br />> > +<br />> > + mm_base_modem_at_command_finish (self, res, &error);<br />> > + if (error) {<br />> > + mm_warn ("Enable QSS failed: %s", error->message);<br />> > + g_simple_async_result_set_error (ctx->result,<br />> > + MM_CORE_ERROR,<br />> > + MM_CORE_ERROR_FAILED,<br />> > + "Could not enable QSS");<br />> <br />> error is leaking here.<br />> <br />> > + } else {<br />> > + mm_port_serial_at_add_unsolicited_msg_handler (<br />> > + mm_base_modem_peek_port_secondary (MM_BASE_MODEM (ctx->self)),<br />> > + g_regex_new ("#QSS:\\s*([0-3])\\r\\n", G_REGEX_RAW, 0, NULL),<br />> > + (MMPortSerialAtUnsolicitedMsgFn)telit_qss_unsolicited_handler,<br />> > + ctx->self,<br />> > + NULL);<br />> <br />> The mm_port_serial_at_add_unsolicited_msg_handler() takes its own<br />> reference to the GRegex, so that would be leaking.<br />> <br />> You should create the GRegex, pass it to<br />> mm_port_serial_at_add_unsolicited_msg_handler(), then unref the<br />> original reference.<br />> <br />> > + g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);<br />> > + }<br />> > +<br />> > + toggle_qss_unsolicited_context_complete_and_free (ctx);<br />> > +}<br />> > +<br />> > +<br />> > +static void<br />> > +modem_setup_sim_hot_swap (MMIfaceModem *self,<br />> > + GAsyncReadyCallback callback,<br />> > + gpointer user_data)<br />> > +{<br />> > + ToggleQssUnsolicitedContext *ctx;<br />> > +<br />> > + mm_dbg ("Telit: enabling QSS");<br />> > +<br />> > + ctx = g_slice_new0 (ToggleQssUnsolicitedContext);<br />> > + ctx->self = g_object_ref (MM_BROADBAND_MODEM_TELIT (self));<br />> > + ctx->result = g_simple_async_result_new (G_OBJECT (self),<br />> > + callback,<br />> > + user_data,<br />> > + modem_setup_sim_hot_swap);<br />> > +<br />> > + mm_base_modem_at_command_full (MM_BASE_MODEM (self),<br />> > + mm_base_modem_peek_port_secondary<br />> <br />> You're assuming there's a secondary port, we shouldn't do that. What<br />> if there's only one port? What if for some reason MM is able to just<br />> one even if there are more?<br />> <br />> Can't this QSS command be sent to the primary port? We always have a<br />> primary port.<br />> <br />> > (MM_BASE_MODEM (self)),<br />> > + "#QSS=1",<br />> > + 3,<br />> > + FALSE,<br />> > + FALSE, /* raw */<br />> > + NULL, /* cancellable */<br />> > + (GAsyncReadyCallback)<br />> > telit_qss_toggle_ready,<br />> > + ctx);<br />> > +}<br />> > +<br />> > /*****************************************************************************/<br />> > /* Set current bands (Modem interface) */<br />> ><br />> > @@ -1009,7 +1134,8 @@ mm_broadband_modem_telit_new (const gchar *device,<br />> > const gchar **drivers,<br />> > const gchar *plugin,<br />> > guint16 vendor_id,<br />> > - guint16 product_id)<br />> > + guint16 product_id,<br />> > + gboolean is_sim_hot_swap_supported)<br />> > {<br />> > return g_object_new (MM_TYPE_BROADBAND_MODEM_TELIT,<br />> > MM_BASE_MODEM_DEVICE, device,<br />> > @@ -1017,12 +1143,17 @@ mm_broadband_modem_telit_new (const gchar *device,<br />> > MM_BASE_MODEM_PLUGIN, plugin,<br />> > MM_BASE_MODEM_VENDOR_ID, vendor_id,<br />> > MM_BASE_MODEM_PRODUCT_ID, product_id,<br />> > + IS_SIM_HOT_SWAP_SUPPORTED_PROPERTY,<br />> > is_sim_hot_swap_supported,<br />> > NULL);<br />> <br />> As said before, I'd just remove the is_sim_hot_swap_supported extra<br />> argument from the mm_broadband_modem_telit_new() method, and then<br />> just):<br />> IS_SIM_HOT_SWAP_SUPPORTED_PROPERTY, TRUE<br />> <br />> > }<br />> ><br />> > static void<br />> > mm_broadband_modem_telit_init (MMBroadbandModemTelit *self)<br />> > {<br />> > + /* Initialize private data */<br />> > + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,<br />> > + MM_TYPE_BROADBAND_MODEM_TELIT,<br />> > + MMBroadbandModemTelitPrivate);<br />> > }<br />> ><br />> > static void<br />> > @@ -1052,6 +1183,8 @@ iface_modem_init (MMIfaceModem *iface)<br />> > iface->load_current_modes_finish = load_current_modes_finish;<br />> > iface->set_current_modes = set_current_modes;<br />> > iface->set_current_modes_finish = set_current_modes_finish;<br />> > + iface->setup_sim_hot_swap = modem_setup_sim_hot_swap;<br />> > + iface->setup_sim_hot_swap_finish = modem_setup_sim_hot_swap_finish;<br />> > }<br />> ><br />> > static void<br />> > @@ -1062,6 +1195,56 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface)<br />> > }<br />> ><br />> > static void<br />> > +set_property (GObject *object,<br />> > + guint prop_id,<br />> > + const GValue *value,<br />> > + GParamSpec *pspec)<br />> > +{<br />> > + MMBroadbandModemTelit *self = MM_BROADBAND_MODEM_TELIT (object);<br />> > +<br />> > + switch (prop_id) {<br />> > + case PROP_IS_SIM_HOT_SWAP_SUPPORTED:<br />> > + self->priv->is_sim_hot_swap_supported = g_value_get_boolean (value);<br />> > + break;<br />> > + default:<br />> > + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);<br />> > + break;<br />> > + }<br />> > +}<br />> > +<br />> > +static void<br />> > +get_property (GObject *object,<br />> > + guint prop_id,<br />> > + GValue *value,<br />> > + GParamSpec *pspec)<br />> > +{<br />> > + MMBroadbandModemTelit *self = MM_BROADBAND_MODEM_TELIT (object);<br />> > +<br />> > + switch (prop_id) {<br />> > + case PROP_IS_SIM_HOT_SWAP_SUPPORTED:<br />> > + g_value_set_boolean (value, self->priv->is_sim_hot_swap_supported);<br />> > + break;<br />> > + default:<br />> > + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);<br />> > + break;<br />> > + }<br />> > +}<br />> <br />> These setter and getter should go in MMBroadbandModem.<br />> <br />> <br />> > +<br />> > +static void<br />> > mm_broadband_modem_telit_class_init (MMBroadbandModemTelitClass *klass)<br />> > {<br />> > + GObjectClass *object_class = G_OBJECT_CLASS (klass);<br />> > +<br />> > + g_type_class_add_private (object_class, sizeof<br />> > (MMBroadbandModemTelitPrivate));<br />> > +<br />> > + object_class->set_property = set_property;<br />> > + object_class->get_property = get_property;<br />> > +<br />> > + g_object_class_install_property (object_class,<br />> > PROP_IS_SIM_HOT_SWAP_SUPPORTED,<br />> > + g_param_spec_boolean (IS_SIM_HOT_SWAP_SUPPORTED_PROPERTY,<br />> > + "IsSimHotSwapSupported",<br />> > + "Whether the modem supports sim hot<br />> > swap or not.",<br />> > + TRUE,<br />> > + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));<br />> <br />> Same for the property itself, it should go in MMBroadbandModem.<br />> <br />> <br />> > +<br />> > }<br />> > diff --git a/plugins/telit/mm-broadband-modem-telit.h<br />> > b/plugins/telit/mm-broadband-modem-telit.h<br />> > index 50e6365..37e2f21 100644<br />> > --- a/plugins/telit/mm-broadband-modem-telit.h<br />> > +++ b/plugins/telit/mm-broadband-modem-telit.h<br />> > @@ -27,11 +27,15 @@<br />> > #define MM_IS_BROADBAND_MODEM_TELIT_CLASS(klass)<br />> > (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_TELIT))<br />> > #define MM_BROADBAND_MODEM_TELIT_GET_CLASS(obj)<br />> > (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_TELIT,<br />> > MMBroadbandModemTelitClass))<br />> ><br />> > +#define IS_SIM_HOT_SWAP_SUPPORTED_PROPERTY "is-sim-hot-swap-supported"<br />> > +<br />> <br />> Why is this redefined here? Wasn't this defined in mm-iface-modem?<br />> <br />> > typedef struct _MMBroadbandModemTelit MMBroadbandModemTelit;<br />> > +typedef struct _MMBroadbandModemTelitPrivate MMBroadbandModemTelitPrivate;<br />> > typedef struct _MMBroadbandModemTelitClass MMBroadbandModemTelitClass;<br />> ><br />> > struct _MMBroadbandModemTelit {<br />> > MMBroadbandModem parent;<br />> > + MMBroadbandModemTelitPrivate *priv;<br />> > };<br />> ><br />> > struct _MMBroadbandModemTelitClass{<br />> > @@ -44,6 +48,7 @@ MMBroadbandModemTelit *mm_broadband_modem_telit_new<br />> > (const gchar *device,<br />> > const gchar **drivers,<br />> > const gchar *plugin,<br />> > guint16 vendor_id,<br />> > - guint16 product_id);<br />> > + guint16 product_id,<br />> > + gboolean<br />> > is_sim_hot_swap_supported);<br />> ><br />> > #endif /* MM_BROADBAND_MODEM_TELIT_H */<br />> > diff --git a/plugins/telit/mm-plugin-telit.c b/plugins/telit/mm-plugin-telit.c<br />> > index 5a44ba6..b9506da 100644<br />> > --- a/plugins/telit/mm-plugin-telit.c<br />> > +++ b/plugins/telit/mm-plugin-telit.c<br />> > @@ -48,7 +48,8 @@ create_modem (MMPlugin *self,<br />> > drivers,<br />> ><br />> > mm_plugin_get_name (self),<br />> > vendor,<br />> > - product));<br />> > + product,<br />> > + TRUE /*<br />> > support sim hot swap */));<br />> <br />> <br />> As said before, I'd remove the extra gboolean arg from<br />> mm_broadband_modem_telit_new(), if it's always TRUE.<br />> <br />> > }<br />> ><br />> > /*****************************************************************************/<br />> ><br />> <br />> <br />> <br /><br /></div>
</td>
</tr>
<tr height="20%">
<td width="100%">
<table id="row2" style="height: 100%; font-family: Arial,Helvetica,sans-serif;" border="0" cellspacing="0" cellpadding="2" width="100%">
<tbody>
<tr>
<td width="100%">
<table border="0">
<tbody>
<tr>
<td> <table id="autoSig" style="height: 100%; font-family: Arial,Helvetica,sans-serif;" border="0" cellspacing="0" cellpadding="2" width="100%">
<tbody>
<tr>
<td width="100%">
<table border="0" width="95%" align="left">
<tbody>
<tr>
<td colspan="2"><span style="font-family: arial,helvetica,sans-serif; color: #003366;"><strong>Carlo Lobrano <br /></strong></span></td>
</tr>
<tr>
<td colspan="2"><span style="font-family: arial,helvetica,sans-serif; color: #003366;">Senior Software Engineer, R&D <br /></span></td>
</tr>
<tr>
<td rowspan="3" width="100"><span style="font-family: arial,helvetica,sans-serif; color: #003366;"><img class="embedded_img" src="cid:imp_0.7706962700687823_autosig_Image_01" border="0" alt="Link" width="87" height="50" / style=" max-width:100%;"></span></td>
<td id="optional" valign="top"><span style="font-family: arial,helvetica,sans-serif; color: #003366;">T:<strong> </strong> </span><span style="font-family: arial,helvetica,sans-serif; color: #003366;">+39 040 4192 560</span></td>
</tr>
<tr>
<TD>
</TD></tr>
<tr>
<td valign="top"><span style="font-family: arial,helvetica,sans-serif; color: #003366;"><a style="text-decoration: none; color:inherit;" id="rt" href="mailto:carlo.lobrano@telit.com"><strong style="text-decoration: none; color:inherit; font-weight:inherit;">carlo.lobrano@telit.com</strong></a></span></td>
</tr>
<tr>
<td colspan="2"><span style="font-family: arial,helvetica,sans-serif; color: #003366;"><img class="embedded_img" src="cid:imp_0.4702790782620736_autosig_Image_02" border="0" alt="Link" width="291" height="7" / style=" max-width:100%;"></span></td>
</tr>
<tr>
<td id="rt" style="font-family: arial,helvetica,sans-serif; color: #003366;" width="100"><a id="rt" href="http://www.telit.com">www.telit.com</a></td>
<td>
<table border="0">
<tbody>
<tr>
<td> <br /></td>
<td><span style="font-family: arial,helvetica,sans-serif; color: #003366;"><a href="http://robustus.impactia.com/AnalyticServer/redirect?cid=15fbbe1bb7e142c9&mid=76961948&eurl=aHR0cDovL3d3dy55b3V0dWJlLmNvbS90ZWxpdGNvbW11bmljYXRpb25z&istmp=enrich@telit.com"><img class="embedded_img" src="cid:imp_0.5532723427003916_autosig_Image_03" border="0" alt="Link" / style=" max-width:100%;"></a></span></td>
<td><a href="http://robustus.impactia.com/AnalyticServer/redirect?cid=15fbbe1bb7e142c9&mid=76961948&eurl=aHR0cHM6Ly9wbHVzLmdvb2dsZS5jb20vK3RlbGl0&istmp=enrich@telit.com"><img class="embedded_img" src="cid:imp_0.6861437723755275_autosig_Image_04" border="0" alt="Link" / style=" max-width:100%;"></a></td>
<td><span style="font-family: arial,helvetica,sans-serif; color: #003366;"><a href="http://robustus.impactia.com/AnalyticServer/redirect?cid=15fbbe1bb7e142c9&mid=76961948&eurl=aHR0cHM6Ly90d2l0dGVyLmNvbS9UZWxpdF9XU19jb3Jw&istmp=enrich@telit.com"><img class="embedded_img" src="cid:imp_0.8252852095764112_autosig_Image_05" border="0" alt="Link" / style=" max-width:100%;"></a></span></td>
<td><span style="font-family: arial,helvetica,sans-serif; color: #003366;"><a href="http://robustus.impactia.com/AnalyticServer/redirect?cid=15fbbe1bb7e142c9&mid=76961948&eurl=aHR0cDovL2ZhY2Vib29rLmNvbS90ZWxpdHdpcmVsZXNz&istmp=enrich@telit.com"><img class="embedded_img" src="cid:imp_0.017211039270454198_autosig_Image_06" border="0" alt="Link" / style=" max-width:100%;"></a></span></td>
<td><span style="font-family: arial,helvetica,sans-serif; color: #003366;"><a href="http://robustus.impactia.com/AnalyticServer/redirect?cid=15fbbe1bb7e142c9&mid=76961948&eurl=aHR0cDovL3d3dy5saW5rZWRpbi5jb20vY29tcGFueS90ZWxpdC13aXJlbGVzcy1zb2x1dGlvbnM=&istmp=enrich@telit.com"><img class="embedded_img" src="cid:imp_0.07153260227664593_autosig_Image_07" border="0" alt="Link" / style=" max-width:100%;"></a></span></td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table> <br /></td>
</tr>
<tr>
<td><a href="http://robustus.impactia.com/AnalyticServer/redirect?cid=15fbbe1bb7e142c9&mid=76961948&eurl=aHR0cDovL3d3dy5pb3QtZXhlY3V0aXZlLWhhbmRib29rLmNvbS9nZXQtdGhlLWJvb2sv&istmp=enrich@telit.com"><img class="embedded_img" src="cid:imp_0.9930939633280242_Image_01" border="0" alt="Link" / style=" max-width:100%;"></a><br />
<table border="0" cellspacing="1" cellpadding="1">
<tbody>
<tr>
<td rowspan="6"><span style="font-size: xx-small; font-family: verdana,geneva;"><span style="color: #808080;">This electronic message, including attachments, is intended only for the use of the individual or company named above or to which it is addressed. <br />The information contained in this message shall be considered confidential and proprietary, and may include confidential work product. If you are not the intended recipient, please be aware that any unauthorized use, <br />dissemination, distribution or copying of this message is strictly prohibited. If you have received this email in error, please notify the sender by replying to this message and deleting this email immediately. <br /></span><br /><span style="color: #808080;">To the extent this email includes an offer to buy Telit products or an order confirmation, the offer or order confirmation is governed by Telit’s General Terms and Conditions of Sale, which are published <a id="rt" href="http://www.telit.com/terms-and-conditions/">here</a>.<br /></span></span><span style="font-size: xx-small; font-family: verdana,geneva;"><span style="color: #808080;"><br /></span></span></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</p><div id="footer" class="mceNonEditable mceNonResizeable" dir="ltr">
<hr size="1" noshade="65535" />
<span style="font-size: 7.5pt; font-family: Arial,sans-serif; color: #808080;"><br /></span></div>
</p></BODY></HTML>