comedi.c 4.33 KB
Newer Older
Anders Blomdell's avatar
Anders Blomdell committed
1
#include <moberg_config.h>
Anders Blomdell's avatar
Anders Blomdell committed
2
3
#include <moberg_parser.h>
#include <moberg_module.h>
Anders Blomdell's avatar
Anders Blomdell committed
4
#include <moberg_device.h>
5
#include <stdio.h>
Anders Blomdell's avatar
Anders Blomdell committed
6
7
8
#include <stdlib.h>
#include <string.h>

Anders Blomdell's avatar
Anders Blomdell committed
9
10
11
12
typedef enum moberg_parser_token_kind kind_t;
typedef struct moberg_parser_token token_t;
typedef struct moberg_parser_ident ident_t;
typedef struct moberg_parser_context context_t;
Anders Blomdell's avatar
Anders Blomdell committed
13

Anders Blomdell's avatar
Anders Blomdell committed
14
15
16
17
18
struct moberg_device_map {};
struct moberg_device_config {
  char *device;
};

Anders Blomdell's avatar
Anders Blomdell committed
19
20
21
22
static inline int acceptsym(context_t *c,
			   kind_t kind,
			   token_t *token)
{
Anders Blomdell's avatar
Anders Blomdell committed
23
  return moberg_parser_acceptsym(c, kind, token);
Anders Blomdell's avatar
Anders Blomdell committed
24
25
26
27
28
}
  
static inline int acceptkeyword(context_t *c,
				const char *keyword)
{
Anders Blomdell's avatar
Anders Blomdell committed
29
  return moberg_parser_acceptkeyword(c, keyword);
Anders Blomdell's avatar
Anders Blomdell committed
30
31
}
  
Anders Blomdell's avatar
Anders Blomdell committed
32
33
static int parse_config(
  struct moberg_device *device,
Anders Blomdell's avatar
Anders Blomdell committed
34
  struct moberg_parser_context *c)
35
{
Anders Blomdell's avatar
Anders Blomdell committed
36
37
38
  struct moberg_device_config *config = malloc(sizeof *config);
  if (! config) {
    fprintf(stderr, "Failed to allocate moberg device config\n");
39
40
41
    goto err;
  }
  if (! acceptsym(c, tok_LBRACE, NULL)) { goto syntax_err; }
Anders Blomdell's avatar
Anders Blomdell committed
42
  for (;;) {
Anders Blomdell's avatar
Anders Blomdell committed
43
44
    if (acceptsym(c, tok_RBRACE, NULL)) {
	break;
Anders Blomdell's avatar
Anders Blomdell committed
45
46
    } else if (acceptkeyword(c, "device")) {
      token_t device;
47
48
49
      if (! acceptsym(c, tok_EQUAL, NULL)) { goto syntax_err; }
      if (! acceptsym(c, tok_STRING, &device)) { goto syntax_err; }
      if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto syntax_err; }
Anders Blomdell's avatar
Anders Blomdell committed
50
      config->device = strndup(device.u.string.value, device.u.string.length);
Anders Blomdell's avatar
Anders Blomdell committed
51
    } else if (acceptkeyword(c, "config")) {
52
53
      if (! acceptsym(c, tok_EQUAL, NULL)) { goto syntax_err; }
      if (! acceptsym(c, tok_LBRACKET, NULL)) { goto syntax_err; }
Anders Blomdell's avatar
Anders Blomdell committed
54
55
56
57
58
59
      for (;;) {
	if (acceptsym(c, tok_RBRACKET, NULL)) {
	  break;
	} else if (acceptsym(c, tok_IDENT, NULL) ||
		   acceptsym(c, tok_STRING, NULL)) {
	} else {
60
	  goto syntax_err;
Anders Blomdell's avatar
Anders Blomdell committed
61
	}
Anders Blomdell's avatar
Anders Blomdell committed
62
      }
63
      if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto syntax_err; }
Anders Blomdell's avatar
Anders Blomdell committed
64
    } else if (acceptkeyword(c, "modprobe")) {
65
66
      if (! acceptsym(c, tok_EQUAL, NULL)) { goto syntax_err; }
      if (! acceptsym(c, tok_LBRACKET, NULL)) { goto syntax_err; }
Anders Blomdell's avatar
Anders Blomdell committed
67
      for (;;) {
Anders Blomdell's avatar
Anders Blomdell committed
68
69
70
71
72
	if (acceptsym(c, tok_RBRACKET, NULL)) {
	  break;
	} else if (acceptsym(c, tok_IDENT, NULL) ||
		   acceptsym(c, tok_STRING, NULL)) {
	} else {
73
	  goto syntax_err;
Anders Blomdell's avatar
Anders Blomdell committed
74
	}
Anders Blomdell's avatar
Anders Blomdell committed
75
      }
76
      if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto syntax_err; }
Anders Blomdell's avatar
Anders Blomdell committed
77
    } else {
78
      goto syntax_err;
Anders Blomdell's avatar
Anders Blomdell committed
79
    }
80
  }
Anders Blomdell's avatar
Anders Blomdell committed
81
82
  moberg_device_set_config(device, config);
  return 1;
83
syntax_err:
Anders Blomdell's avatar
Anders Blomdell committed
84
  moberg_parser_failed(c, stderr);
Anders Blomdell's avatar
Anders Blomdell committed
85
  free(config);
86
err:
Anders Blomdell's avatar
Anders Blomdell committed
87
  return 0;
88
89
}

Anders Blomdell's avatar
Anders Blomdell committed
90
91
static int parse_map(
  struct moberg_device *device,
Anders Blomdell's avatar
Anders Blomdell committed
92
  struct moberg_parser_context *c,
Anders Blomdell's avatar
Anders Blomdell committed
93
  enum moberg_device_map_kind kind)
94
{
Anders Blomdell's avatar
Anders Blomdell committed
95
  token_t min, max;
96

97
98
99
100
101
102
103
104
105
106
107
108
  if (! acceptsym(c, tok_LBRACE, NULL)) { goto err; }
  for (;;) {
    token_t subdevice;
    if (! acceptkeyword(c, "subdevice") != 0) {  goto err; }
    if (! acceptsym(c, tok_LBRACKET, NULL)) { goto err; }
    if (! acceptsym(c, tok_INTEGER, &subdevice)) { goto err; }
    if (! acceptsym(c, tok_RBRACKET, NULL)) { goto err; }
    if (acceptkeyword(c, "route")) {
      token_t route;
      if (! acceptsym(c, tok_INTEGER, &route)) { goto err; }
    }
    if (! acceptsym(c, tok_LBRACKET, NULL)) { goto err; }
Anders Blomdell's avatar
Anders Blomdell committed
109
    if (! acceptsym(c, tok_INTEGER, &min)) { goto err; }
110
    if (acceptsym(c, tok_COLON, NULL)) { 
Anders Blomdell's avatar
Anders Blomdell committed
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
      if (! acceptsym(c, tok_INTEGER, &max)) { goto err; }
    } else {
      max = min;
    }
    for (int i = min.u.integer.value ; i <= max.u.integer.value ; i++) {
      switch (kind) {
        case map_analog_in:
          moberg_device_add_analog_in(device, NULL);
          break;
        case map_analog_out:
          moberg_device_add_analog_out(device, NULL);
          break;
        case map_digital_in:
          moberg_device_add_digital_in(device, NULL);
          break;
        case map_digital_out:
          moberg_device_add_digital_out(device, NULL);
          break;
        case map_encoder_in:
          moberg_device_add_encoder_in(device, NULL);
          break;
      }
133
134
135
    }
    if (! acceptsym(c, tok_RBRACKET, NULL)) { goto err; }
    if (! acceptsym(c, tok_COMMA, NULL)) { break; }
Anders Blomdell's avatar
Anders Blomdell committed
136
    
137
  }
138
  if (! acceptsym(c, tok_RBRACE, NULL)) { goto err; }
Anders Blomdell's avatar
Anders Blomdell committed
139
  return 1;
Anders Blomdell's avatar
Anders Blomdell committed
140
err:
Anders Blomdell's avatar
Anders Blomdell committed
141
  moberg_parser_failed(c, stderr);
Anders Blomdell's avatar
Anders Blomdell committed
142
143
144
145
146
147
148
  return 0;
}

static int config_free(struct moberg_device_config *config)
{
  free(config->device);
  return 1;
149
150
}

Anders Blomdell's avatar
Anders Blomdell committed
151
struct moberg_device_driver moberg_device_driver = {
152
153
  .parse_config = parse_config,
  .parse_map = parse_map,
Anders Blomdell's avatar
Anders Blomdell committed
154
  .config_free = config_free
155
};