aboutsummaryrefslogtreecommitdiff
path: root/libwmc/src
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2011-11-11 12:20:51 -0600
committerDan Williams <dcbw@redhat.com>2011-11-11 12:21:41 -0600
commitae3f1cd578e59245a6bff5cfd19f64f0c47f5de9 (patch)
tree5db2e66c1688643a58567bc97a58048b798b9c20 /libwmc/src
parent83c905837693f095d9e7c1bf9ac56d8290510f45 (diff)
libwmc: add testcases that talk to the device
Diffstat (limited to 'libwmc/src')
-rw-r--r--libwmc/src/commands.c70
-rw-r--r--libwmc/src/commands.h5
-rw-r--r--libwmc/src/protocol.h17
-rw-r--r--libwmc/src/utils.c79
-rw-r--r--libwmc/src/utils.h26
5 files changed, 185 insertions, 12 deletions
diff --git a/libwmc/src/commands.c b/libwmc/src/commands.c
index 08bfd4da..cda4a5be 100644
--- a/libwmc/src/commands.c
+++ b/libwmc/src/commands.c
@@ -27,16 +27,22 @@
/**********************************************************************/
static int
-check_command (const char *buf, gsize len, guint8 cmd, gsize min_len)
+check_command (const char *buf, gsize len, u_int8_t cmd, size_t min_len)
{
if (len < 1) {
wmc_err (0, "Zero-length response");
return -WMC_ERROR_RESPONSE_BAD_LENGTH;
}
- if (buf[0] != cmd) {
- wmc_err (0, "Unexpected WMC command response (expected %d, got %d)",
- cmd, buf[0]);
+ if ((u_int8_t) buf[0] != WMC_CMD_MARKER) {
+ wmc_err (0, "Missing WMC command marker (expected 0x%02X, got 0x%02X)",
+ WMC_CMD_MARKER, (u_int8_t) buf[0]);
+ return -WMC_ERROR_RESPONSE_UNEXPECTED;
+ }
+
+ if ((u_int8_t) buf[1] != cmd) {
+ wmc_err (0, "Unexpected WMC command response (expected 0x%02X, got 0x%02X)",
+ (u_int8_t) cmd, (u_int8_t) buf[1]);
return -WMC_ERROR_RESPONSE_UNEXPECTED;
}
@@ -51,6 +57,61 @@ check_command (const char *buf, gsize len, guint8 cmd, gsize min_len)
/**********************************************************************/
+/**
+ * wmc_cmd_init_new:
+ * @buf: buffer in which to store constructed command
+ * @buflen: size of @buf
+ * @wmc2: if %TRUE add additional data that later-model devices (UML290) want
+ *
+ * Returns: size of the constructed command on success, or 0 on failure
+ */
+size_t
+wmc_cmd_init_new (char *buf, size_t buflen, int wmc2)
+{
+ wmc_return_val_if_fail (buf != NULL, 0);
+
+ if (wmc2) {
+ WmcCmdInit2 *cmd = (WmcCmdInit2 *) buf;
+ const char data[] = { 0xda, 0x07, 0x0c, 0x00, 0x1e, 0x00, 0x09, 0x00, 0x39,
+ 0x00, 0x18, 0x00, 0x04, 0x00 };
+
+ wmc_return_val_if_fail (buflen >= sizeof (*cmd), 0);
+
+ memset (cmd, 0, sizeof (*cmd));
+ cmd->hdr.marker = WMC_CMD_MARKER;
+ cmd->hdr.cmd = WMC_CMD_INIT;
+ memcpy (cmd->_unknown1, data, sizeof (data));
+ return sizeof (*cmd);
+ } else {
+ WmcCmdHeader *cmd = (WmcCmdHeader *) buf;
+
+ wmc_return_val_if_fail (buflen >= sizeof (*cmd), 0);
+
+ memset (cmd, 0, sizeof (*cmd));
+ cmd->marker = WMC_CMD_MARKER;
+ cmd->cmd = WMC_CMD_INIT;
+ return sizeof (*cmd);
+ }
+}
+
+WmcResult *
+wmc_cmd_init_result (const char *buf, gsize buflen, int wmc2)
+{
+ g_return_val_if_fail (buf != NULL, NULL);
+
+ if (wmc2) {
+ if (check_command (buf, buflen, WMC_CMD_INIT, sizeof (WmcCmdInit2Rsp)) < 0)
+ return NULL;
+ } else {
+ if (check_command (buf, buflen, WMC_CMD_INIT, sizeof (WmcCmdHeader)) < 0)
+ return NULL;
+ }
+
+ return wmc_result_new ();
+}
+
+/**********************************************************************/
+
size_t
wmc_cmd_device_info_new (char *buf, size_t buflen)
{
@@ -60,6 +121,7 @@ wmc_cmd_device_info_new (char *buf, size_t buflen)
wmc_return_val_if_fail (buflen >= sizeof (*cmd), 0);
memset (cmd, 0, sizeof (*cmd));
+ cmd->marker = WMC_CMD_MARKER;
cmd->cmd = WMC_CMD_DEVICE_INFO;
return sizeof (*cmd);
}
diff --git a/libwmc/src/commands.h b/libwmc/src/commands.h
index dba839b5..60ecdac0 100644
--- a/libwmc/src/commands.h
+++ b/libwmc/src/commands.h
@@ -24,6 +24,11 @@
/* Generic enums */
+/**********************************************************************/
+
+size_t wmc_cmd_init_new (char *buf, size_t buflen, int wmc2);
+
+WmcResult * wmc_cmd_init_result (const char *buf, size_t len, int wmc2);
/**********************************************************************/
diff --git a/libwmc/src/protocol.h b/libwmc/src/protocol.h
index 7bc751ee..b09322dd 100644
--- a/libwmc/src/protocol.h
+++ b/libwmc/src/protocol.h
@@ -18,10 +18,13 @@
#ifndef LIBWMC_PROTOCOL_H
#define LIBWMC_PROTOCOL_H
+#define WMC_CMD_MARKER ((u_int8_t) 0xC8)
+
enum {
WMC_CMD_DEVICE_INFO = 0x06,
WMC_CMD_IP_INFO = 0x0A,
WMC_CMD_STATUS = 0x0B,
+ WMC_CMD_INIT = 0x0D,
WMC_CMD_EPS_BEARER_INFO = 0x4D,
};
@@ -33,6 +36,20 @@ struct WmcCmdHeader {
} __attribute__ ((packed));
typedef struct WmcCmdHeader WmcCmdHeader;
+/* Used on newer devices like the UML290 */
+struct WmcCmdInit2 {
+ WmcCmdHeader hdr;
+ u_int8_t _unknown1[14];
+} __attribute__ ((packed));
+typedef struct WmcCmdInit2 WmcCmdInit2;
+
+struct WmcCmdInit2Rsp {
+ WmcCmdHeader hdr;
+ u_int8_t _unknown1[4];
+} __attribute__ ((packed));
+typedef struct WmcCmdInit2Rsp WmcCmdInit2Rsp;
+
+
struct WmcCmdDeviceInfoRsp {
WmcCmdHeader hdr;
u_int8_t _unknown1[27];
diff --git a/libwmc/src/utils.c b/libwmc/src/utils.c
index 3c470330..ce3bb7af 100644
--- a/libwmc/src/utils.c
+++ b/libwmc/src/utils.c
@@ -236,7 +236,7 @@ hdlc_encapsulate_buffer (char *inbuf,
*
* Returns: size of the encapsulated data writted to @outbuf.
*/
-gsize
+static gsize
uml290_wmc_encapsulate (char *inbuf,
gsize cmd_len,
gsize inbuf_len,
@@ -251,7 +251,7 @@ uml290_wmc_encapsulate (char *inbuf,
g_return_val_if_fail (inbuf_len >= cmd_len + 2, 0); /* space for CRC */
g_return_val_if_fail (outbuf != NULL, 0);
- estimated_out_len = inbuf_len + strlen (AT_WMC_PREFIX);
+ estimated_out_len = cmd_len + strlen (AT_WMC_PREFIX);
estimated_out_len += 3; /* CRC + trailer */
estimated_out_len += cmd_len * 1.3; /* escaping */
g_return_val_if_fail (outbuf_len > estimated_out_len, 0);
@@ -271,6 +271,40 @@ uml290_wmc_encapsulate (char *inbuf,
}
/**
+ * wmc_encapsulate:
+ * @inbuf: data buffer to encapsulate
+ * @cmd_len: size of the data contained in @inbuf
+ * @inbuf_len: total size of @inbuf itself (not just the data)
+ * @outbuf: buffer in which to put the encapsulated data
+ * @outbuf_len: total size of @outbuf
+ * @uml290: if %TRUE return buffer suitable for sending to UML290 devices
+ *
+ * Escapes and CRCs given data using HDLC-style mechanisms.
+ *
+ * Returns: size of the encapsulated data writted to @outbuf.
+ */
+gsize
+wmc_encapsulate (char *inbuf,
+ gsize cmd_len,
+ gsize inbuf_len,
+ char *outbuf,
+ gsize outbuf_len,
+ gboolean uml290)
+{
+ g_return_val_if_fail (inbuf != NULL, 0);
+ g_return_val_if_fail (cmd_len >= 1, 0);
+ g_return_val_if_fail (inbuf_len >= cmd_len + 3, 0); /* space for CRC + trailer */
+ g_return_val_if_fail (outbuf != NULL, 0);
+
+ if (uml290)
+ return uml290_wmc_encapsulate (inbuf, cmd_len, inbuf_len, outbuf, outbuf_len);
+
+ /* Otherwise do normal WMC */
+ return hdlc_encapsulate_buffer (inbuf, cmd_len, inbuf_len,
+ 0, TRUE, FALSE, outbuf, outbuf_len);
+}
+
+/**
* hdlc_decapsulate_buffer:
* @inbuf: buffer in which to look for an HDLC frame
* @inbuf_len: length of valid data in @inbuf
@@ -382,3 +416,44 @@ hdlc_decapsulate_buffer (const char *inbuf,
return TRUE;
}
+/**
+ * wmc_decapsulate:
+ * @inbuf: buffer in which to look for an HDLC frame
+ * @inbuf_len: length of valid data in @inbuf
+ * @outbuf: buffer in which to put decapsulated data from the HDLC frame
+ * @outbuf_len: max size of @outbuf
+ * @out_decap_len: on success, size of the decapsulated data
+ * @out_used: on either success or failure, amount of data used; caller should
+ * discard this much data from @inbuf before the next call to this function
+ * @out_need_more: when TRUE, indicates that more data is required before
+ * a determination about a valid HDLC frame can be made; caller should add
+ * more data to @inbuf before calling this function again.
+ * @uml290: if %TRUE decapsulate response from UML290 devices
+ *
+ * Attempts to retrieve, unescape, and CRC-check an HDLC frame from the given
+ * buffer.
+ *
+ * Returns: FALSE on error (packet was invalid or malformed, or the CRC check
+ * failed, etc) and places number of bytes to discard from @inbuf in @out_used.
+ * When TRUE, either more data is required (in which case @out_need_more will
+ * be TRUE), or a data packet was successfully retrieved from @inbuf and the
+ * decapsulated packet of length @out_decap_len was placed into @outbuf. In
+ * all cases the caller should advance the buffer by the number of bytes
+ * returned in @out_used before calling this function again.
+ **/
+gboolean
+wmc_decapsulate (const char *inbuf,
+ gsize inbuf_len,
+ char *outbuf,
+ gsize outbuf_len,
+ gsize *out_decap_len,
+ gsize *out_used,
+ gboolean *out_need_more,
+ gboolean uml290)
+{
+ return hdlc_decapsulate_buffer (inbuf, inbuf_len,
+ uml290, uml290 ? 0x3030 : 0,
+ outbuf, outbuf_len,
+ out_decap_len, out_used, out_need_more);
+}
+
diff --git a/libwmc/src/utils.h b/libwmc/src/utils.h
index 4a7ab302..2163784e 100644
--- a/libwmc/src/utils.h
+++ b/libwmc/src/utils.h
@@ -23,6 +23,8 @@
#define DIAG_CONTROL_CHAR 0x7E
#define DIAG_TRAILER_LEN 3
+/* Utility and testcase functions */
+
guint16 crc16 (const char *buffer, gsize len, guint16 seed);
gsize hdlc_escape (const char *inbuf,
@@ -46,12 +48,6 @@ gsize hdlc_encapsulate_buffer (char *inbuf,
char *outbuf,
gsize outbuf_len);
-gsize uml290_wmc_encapsulate (char *inbuf,
- gsize cmd_len,
- gsize inbuf_len,
- char *outbuf,
- gsize outbuf_len);
-
gboolean hdlc_decapsulate_buffer (const char *inbuf,
gsize inbuf_len,
gboolean check_known_crc,
@@ -62,5 +58,23 @@ gboolean hdlc_decapsulate_buffer (const char *inbuf,
gsize *out_used,
gboolean *out_need_more);
+/* Functions for actual communication */
+
+gsize wmc_encapsulate (char *inbuf,
+ gsize cmd_len,
+ gsize inbuf_len,
+ char *outbuf,
+ gsize outbuf_len,
+ gboolean uml290);
+
+gboolean wmc_decapsulate (const char *inbuf,
+ gsize inbuf_len,
+ char *outbuf,
+ gsize outbuf_len,
+ gsize *out_decap_len,
+ gsize *out_used,
+ gboolean *out_need_more,
+ gboolean uml290);
+
#endif /* UTILS_H */