labcomm2006_encoder.c 5.05 KB
Newer Older
1
/*
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
2
  labcomm2006_encoder.c -- handling encoding of labcomm samples.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

  Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>

  This file is part of LabComm.

  LabComm is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  LabComm 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 <errno.h>
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
22
23
24
25
26
27
28
29
30
#include "labcomm2006.h"
#include "labcomm2006_private.h"
#include "labcomm2006_ioctl.h"

struct labcomm2006_encoder {
  struct labcomm2006_writer *writer;
  struct labcomm2006_error_handler *error;
  struct labcomm2006_memory *memory;
  struct labcomm2006_scheduler *scheduler;
31
32
33
  LABCOMM_SIGNATURE_ARRAY_DEF(registered, int);
};

Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
34
35
36
37
38
struct labcomm2006_encoder *labcomm2006_encoder_new(
  struct labcomm2006_writer *writer,
  struct labcomm2006_error_handler *error,
  struct labcomm2006_memory *memory,
  struct labcomm2006_scheduler *scheduler)
39
{
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
40
  struct labcomm2006_encoder *result;
41

Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
42
  result = labcomm2006_memory_alloc(memory, 0, sizeof(*result));
43
44
45
46
47
48
49
50
51
52
53
54
  if (result) {
    result->writer = writer;
    result->writer->encoder = result;
    result->writer->data = NULL;
    result->writer->data_size = 0;
    result->writer->count = 0;
    result->writer->pos = 0;
    result->writer->error = 0;
    result->error = error;
    result->memory = memory;
    result->scheduler = scheduler;
    LABCOMM_SIGNATURE_ARRAY_INIT(result->registered, int);
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
55
    labcomm2006_writer_alloc(result->writer,
56
			 result->writer->action_context);
57
58
59
60
  }
  return result;
}

Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
61
void labcomm2006_encoder_free(struct labcomm2006_encoder* e)
62
{
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
63
  struct labcomm2006_memory *memory = e->memory;
64

Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
65
  labcomm2006_writer_free(e->writer, e->writer->action_context);
66
  LABCOMM_SIGNATURE_ARRAY_FREE(e->memory, e->registered, int);
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
67
  labcomm2006_memory_free(memory, 0, e);
68
69
}

Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
70
71
int labcomm2006_internal_encoder_register(
  struct labcomm2006_encoder *e,
Anders Blomdell's avatar
Anders Blomdell committed
72
  const struct labcomm2006_signature *signature,
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
73
  labcomm2006_encoder_function encode)
74
75
76
77
{
  int result = -EINVAL;
  int index, *done, err, i;

Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
78
79
  index = labcomm2006_get_local_index(signature);
  labcomm2006_scheduler_writer_lock(e->scheduler);
80
81
82
83
  if (index <= 0) { goto out; }
  done = LABCOMM_SIGNATURE_ARRAY_REF(e->memory, e->registered, int, index);
  if (*done) { goto out; }
  *done = 1;	
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
84
  err = labcomm2006_writer_start(e->writer, e->writer->action_context, 
85
86
87
			     index, signature, NULL);
  if (err == -EALREADY) { result = 0; goto out; }
  if (err != 0) { result = err; goto out; }
Anders Blomdell's avatar
Anders Blomdell committed
88
  labcomm2006_write_packed32(e->writer, LABCOMM_SAMPLE);
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
89
90
  labcomm2006_write_packed32(e->writer, index);
  labcomm2006_write_string(e->writer, signature->name);
91
92
  for (i = 0 ; i < signature->size ; i++) {
    if (e->writer->pos >= e->writer->count) {
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
93
      labcomm2006_writer_flush(e->writer, e->writer->action_context);
94
95
96
97
    }
    e->writer->data[e->writer->pos] = signature->signature[i];
    e->writer->pos++;
  }
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
98
  labcomm2006_writer_end(e->writer, e->writer->action_context);
99
100
  result = e->writer->error;
out:
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
101
  labcomm2006_scheduler_writer_unlock(e->scheduler);
102
103
104
  return result;
}

Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
105
106
int labcomm2006_internal_encode(
  struct labcomm2006_encoder *e,
Anders Blomdell's avatar
Anders Blomdell committed
107
  const struct labcomm2006_signature *signature,
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
108
  labcomm2006_encoder_function encode,
109
110
111
112
113
  void *value)
{
  int result;
  int index;

Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
114
115
116
  index = labcomm2006_get_local_index(signature);
  labcomm2006_scheduler_writer_lock(e->scheduler);
  result = labcomm2006_writer_start(e->writer, e->writer->action_context, 
117
118
119
				index, signature, value);
  if (result == -EALREADY) { result = 0; goto no_end; }
  if (result != 0) { goto out; }
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
120
  result = labcomm2006_write_packed32(e->writer, index);
121
122
123
  if (result != 0) { goto out; }
  result = encode(e->writer, value);
out:
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
124
  labcomm2006_writer_end(e->writer, e->writer->action_context);
125
no_end:
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
126
  labcomm2006_scheduler_writer_unlock(e->scheduler);
127
128
129
  return result;
}

Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
130
int labcomm2006_encoder_ioctl(struct labcomm2006_encoder *encoder, 
131
132
133
134
135
136
137
138
139
140
141
142
			  uint32_t action,
			  ...)
{
  int result;
  va_list va;
  
  if (LABCOMM_IOC_SIG(action) != LABCOMM_IOC_NOSIG) {
    result = -EINVAL;
    goto out;
  }
  
  va_start(va, action);
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
143
  result = labcomm2006_writer_ioctl(encoder->writer, 
144
145
146
147
148
149
150
151
			       encoder->writer->action_context,
			       0, NULL, action, va);
  va_end(va);

out:
  return result;
}

Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
152
int labcomm2006_internal_encoder_ioctl(struct labcomm2006_encoder *encoder, 
Anders Blomdell's avatar
Anders Blomdell committed
153
154
                                       const struct labcomm2006_signature *signature,
                                       uint32_t action, va_list va)
155
156
157
158
{
  int result = -ENOTSUP;
  int index;

Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
159
160
  index = labcomm2006_get_local_index(signature);
  result = labcomm2006_writer_ioctl(encoder->writer, 
161
162
163
164
				encoder->writer->action_context, 
				index, signature, action, va);
  return result;
}