diff options
-rw-r--r-- | libwmc/src/Makefile.am | 6 | ||||
-rw-r--r-- | libwmc/src/commands.c | 109 | ||||
-rw-r--r-- | libwmc/src/commands.h | 41 | ||||
-rw-r--r-- | libwmc/src/errors.h | 6 | ||||
-rw-r--r-- | libwmc/src/protocol.h | 52 | ||||
-rw-r--r-- | libwmc/src/result-private.h | 38 | ||||
-rw-r--r-- | libwmc/src/result.c | 298 | ||||
-rw-r--r-- | libwmc/src/result.h | 42 |
8 files changed, 590 insertions, 2 deletions
diff --git a/libwmc/src/Makefile.am b/libwmc/src/Makefile.am index 1a376e36..9d264e30 100644 --- a/libwmc/src/Makefile.am +++ b/libwmc/src/Makefile.am @@ -9,8 +9,12 @@ libwmc_la_SOURCES = \ errors.h \ utils.c \ utils.h \ + result.c \ + result.h \ com.c \ - com.h + com.h \ + commands.c \ + commands.h libwmc_la_LIBADD = \ $(MM_LIBS) diff --git a/libwmc/src/commands.c b/libwmc/src/commands.c new file mode 100644 index 00000000..08bfd4da --- /dev/null +++ b/libwmc/src/commands.c @@ -0,0 +1,109 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <string.h> + +#include "commands.h" +#include "errors.h" +#include "result-private.h" +#include "utils.h" +#include "protocol.h" + + +/**********************************************************************/ + +static int +check_command (const char *buf, gsize len, guint8 cmd, gsize 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]); + return -WMC_ERROR_RESPONSE_UNEXPECTED; + } + + if (len < min_len) { + wmc_err (0, "WMC command %d response not long enough (got %zu, expected " + "at least %zu).", cmd, len, min_len); + return -WMC_ERROR_RESPONSE_BAD_LENGTH; + } + + return 0; +} + +/**********************************************************************/ + +size_t +wmc_cmd_device_info_new (char *buf, size_t buflen) +{ + WmcCmdHeader *cmd = (WmcCmdHeader *) buf; + + wmc_return_val_if_fail (buf != NULL, 0); + wmc_return_val_if_fail (buflen >= sizeof (*cmd), 0); + + memset (cmd, 0, sizeof (*cmd)); + cmd->cmd = WMC_CMD_DEVICE_INFO; + return sizeof (*cmd); +} + +WmcResult * +wmc_cmd_device_info_result (const char *buf, gsize buflen) +{ + WmcResult *r = NULL; + WmcCmdDeviceInfoRsp *rsp = (WmcCmdDeviceInfoRsp *) buf; + char tmp[65]; + + g_return_val_if_fail (buf != NULL, NULL); + + if (check_command (buf, buflen, WMC_CMD_DEVICE_INFO, sizeof (WmcCmdDeviceInfoRsp)) < 0) + return NULL; + + r = wmc_result_new (); + + /* Manf */ + memset (tmp, 0, sizeof (tmp)); + g_assert (sizeof (rsp->manf) <= sizeof (tmp)); + memcpy (tmp, rsp->manf, sizeof (rsp->manf)); + wmc_result_add_string (r, WMC_CMD_DEVICE_INFO_ITEM_MANUFACTURER, tmp); + + /* Model */ + memset (tmp, 0, sizeof (tmp)); + g_assert (sizeof (rsp->model) <= sizeof (tmp)); + memcpy (tmp, rsp->model, sizeof (rsp->model)); + wmc_result_add_string (r, WMC_CMD_DEVICE_INFO_ITEM_MODEL, tmp); + + /* Firmware revision */ + memset (tmp, 0, sizeof (tmp)); + g_assert (sizeof (rsp->fwrev) <= sizeof (tmp)); + memcpy (tmp, rsp->fwrev, sizeof (rsp->fwrev)); + wmc_result_add_string (r, WMC_CMD_DEVICE_INFO_ITEM_FW_REVISION, tmp); + + /* Hardware revision */ + memset (tmp, 0, sizeof (tmp)); + g_assert (sizeof (rsp->hwrev) <= sizeof (tmp)); + memcpy (tmp, rsp->hwrev, sizeof (rsp->hwrev)); + wmc_result_add_string (r, WMC_CMD_DEVICE_INFO_ITEM_HW_REVISION, tmp); + + return r; +} + +/**********************************************************************/ + diff --git a/libwmc/src/commands.h b/libwmc/src/commands.h new file mode 100644 index 00000000..dba839b5 --- /dev/null +++ b/libwmc/src/commands.h @@ -0,0 +1,41 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef LIBWMC_COMMANDS_H +#define LIBWMC_COMMANDS_H + +#include "result.h" + +/**********************************************************************/ + +/* Generic enums */ + + +/**********************************************************************/ + +#define WMC_CMD_DEVICE_INFO_ITEM_MANUFACTURER "manufacturer" +#define WMC_CMD_DEVICE_INFO_ITEM_MODEL "model" +#define WMC_CMD_DEVICE_INFO_ITEM_FW_REVISION "firmware-revision" +#define WMC_CMD_DEVICE_INFO_ITEM_HW_REVISION "hardware-revision" + +size_t wmc_cmd_device_info_new (char *buf, size_t buflen); + +WmcResult * wmc_cmd_device_info_result (const char *buf, size_t len); + +/**********************************************************************/ + +#endif /* LIBWMC_COMMANDS_H */ diff --git a/libwmc/src/errors.h b/libwmc/src/errors.h index f9346df9..5ad22c1a 100644 --- a/libwmc/src/errors.h +++ b/libwmc/src/errors.h @@ -33,7 +33,11 @@ enum { enum { WMC_SUCCESS = 0, - WMC_ERROR_SERIAL_CONFIG_FAILED = 1, + WMC_ERROR_INVALID_ARGUMENTS = 1, + WMC_ERROR_SERIAL_CONFIG_FAILED = 2, + WMC_ERROR_VALUE_NOT_FOUND = 3, + WMC_ERROR_RESPONSE_UNEXPECTED = 4, + WMC_ERROR_RESPONSE_BAD_LENGTH = 5, }; #define wmc_assert assert diff --git a/libwmc/src/protocol.h b/libwmc/src/protocol.h new file mode 100644 index 00000000..7bc751ee --- /dev/null +++ b/libwmc/src/protocol.h @@ -0,0 +1,52 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef LIBWMC_PROTOCOL_H +#define LIBWMC_PROTOCOL_H + +enum { + WMC_CMD_DEVICE_INFO = 0x06, + WMC_CMD_IP_INFO = 0x0A, + WMC_CMD_STATUS = 0x0B, + WMC_CMD_EPS_BEARER_INFO = 0x4D, +}; + + +/* Generic WMC command header */ +struct WmcCmdHeader { + u_int8_t marker; /* Always 0xC8 */ + u_int8_t cmd; +} __attribute__ ((packed)); +typedef struct WmcCmdHeader WmcCmdHeader; + +struct WmcCmdDeviceInfoRsp { + WmcCmdHeader hdr; + u_int8_t _unknown1[27]; + char manf[64]; + char model[64]; + char fwrev[64]; + char hwrev[64]; + u_int8_t _unknown2[64]; + u_int8_t _unknown3[64]; + u_int8_t _unknown4[22]; + u_int8_t _unknown5[8]; + u_int8_t _unknown6[6]; +} __attribute__ ((packed)); +typedef struct WmcCmdDeviceInfoRsp WmcCmdDeviceInfoRsp; + + +#endif /* LIBWMC_PROTOCOL_H */ diff --git a/libwmc/src/result-private.h b/libwmc/src/result-private.h new file mode 100644 index 00000000..32a3fcb3 --- /dev/null +++ b/libwmc/src/result-private.h @@ -0,0 +1,38 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2011 Red Hat, Inc. + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef LIBWMC_RESULT_PRIVATE_H +#define LIBWMC_RESULT_PRIVATE_H + +#include "result.h" + +WmcResult *wmc_result_new (void); + +void wmc_result_add_string (WmcResult *result, + const char *key, + const char *str); + +void wmc_result_add_u8 (WmcResult *result, + const char *key, + u_int8_t num); + +void wmc_result_add_u32 (WmcResult *result, + const char *key, + u_int32_t num); + +#endif /* LIBWMC_RESULT_PRIVATE_H */ + diff --git a/libwmc/src/result.c b/libwmc/src/result.c new file mode 100644 index 00000000..936716f0 --- /dev/null +++ b/libwmc/src/result.c @@ -0,0 +1,298 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2010 Red Hat, Inc. + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <string.h> +#include <stdlib.h> + +#include "result.h" +#include "result-private.h" +#include "errors.h" + +/*********************************************************/ + +typedef struct Val Val; + +typedef enum { + VAL_TYPE_NONE = 0, + VAL_TYPE_STRING = 1, + VAL_TYPE_U8 = 2, + VAL_TYPE_U32 = 3 +} ValType; + +struct Val { + char *key; + ValType type; + union { + char *s; + u_int8_t u8; + u_int32_t u32; + } u; + Val *next; +}; + +static void +val_free (Val *v) +{ + if (v->type == VAL_TYPE_STRING) { + if (v->u.s) + free (v->u.s); + } + free (v->key); + memset (v, 0, sizeof (*v)); + free (v); +} + +static Val * +val_new_string (const char *key, const char *value) +{ + Val *v; + + wmc_return_val_if_fail (key != NULL, NULL); + wmc_return_val_if_fail (key[0] != '\0', NULL); + wmc_return_val_if_fail (value != NULL, NULL); + + v = calloc (sizeof (Val), 1); + if (v == NULL) + return NULL; + + v->key = strdup (key); + v->type = VAL_TYPE_STRING; + v->u.s = strdup (value); + return v; +} + +static Val * +val_new_u8 (const char *key, u_int8_t u) +{ + Val *v; + + wmc_return_val_if_fail (key != NULL, NULL); + wmc_return_val_if_fail (key[0] != '\0', NULL); + + v = calloc (sizeof (Val), 1); + if (v == NULL) + return NULL; + + v->key = strdup (key); + v->type = VAL_TYPE_U8; + v->u.u8 = u; + return v; +} + +static Val * +val_new_u32 (const char *key, u_int32_t u) +{ + Val *v; + + wmc_return_val_if_fail (key != NULL, NULL); + wmc_return_val_if_fail (key[0] != '\0', NULL); + + v = calloc (sizeof (Val), 1); + if (v == NULL) + return NULL; + + v->key = strdup (key); + v->type = VAL_TYPE_U8; + v->u.u32 = u; + return v; +} + +/*********************************************************/ + +struct WmcResult { + u_int32_t refcount; + Val *first; +}; + +WmcResult * +wmc_result_new (void) +{ + WmcResult *r; + + r = calloc (sizeof (WmcResult), 1); + if (r) + r->refcount = 1; + return r; +} + +WmcResult * +wmc_result_ref (WmcResult *r) +{ + wmc_return_val_if_fail (r != NULL, NULL); + wmc_return_val_if_fail (r->refcount > 0, NULL); + + r->refcount++; + return r; +} + +static void +wmc_result_free (WmcResult *r) +{ + Val *v, *n; + + v = r->first; + while (v) { + n = v->next; + val_free (v); + v = n; + } + memset (r, 0, sizeof (*r)); + free (r); +} + +void +wmc_result_unref (WmcResult *r) +{ + wmc_return_if_fail (r != NULL); + wmc_return_if_fail (r->refcount > 0); + + r->refcount--; + if (r->refcount == 0) + wmc_result_free (r); +} + +static Val * +find_val (WmcResult *r, const char *key, ValType expected_type) +{ + Val *v, *n; + + v = r->first; + while (v) { + n = v->next; + if (strcmp (v->key, key) == 0) { + /* Check type */ + wmc_return_val_if_fail (v->type == expected_type, NULL); + return v; + } + v = n; + } + return NULL; +} + +void +wmc_result_add_string (WmcResult *r, + const char *key, + const char *str) +{ + Val *v; + + wmc_return_if_fail (r != NULL); + wmc_return_if_fail (r->refcount > 0); + wmc_return_if_fail (key != NULL); + wmc_return_if_fail (str != NULL); + + v = val_new_string (key, str); + wmc_return_if_fail (v != NULL); + v->next = r->first; + r->first = v; +} + +int +wmc_result_get_string (WmcResult *r, + const char *key, + const char **out_val) +{ + Val *v; + + wmc_return_val_if_fail (r != NULL, -WMC_ERROR_INVALID_ARGUMENTS); + wmc_return_val_if_fail (r->refcount > 0, -WMC_ERROR_INVALID_ARGUMENTS); + wmc_return_val_if_fail (key != NULL, -WMC_ERROR_INVALID_ARGUMENTS); + wmc_return_val_if_fail (out_val != NULL, -WMC_ERROR_INVALID_ARGUMENTS); + wmc_return_val_if_fail (*out_val == NULL, -WMC_ERROR_INVALID_ARGUMENTS); + + v = find_val (r, key, VAL_TYPE_STRING); + if (v == NULL) + return -WMC_ERROR_VALUE_NOT_FOUND; + + *out_val = v->u.s; + return 0; +} + +void +wmc_result_add_u8 (WmcResult *r, + const char *key, + u_int8_t num) +{ + Val *v; + + wmc_return_if_fail (r != NULL); + wmc_return_if_fail (r->refcount > 0); + wmc_return_if_fail (key != NULL); + + v = val_new_u8 (key, num); + wmc_return_if_fail (v != NULL); + v->next = r->first; + r->first = v; +} + +int +wmc_result_get_u8 (WmcResult *r, + const char *key, + u_int8_t *out_val) +{ + Val *v; + + wmc_return_val_if_fail (r != NULL, -WMC_ERROR_INVALID_ARGUMENTS); + wmc_return_val_if_fail (r->refcount > 0, -WMC_ERROR_INVALID_ARGUMENTS); + wmc_return_val_if_fail (key != NULL, -WMC_ERROR_INVALID_ARGUMENTS); + wmc_return_val_if_fail (out_val != NULL, -WMC_ERROR_INVALID_ARGUMENTS); + + v = find_val (r, key, VAL_TYPE_U8); + if (v == NULL) + return -WMC_ERROR_VALUE_NOT_FOUND; + + *out_val = v->u.u8; + return 0; +} + +void +wmc_result_add_u32 (WmcResult *r, + const char *key, + u_int32_t num) +{ + Val *v; + + wmc_return_if_fail (r != NULL); + wmc_return_if_fail (r->refcount > 0); + wmc_return_if_fail (key != NULL); + + v = val_new_u32 (key, num); + wmc_return_if_fail (v != NULL); + v->next = r->first; + r->first = v; +} + +int +wmc_result_get_u32 (WmcResult *r, + const char *key, + u_int32_t *out_val) +{ + Val *v; + + wmc_return_val_if_fail (r != NULL, -WMC_ERROR_INVALID_ARGUMENTS); + wmc_return_val_if_fail (r->refcount > 0, -WMC_ERROR_INVALID_ARGUMENTS); + wmc_return_val_if_fail (key != NULL, -WMC_ERROR_INVALID_ARGUMENTS); + wmc_return_val_if_fail (out_val != NULL, -WMC_ERROR_INVALID_ARGUMENTS); + + v = find_val (r, key, VAL_TYPE_U32); + if (v == NULL) + return -WMC_ERROR_VALUE_NOT_FOUND; + + *out_val = v->u.u32; + return 0; +} + diff --git a/libwmc/src/result.h b/libwmc/src/result.h new file mode 100644 index 00000000..516f0ba7 --- /dev/null +++ b/libwmc/src/result.h @@ -0,0 +1,42 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2010 Red Hat, Inc. + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef LIBWMC_RESULT_H +#define LIBWMC_RESULT_H + +#include <sys/types.h> + +typedef struct WmcResult WmcResult; + +int wmc_result_get_string (WmcResult *r, + const char *key, + const char **out_val); + +int wmc_result_get_u8 (WmcResult *r, + const char *key, + u_int8_t *out_val); + +int wmc_result_get_u32 (WmcResult *r, + const char *key, + u_int32_t *out_val); + +WmcResult *wmc_result_ref (WmcResult *r); + +void wmc_result_unref (WmcResult *r); + +#endif /* LIBWMC_RESULT_H */ + |