aboutsummaryrefslogtreecommitdiffstats
path: root/src/avirt-config.c
blob: d2b1d5e7ebc8f15299336f982bf479416a7a5d71 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
 * AVIRT User-space library
 * 
 * avirt-config.c - Main AVIRT configuration via configfs
 *
 * Copyright (C) 2018 Fiberdyne Systems Pty Ltd
 *
 * This program 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 2 of the License, or
 * (at your option) any later version.
 *
 * 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/>.
 */

#define _GNU_SOURCE

#include <avirt/avirt.h>

#include <stdbool.h>
#include <stdio.h>
#include <alsa/asoundlib.h>
#include <sys/stat.h>
#include <sys/mount.h>

#define AVIRT_CONFIGFS_PATH_STREAMS "/config/avirt/streams/"
#define AVIRT_CONFIGFS_PATH_MAXLEN 64

#define AVIRT_ERROR(errmsg) \
  fprintf(stderr, "AVIRT ERROR: %s\n", errmsg);

#define AVIRT_ERROR_V(errmsg, ...)                       \
  do {                                                   \
      char *errmsg_done;                                 \
      asprintf(&errmsg_done, errmsg, ##__VA_ARGS__);     \
      fprintf(stderr, "AVIRT ERROR: %s\n", errmsg_done); \
      free(errmsg_done);                                 \
  } while (0)

#define AVIRT_DEBUG_ON
#ifdef AVIRT_DEBUG_ON
# define AVIRT_DEBUG(debugmsg) \
  fprintf(stderr, "AVIRT DEBUG: %s\n", debugmsg);

# define AVIRT_DEBUG_V(debugmsg, ...)                                      \
  do {                                                                     \
      char *debugmsg_done;                                                 \
      asprintf(&debugmsg_done, debugmsg, ##__VA_ARGS__);                   \
      fprintf(stderr, "[%s]: AVIRT DEBUG: %s\n", __func__, debugmsg_done); \
      free(debugmsg_done);                                                 \
  } while (0)
#endif

static bool configfs_mounted = false;

static int mount_configfs()
{
  int err;

  err = mount("none", "/config", "configfs", 0, NULL);
  if (!err)
    configfs_mounted = true;
  else
    AVIRT_ERROR("Failed to mount configfs filesystem!");

  return err;
}

int AVIRT_CreateStream(const char *name, unsigned int channels, int direction)
{
  int err;
  char path[AVIRT_CONFIGFS_PATH_MAXLEN];
  char path_chans[AVIRT_CONFIGFS_PATH_MAXLEN];
  FILE *fd;

  if (!configfs_mounted) {
    err = mount_configfs();
    if (err < 0)
      return err;
  }

  strcpy(path, AVIRT_CONFIGFS_PATH_STREAMS);
  switch (direction) {
    case SND_PCM_STREAM_PLAYBACK:
      strcat(path, "playback_");
      break;
    case SND_PCM_STREAM_CAPTURE:
      strcat(path, "capture_");
      break;
    default:
      return -EINVAL;
  }

  if ((AVIRT_CONFIGFS_PATH_MAXLEN - strlen(path)) < strlen(name))
  {
    AVIRT_ERROR_V("Cannot create stream '%s' since name is too long!", name);
    return -ENOMEM;
  }

  strcat(path, name);
  err = mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
  if (err < 0)
  {
    AVIRT_ERROR_V("Cannot create stream '%s' at directory '%s'", name, path);
    return err;
  }

  strcpy(path_chans, path);
  strcat(path_chans, "/channels");
  fd = fopen(path_chans, "w");
  if (!fd)
  {
    AVIRT_ERROR_V("Failed to open file at '%s'", path_chans);
    return -1;
  }

  fprintf(fd, "%d", channels);
  fclose(fd);

  return 0;
}

int AVIRT_SealCard()
{
  int err;
  char path_sealed[AVIRT_CONFIGFS_PATH_MAXLEN];
  FILE *fd;

  if (!configfs_mounted) {
    err = mount_configfs();
    if (err < 0)
      return err;
  }

  strcpy(path_sealed, AVIRT_CONFIGFS_PATH_STREAMS);
  strcat(path_sealed, "/sealed");
  fd = fopen(path_sealed, "w");
  if (!fd)
  {
    AVIRT_ERROR_V("Failed to open file at '%s'", path_sealed);
    return -1;
  }

  fprintf(fd, "%d", 1);
  fclose(fd);
}