Commit 673cd458 authored by Richard Hughes's avatar Richard Hughes

Add a simple parser that can parse the output of the Beagle USB capture device

parent dc871953
.deps
.libs
gcm-parse-beagle
*.parsed
*.pdf
*.csv
*.o
SUBDIRS = \
huey \
api
INCLUDES = \
-I$(top_srcdir)/libcolor-glib \
-DI_KNOW_THE_LIBCOLOR_GLIB_API_IS_SUBJECT_TO_CHANGE \
-DGCM_I_KNOW_THIS_IS_PRIVATE \
$(GUDEV_CFLAGS) \
$(GTK_CFLAGS) \
$(GLIB_CFLAGS)
COLOR_GLIB_LIBS = \
$(top_builddir)/libcolor-glib/libcolor-glib.la
noinst_PROGRAMS = \
gcm-parse-beagle
gcm_parse_beagle_SOURCES = \
gcm-parse-beagle.c
gcm_parse_beagle_LDADD = \
$(COLOR_GLIB_LIBS) \
$(GLIB_LIBS)
gcm_parse_beagle_CFLAGS = \
$(WARNINGFLAGS_C)
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2010 Richard Hughes <richard@hughsie.com>
*
* Licensed under the GNU Lesser General Public License Version 2.1
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <glib.h>
#include <libcolor-glib.h>
#include "gcm-sensor-huey-private.h"
typedef enum {
GCM_PARSE_SECTION_LEVEL,
GCM_PARSE_SECTION_SP,
GCM_PARSE_SECTION_MS_US,
GCM_PARSE_SECTION_DUR,
GCM_PARSE_SECTION_LEN,
GCM_PARSE_SECTION_ERR,
GCM_PARSE_SECTION_DEV,
GCM_PARSE_SECTION_EP,
GCM_PARSE_SECTION_RECORD,
GCM_PARSE_SECTION_SUMMARY
} GcmParseSection;
typedef enum {
GCM_PARSE_ENTRY_DIRECTION_UNKNOWN,
GCM_PARSE_ENTRY_DIRECTION_REQUEST,
GCM_PARSE_ENTRY_DIRECTION_REPLY
} GcmParseEntryDirection;
typedef struct {
const gchar *record;
const gchar *summary;
const gchar *summary_pretty;
gint dev;
gint ep;
GcmParseEntryDirection direction;
} GcmParseEntry;
/**
* gcm_parse_beagle_process_entry_huey:
**/
static void
gcm_parse_beagle_process_entry_huey (GcmParseEntry *entry)
{
gchar **tok;
guint j;
guchar cmd;
guchar instruction = 0;
const gchar *command_as_text;
GString *output;
/* only know how to parse 8 bytes */
tok = g_strsplit (entry->summary, " ", -1);
if (g_strv_length (tok) != 8) {
g_print ("not 8 tokens: %s\n", entry->summary);
goto out;
}
output = g_string_new ("");
for (j=0; j<8; j++) {
command_as_text = NULL;
cmd = g_ascii_strtoll (tok[j], NULL, 16);
if (j == 0 && entry->direction == GCM_PARSE_ENTRY_DIRECTION_REPLY) {
command_as_text = gcm_sensor_huey_return_code_to_string (cmd);
if (command_as_text == NULL)
g_warning ("return code 0x%02x not known in %s", cmd, entry->summary);
}
if ((j == 0 && entry->direction == GCM_PARSE_ENTRY_DIRECTION_REQUEST) ||
(j == 1 && entry->direction == GCM_PARSE_ENTRY_DIRECTION_REPLY)) {
instruction = cmd;
command_as_text = gcm_sensor_huey_command_code_to_string (instruction);
if (command_as_text == NULL)
g_warning ("command code 0x%02x not known", cmd);
}
/* some requests are filled with junk data */
if (entry->direction == GCM_PARSE_ENTRY_DIRECTION_REQUEST &&
instruction == GCM_SENSOR_HUEY_COMMAND_REGISTER_READ && j > 1)
g_string_append_printf (output, "xx ");
else if (entry->direction == GCM_PARSE_ENTRY_DIRECTION_REQUEST &&
instruction == GCM_SENSOR_HUEY_COMMAND_SET_LEDS && j > 4)
g_string_append_printf (output, "xx ");
else if (entry->direction == GCM_PARSE_ENTRY_DIRECTION_REQUEST &&
instruction == GCM_SENSOR_HUEY_COMMAND_GET_AMBIENT && j > 3)
g_string_append_printf (output, "xx ");
else if (command_as_text != NULL)
g_string_append_printf (output, "%02x(%s) ", cmd, command_as_text);
else
g_string_append_printf (output, "%02x ", cmd);
}
/* remove trailing space */
if (output->len > 1)
g_string_set_size (output, output->len - 1);
out:
if (output != NULL)
entry->summary_pretty = g_string_free (output, FALSE);
g_strfreev (tok);
}
/**
* gcm_parse_beagle_process_entry:
**/
static gchar *
gcm_parse_beagle_process_entry (GcmSensorKind kind, GcmParseEntry *entry)
{
gchar *retval = NULL;
const gchar *direction = "??";
/* timeout */
if (g_strcmp0 (entry->record, "[250 IN-NAK]") == 0)
goto out;
/* device closed */
if (g_strcmp0 (entry->record, "[1 ORPHANED]") == 0)
goto out;
/* usb error */
if (g_strcmp0 (entry->record, "[53 SYNC ERRORS]") == 0)
goto out;
if (g_strcmp0 (entry->record, "[240 IN-NAK]") == 0)
goto out;
if (g_strcmp0 (entry->record, "Bus event") == 0)
goto out;
/* start or end of file */
if (g_str_has_prefix (entry->record, "Capture started"))
goto out;
if (g_strcmp0 (entry->record, "Capture stopped") == 0)
goto out;
/* get direction */
if (g_str_has_prefix (entry->record, "IN txn"))
entry->direction = GCM_PARSE_ENTRY_DIRECTION_REPLY;
else if (g_strcmp0 (entry->record, "Control Transfer") == 0)
entry->direction = GCM_PARSE_ENTRY_DIRECTION_REQUEST;
/* get correct string */
if (entry->direction == GCM_PARSE_ENTRY_DIRECTION_REQUEST)
direction = ">>";
else if (entry->direction == GCM_PARSE_ENTRY_DIRECTION_REPLY)
direction = "<<";
/* sexify the output */
if (kind == GCM_SENSOR_KIND_HUEY)
gcm_parse_beagle_process_entry_huey (entry);
retval = g_strdup_printf ("dev%02i ep%02i\t%s\t%s\n",
entry->dev, entry->ep, direction,
entry->summary_pretty != NULL ? entry->summary_pretty : entry->summary);
out:
return retval;
}
/**
* main:
**/
gint
main (gint argc, gchar *argv[])
{
gboolean ret;
gchar *data = NULL;
gchar **split = NULL;
gchar **sections = NULL;
GString *output = NULL;
GError *error = NULL;
guint i;
GcmParseEntry entry;
gchar *part;
gint retval = 1;
GcmSensorKind kind;
if (argc != 4) {
g_print ("need to specify [huey|colormunki] input output\n");
goto out;
}
kind = gcm_sensor_kind_from_string (argv[1]);
if (kind != GCM_SENSOR_KIND_HUEY &&
kind != GCM_SENSOR_KIND_COLOR_MUNKI) {
g_print ("only huey and colormunki device kinds supported\n");
goto out;
}
/* read file */
ret = g_file_get_contents (argv[2], &data, NULL, &error);
if (!ret) {
g_print ("failed to read: %s\n", error->message);
g_error_free (error);
goto out;
}
/* parse string */
output = g_string_new ("// automatically generated, do not edit\n");
/* parse string */
split = g_strsplit (data, "\n", -1);
for (i=0; split[i] != NULL; i++) {
/* comment or blank line */
if (split[i][0] == '#' ||
split[i][0] == '\0')
continue;
/* populate a GcmParseEntry */
sections = g_strsplit (split[i], ",", -1);
entry.record = sections[GCM_PARSE_SECTION_RECORD];
entry.summary = sections[GCM_PARSE_SECTION_SUMMARY];
entry.dev = atoi (sections[GCM_PARSE_SECTION_DEV]);
entry.ep = atoi (sections[GCM_PARSE_SECTION_EP]);
entry.direction = GCM_PARSE_ENTRY_DIRECTION_UNKNOWN;
entry.summary_pretty = NULL;
part = gcm_parse_beagle_process_entry (kind, &entry);
if (part != NULL) {
g_string_append (output, part);
// g_print ("%s\n", part);
}
g_free (part);
g_strfreev (sections);
}
/* write file */
ret = g_file_set_contents (argv[3], output->str, -1, &error);
if (!ret) {
g_print ("failed to read: %s\n", error->message);
g_error_free (error);
goto out;
}
g_print ("done!\n");
retval = 0;
out:
if (output != NULL)
g_string_free (output, TRUE);
g_free (data);
g_strfreev (split);
return retval;
}
......@@ -5,3 +5,5 @@ gcm-parse-huey
gcm-calculate-fudge
*.o
*.parsed
*.txt
*.gnumeric
INCLUDES = \
-I$(top_srcdir)/libcolor-glib \
-DI_KNOW_THE_LIBCOLOR_GLIB_API_IS_SUBJECT_TO_CHANGE \
-DGCM_I_KNOW_THIS_IS_PRIVATE \
$(GUDEV_CFLAGS) \
$(GTK_CFLAGS) \
$(GLIB_CFLAGS)
......@@ -27,6 +28,7 @@ gcm_parse_huey_SOURCES = \
gcm-parse-huey.c
gcm_parse_huey_LDADD = \
$(COLOR_GLIB_LIBS) \
$(GLIB_LIBS)
gcm_parse_huey_CFLAGS = \
......
......@@ -25,74 +25,7 @@
#include <glib.h>
#define HUEY_RETVAL_SUCCESS 0x00
#define HUEY_RETVAL_LOCKED 0xc0
#define HUEY_RETVAL_UNKNOWN_5A 0x5a /* seen in profiling */
#define HUEY_RETVAL_ERROR 0x80
#define HUEY_RETVAL_UNKNOWN_81 0x81 /* seen once in init */
#define HUEY_RETVAL_RETRY 0x90
static const gchar *
get_return_string (guchar value)
{
if (value == HUEY_RETVAL_SUCCESS)
return "success";
if (value == HUEY_RETVAL_LOCKED)
return "locked";
if (value == HUEY_RETVAL_ERROR)
return "error";
if (value == HUEY_RETVAL_RETRY)
return "retry";
if (value == HUEY_RETVAL_UNKNOWN_5A)
return "unknown5a";
if (value == HUEY_RETVAL_UNKNOWN_81)
return "unknown81";
return NULL;
}
static const gchar *
get_command_string (guchar value)
{
if (value == 0x00)
return "get-status";
if (value == 0x02)
return "read-green";
if (value == 0x03)
return "read-blue";
if (value == 0x05)
return "set-value";
if (value == 0x06)
return "get-value";
if (value == 0x07)
return "unknown07";
if (value == 0x08)
return "reg-read";
if (value == 0x0e)
return "unlock";
if (value == 0x0f)
return "unknown0f";
if (value == 0x10)
return "unknown10";
if (value == 0x11)
return "unknown11";
if (value == 0x12)
return "unknown12";
if (value == 0x13)
return "measure-rgb-crt";
if (value == 0x15)
return "unknown15(status?)";
if (value == 0x16)
return "measure-rgb";
if (value == 0x21)
return "unknown21";
if (value == 0x17)
return "ambient";
if (value == 0x18)
return "set-leds";
if (value == 0x19)
return "unknown19";
return NULL;
}
#include "gcm-sensor-huey-private.h"
static void
parse_command_sequence (GString *output, const gchar *line, gboolean reply)
......@@ -111,14 +44,14 @@ parse_command_sequence (GString *output, const gchar *line, gboolean reply)
command_as_text = NULL;
cmd = g_ascii_strtoll (tok[j], NULL, 16);
if (j == 0 && reply) {
command_as_text = get_return_string (cmd);
command_as_text = gcm_sensor_huey_return_code_to_string (cmd);
if (command_as_text == NULL)
g_warning ("return code 0x%02x not known in %s", cmd, line);
}
if ((j == 0 && !reply) ||
(j == 1 && reply)) {
instruction = cmd;
command_as_text = get_command_string (instruction);
command_as_text = gcm_sensor_huey_command_code_to_string (instruction);
if (command_as_text == NULL)
g_warning ("command code 0x%02x not known", cmd);
}
......
gnome-color-manager-*.omf
gnome-color-manager.xml
......@@ -67,6 +67,8 @@ libcolor_glib_la_SOURCES = \
gcm-sensor-client.h \
gcm-sensor-huey.c \
gcm-sensor-huey.h \
gcm-sensor-huey-private.c \
gcm-sensor-huey-private.h \
gcm-sensor-dummy.c \
gcm-sensor-dummy.h \
gcm-tables.c \
......
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2010 Richard Hughes <richard@hughsie.com>
*
* Licensed under the GNU Lesser General Public License Version 2.1
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* SECTION:gcm-sensor-huey-private
*/
#include "gcm-sensor-huey-private.h"
/**
* gcm_sensor_huey_return_code_to_string:
**/
const gchar *
gcm_sensor_huey_return_code_to_string (guchar value)
{
if (value == GCM_SENSOR_HUEY_RETURN_SUCCESS)
return "success";
if (value == GCM_SENSOR_HUEY_RETURN_LOCKED)
return "locked";
if (value == GCM_SENSOR_HUEY_RETURN_ERROR)
return "error";
if (value == GCM_SENSOR_HUEY_RETURN_RETRY)
return "retry";
if (value == GCM_SENSOR_HUEY_RETURN_UNKNOWN_5A)
return "unknown5a";
if (value == GCM_SENSOR_HUEY_RETURN_UNKNOWN_81)
return "unknown81";
return NULL;
}
/**
* gcm_sensor_huey_command_code_to_string:
**/
const gchar *
gcm_sensor_huey_command_code_to_string (guchar value)
{
if (value == GCM_SENSOR_HUEY_COMMAND_GET_STATUS)
return "get-status";
if (value == GCM_SENSOR_HUEY_COMMAND_READ_GREEN)
return "read-green";
if (value == GCM_SENSOR_HUEY_COMMAND_READ_BLUE)
return "read-blue";
if (value == GCM_SENSOR_HUEY_COMMAND_SET_VALUE)
return "set-value";
if (value == GCM_SENSOR_HUEY_COMMAND_GET_VALUE)
return "get-value";
if (value == GCM_SENSOR_HUEY_COMMAND_UNKNOWN_07)
return "unknown07";
if (value == GCM_SENSOR_HUEY_COMMAND_REGISTER_READ)
return "reg-read";
if (value == GCM_SENSOR_HUEY_COMMAND_UNLOCK)
return "unlock";
if (value == GCM_SENSOR_HUEY_COMMAND_UNKNOWN_0F)
return "unknown0f";
if (value == GCM_SENSOR_HUEY_COMMAND_UNKNOWN_10)
return "unknown10";
if (value == GCM_SENSOR_HUEY_COMMAND_UNKNOWN_11)
return "unknown11";
if (value == GCM_SENSOR_HUEY_COMMAND_UNKNOWN_12)
return "unknown12";
if (value == GCM_SENSOR_HUEY_COMMAND_SENSOR_MEASURE_RGB_CRT)
return "measure-rgb-crt";
if (value == GCM_SENSOR_HUEY_COMMAND_UNKNOWN_15)
return "unknown15(status?)";
if (value == GCM_SENSOR_HUEY_COMMAND_SENSOR_MEASURE_RGB)
return "measure-rgb";
if (value == GCM_SENSOR_HUEY_COMMAND_UNKNOWN_21)
return "unknown21";
if (value == GCM_SENSOR_HUEY_COMMAND_GET_AMBIENT)
return "ambient";
if (value == GCM_SENSOR_HUEY_COMMAND_SET_LEDS)
return "set-leds";
if (value == GCM_SENSOR_HUEY_COMMAND_UNKNOWN_19)
return "unknown19";
return NULL;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2010 Richard Hughes <richard@hughsie.com>
*
* Licensed under the GNU Lesser General Public License Version 2.1
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if !defined (LIBCOLOR_GLIB_COMPILATION) && !defined (GCM_I_KNOW_THIS_IS_PRIVATE)
#error "This header file is for internal use only."
#endif
#ifndef __GCM_SENSOR_HUEY_PRIVATE_H
#define __GCM_SENSOR_HUEY_PRIVATE_H
#include <glib.h>
G_BEGIN_DECLS
#define GCM_SENSOR_HUEY_VENDOR_ID 0x0971
#define GCM_SENSOR_HUEY_PRODUCT_ID 0x2005
/* Return values from the commands */
#define GCM_SENSOR_HUEY_RETURN_SUCCESS 0x00
#define GCM_SENSOR_HUEY_RETURN_LOCKED 0xc0
#define GCM_SENSOR_HUEY_RETURN_UNKNOWN_5A 0x5a /* seen in profiling */
#define GCM_SENSOR_HUEY_RETURN_ERROR 0x80
#define GCM_SENSOR_HUEY_RETURN_UNKNOWN_81 0x81 /* seen once in init */
#define GCM_SENSOR_HUEY_RETURN_RETRY 0x90
/*
* Get the currect status of the device
*
* input: 00 00 00 00 3f 00 00 00
* returns: 00 00 43 69 72 30 30 31 (or)
* "Cir001" --^^^^^^^^^^^^^^^^^ -- Circuit1?...
* c0 00 4c 6f 63 6b 65 64
* "locked" --^^^^^^^^^^^^^^^^^
*/
#define GCM_SENSOR_HUEY_COMMAND_GET_STATUS 0x00
/*
* Read the green sample data
*
* input: 02 xx xx xx xx xx xx xx
* returns: 00 02 00 00 0a 00 00 00 (or)
* 00 02 00 0e c6 80 00 00
* data --^^^^^ ^-- only ever 00 or 80
* |
* \-- for RGB(00,00,00) is 09 f2
* RGB(ff,ff,ff) is 00 00
* RGB(ff,00,00) is 02 a5
* RGB(00,ff,00) is 00 f1
* RGB(00,00,ff) is 08 56
*
* This doesn't do a sensor read, it seems to be a simple accessor.
* GCM_SENSOR_HUEY_COMMAND_SENSOR_MEASURE_RGB has to be used before this one.
*/
#define GCM_SENSOR_HUEY_COMMAND_READ_GREEN 0x02
/*
* Read the blue sample data
*
* input: 03 xx xx xx xx xx xx xx
* returns: 00 03 00 0f 18 00 00 00
* data --^^^^^ ^-- only ever 00 or 80
* |
* \-- for RGB(00,00,00) is 09 64
* RGB(ff,ff,ff) is 08 80
* RGB(ff,00,00) is 03 22
* RGB(00,ff,00) is 00 58
* RGB(00,00,ff) is 00 59
*
* This doesn't do a sensor read, it seems to be a simple accessor.
* GCM_SENSOR_HUEY_COMMAND_SENSOR_MEASURE_RGB has to be used before this one.
*/
#define GCM_SENSOR_HUEY_COMMAND_READ_BLUE 0x03
/*
* Set value of some 32 bit register.
*
* input: 05 ?? 11 12 13 14 xx xx
* returns: 00 05 00 00 00 00 00 00
* ^--- always the same no matter the input
*
* This is never used in profiling
*/
#define GCM_SENSOR_HUEY_COMMAND_SET_VALUE 0x05
/*
* Get the value of some 32 bit register.
*
* input: 06 xx xx xx xx xx xx xx