00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <glib.h>
00024 #include "config.h"
00025 #include "sigrok.h"
00026 #include "sigrok-internal.h"
00027
00028 struct context {
00029 unsigned int num_enabled_probes;
00030 unsigned int unitsize;
00031 char *probelist[SR_MAX_NUM_PROBES + 1];
00032 uint64_t samplerate;
00033 GString *header;
00034 char separator;
00035 };
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 static int init(struct sr_output *o)
00050 {
00051 struct context *ctx;
00052 struct sr_probe *probe;
00053 GSList *l;
00054 int num_probes;
00055 uint64_t samplerate;
00056 time_t t;
00057 unsigned int i;
00058
00059 if (!o) {
00060 sr_err("csv out: %s: o was NULL", __func__);
00061 return SR_ERR_ARG;
00062 }
00063
00064 if (!o->dev) {
00065 sr_err("csv out: %s: o->dev was NULL", __func__);
00066 return SR_ERR_ARG;
00067 }
00068
00069 if (!o->dev->driver) {
00070 sr_err("csv out: %s: o->dev->driver was NULL", __func__);
00071 return SR_ERR_ARG;
00072 }
00073
00074 if (!(ctx = g_try_malloc0(sizeof(struct context)))) {
00075 sr_err("csv out: %s: ctx malloc failed", __func__);
00076 return SR_ERR_MALLOC;
00077 }
00078
00079 o->internal = ctx;
00080
00081
00082
00083 for (l = o->dev->probes; l; l = l->next) {
00084 probe = l->data;
00085 if (!probe->enabled)
00086 continue;
00087 ctx->probelist[ctx->num_enabled_probes++] = probe->name;
00088 }
00089 ctx->probelist[ctx->num_enabled_probes] = 0;
00090 ctx->unitsize = (ctx->num_enabled_probes + 7) / 8;
00091
00092 num_probes = g_slist_length(o->dev->probes);
00093
00094 if (sr_dev_has_hwcap(o->dev, SR_HWCAP_SAMPLERATE)) {
00095 samplerate = *((uint64_t *) o->dev->driver->dev_info_get(
00096 o->dev->driver_index, SR_DI_CUR_SAMPLERATE));
00097
00098 } else {
00099 samplerate = 0;
00100 }
00101 ctx->samplerate = samplerate;
00102
00103 ctx->separator = ',';
00104
00105 ctx->header = g_string_sized_new(512);
00106
00107 t = time(NULL);
00108
00109
00110 g_string_append_printf(ctx->header, "; CSV, generated by %s on %s",
00111 PACKAGE_STRING, ctime(&t));
00112 g_string_append_printf(ctx->header, "; Samplerate: %"PRIu64"\n",
00113 ctx->samplerate);
00114
00115
00116 g_string_append_printf(ctx->header, "; Channels (%d/%d): ",
00117 ctx->num_enabled_probes, num_probes);
00118 for (i = 0; i < ctx->num_enabled_probes; i++)
00119 g_string_append_printf(ctx->header, "%s, ", ctx->probelist[i]);
00120 g_string_append_printf(ctx->header, "\n");
00121
00122 return 0;
00123 }
00124
00125 static int event(struct sr_output *o, int event_type, uint8_t **data_out,
00126 uint64_t *length_out)
00127 {
00128 struct context *ctx;
00129
00130 if (!o) {
00131 sr_err("csv out: %s: o was NULL", __func__);
00132 return SR_ERR_ARG;
00133 }
00134
00135 if (!(ctx = o->internal)) {
00136 sr_err("csv out: %s: o->internal was NULL", __func__);
00137 return SR_ERR_ARG;
00138 }
00139
00140 if (!data_out) {
00141 sr_err("csv out: %s: data_out was NULL", __func__);
00142 return SR_ERR_ARG;
00143 }
00144
00145 switch (event_type) {
00146 case SR_DF_TRIGGER:
00147 sr_dbg("csv out: %s: SR_DF_TRIGGER event", __func__);
00148
00149 *data_out = NULL;
00150 *length_out = 0;
00151 break;
00152 case SR_DF_END:
00153 sr_dbg("csv out: %s: SR_DF_END event", __func__);
00154
00155 *data_out = NULL;
00156 *length_out = 0;
00157 g_free(o->internal);
00158 o->internal = NULL;
00159 break;
00160 default:
00161 sr_err("csv out: %s: unsupported event type: %d", __func__,
00162 event_type);
00163 *data_out = NULL;
00164 *length_out = 0;
00165 break;
00166 }
00167
00168 return SR_OK;
00169 }
00170
00171 static int data(struct sr_output *o, const uint8_t *data_in,
00172 uint64_t length_in, uint8_t **data_out, uint64_t *length_out)
00173 {
00174 struct context *ctx;
00175 GString *outstr;
00176 uint64_t sample, i;
00177 int j;
00178
00179 if (!o) {
00180 sr_err("csv out: %s: o was NULL", __func__);
00181 return SR_ERR_ARG;
00182 }
00183
00184 if (!(ctx = o->internal)) {
00185 sr_err("csv out: %s: o->internal was NULL", __func__);
00186 return SR_ERR_ARG;
00187 }
00188
00189 if (!data_in) {
00190 sr_err("csv out: %s: data_in was NULL", __func__);
00191 return SR_ERR_ARG;
00192 }
00193
00194 if (ctx->header) {
00195
00196 outstr = ctx->header;
00197 ctx->header = NULL;
00198 } else {
00199 outstr = g_string_sized_new(512);
00200 }
00201
00202 for (i = 0; i <= length_in - ctx->unitsize; i += ctx->unitsize) {
00203 memcpy(&sample, data_in + i, ctx->unitsize);
00204 for (j = ctx->num_enabled_probes - 1; j >= 0; j--) {
00205 g_string_append_printf(outstr, "%d%c",
00206 (int)((sample & (1 << j)) >> j),
00207 ctx->separator);
00208 }
00209 g_string_append_printf(outstr, "\n");
00210 }
00211
00212 *data_out = (uint8_t *)outstr->str;
00213 *length_out = outstr->len;
00214 g_string_free(outstr, FALSE);
00215
00216 return SR_OK;
00217 }
00218
00219 SR_PRIV struct sr_output_format output_csv = {
00220 .id = "csv",
00221 .description = "Comma-separated values (CSV)",
00222 .df_type = SR_DF_LOGIC,
00223 .init = init,
00224 .data = data,
00225 .event = event,
00226 };