Blame sscape_ctl/sscape_ctl.c

Packit 427e91
/*
Packit 427e91
 * ALSA SoundScape control utility
Packit 427e91
 *
Packit 427e91
 * Copyright (c) 2003 by Chris Rankin
Packit 427e91
 *
Packit 427e91
 *   This program is free software; you can redistribute it and/or modify
Packit 427e91
 *   it under the terms of the GNU General Public License as published by
Packit 427e91
 *   the Free Software Foundation; either version 2 of the License, or
Packit 427e91
 *   (at your option) any later version.
Packit 427e91
 *
Packit 427e91
 *   This program is distributed in the hope that it will be useful,
Packit 427e91
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 427e91
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 427e91
 *   GNU General Public License for more details.
Packit 427e91
 *
Packit 427e91
 *   You should have received a copy of the GNU General Public License
Packit 427e91
 *   along with this program; if not, write to the Free Software
Packit 427e91
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit 427e91
 */
Packit 427e91
Packit 427e91
#include <stdio.h>
Packit 427e91
#include <stdlib.h>
Packit 427e91
#include <string.h>
Packit 427e91
Packit 427e91
#include <errno.h>
Packit 427e91
#include <fcntl.h>
Packit 427e91
#include <unistd.h>
Packit 427e91
#include <getopt.h>
Packit 427e91
#include <sys/ioctl.h>
Packit 427e91
Packit 427e91
#include <alsa/sound/sscape_ioctl.h>
Packit 427e91
#include <alsa/asoundlib.h>
Packit 427e91
Packit 427e91
Packit 427e91
const char default_dir[] = "/sndscape";
Packit 427e91
const char scope[] = "scope.cod";
Packit 427e91
unsigned char _microcode[SSCAPE_MICROCODE_SIZE];
Packit 427e91
Packit 427e91
static void
Packit 427e91
show_usage(void)
Packit 427e91
{
Packit 427e91
  printf("sscape_ctl: [--card card number]\n"
Packit 427e91
         "            [--directory firmware directory]\n"
Packit 427e91
         "sscape_ctl: --help\n"
Packit 427e91
         "sscape_ctl: --version\n");
Packit 427e91
}
Packit 427e91
Packit 427e91
Packit 427e91
static void
Packit 427e91
show_version(void)
Packit 427e91
{
Packit 427e91
  printf("ALSA SoundScape control utility: v" VERSION "\n");
Packit 427e91
}
Packit 427e91
Packit 427e91
Packit 427e91
void
Packit 427e91
safe_close(int fd)
Packit 427e91
{
Packit 427e91
  int err;
Packit 427e91
  while (((err = close(fd)) != 0) && (errno == EINTR)) {}
Packit 427e91
}
Packit 427e91
Packit 427e91
size_t
Packit 427e91
get_directory(const char *dir, char *buffer, size_t bufsize)
Packit 427e91
{
Packit 427e91
  size_t len;
Packit 427e91
Packit 427e91
  len = snprintf(buffer, bufsize, "%s/", dir);
Packit 427e91
  if (len >= bufsize)
Packit 427e91
    return 0;
Packit 427e91
Packit 427e91
  if ((len > 1) && (buffer[len - 1] == '/') && (buffer[len - 2] == '/'))
Packit 427e91
  {
Packit 427e91
    buffer[--len] = '\0';
Packit 427e91
  }
Packit 427e91
Packit 427e91
  return len;
Packit 427e91
}
Packit 427e91
Packit 427e91
Packit 427e91
size_t
Packit 427e91
get_bootfile(const char *filename, char *buffer, size_t bufsize)
Packit 427e91
{
Packit 427e91
  size_t len = snprintf(buffer, bufsize, "%s", filename);
Packit 427e91
  if (len >= bufsize)
Packit 427e91
    return 0;
Packit 427e91
  return len;
Packit 427e91
}
Packit 427e91
Packit 427e91
Packit 427e91
size_t
Packit 427e91
get_mcodefile(unsigned version, char *buffer, size_t bufsize)
Packit 427e91
{
Packit 427e91
  static const char sndscape[] = "sndscape.co%u";
Packit 427e91
Packit 427e91
  size_t len = snprintf(buffer, bufsize, sndscape, version);
Packit 427e91
  if (len >= bufsize)
Packit 427e91
    return 0;
Packit 427e91
  return len;
Packit 427e91
}
Packit 427e91
Packit 427e91
Packit 427e91
int
Packit 427e91
load_bootblock(const char *fname, struct sscape_bootblock *boot)
Packit 427e91
{
Packit 427e91
  int err;
Packit 427e91
  int fd;
Packit 427e91
Packit 427e91
  printf("Bootblock: %s\n", fname);
Packit 427e91
Packit 427e91
  err = fd = open(fname, O_RDONLY);
Packit 427e91
  if (err >= 0)
Packit 427e91
  {
Packit 427e91
    int save_errno;
Packit 427e91
Packit 427e91
    err = read(fd, boot->code, sizeof(boot->code));
Packit 427e91
    if (err >= 0)
Packit 427e91
    {
Packit 427e91
      printf("Bootblock: read %d bytes\n", err);
Packit 427e91
      err = 0;
Packit 427e91
    }
Packit 427e91
Packit 427e91
    save_errno = errno;
Packit 427e91
    safe_close(fd);
Packit 427e91
    errno = save_errno;
Packit 427e91
  }
Packit 427e91
Packit 427e91
  return err;
Packit 427e91
}
Packit 427e91
Packit 427e91
Packit 427e91
int
Packit 427e91
load_microcode(const char *fname, struct sscape_microcode *microcode)
Packit 427e91
{
Packit 427e91
  int err;
Packit 427e91
  int fd;
Packit 427e91
Packit 427e91
  printf("Microcode: %s\n", fname);
Packit 427e91
Packit 427e91
  err = fd = open(fname, O_RDONLY);
Packit 427e91
  if (err >= 0)
Packit 427e91
  {
Packit 427e91
    int save_errno;
Packit 427e91
Packit 427e91
    err = read(fd, microcode->code, sizeof(_microcode));
Packit 427e91
    if (err >= 0)
Packit 427e91
    {
Packit 427e91
      printf("Microcode: read %d bytes\n", err);
Packit 427e91
      err = 0;
Packit 427e91
    }
Packit 427e91
Packit 427e91
    save_errno = errno;
Packit 427e91
    safe_close(fd);
Packit 427e91
    errno = save_errno;
Packit 427e91
  }
Packit 427e91
Packit 427e91
  return err;
Packit 427e91
}
Packit 427e91
Packit 427e91
Packit 427e91
static const struct option long_option[] = {
Packit 427e91
  { "card", 1, NULL, 'c' },
Packit 427e91
  { "directory", 1, NULL, 'd' },
Packit 427e91
  { "help", 0, NULL, 'h' },
Packit 427e91
  { "version", 0, NULL, 'v' },
Packit 427e91
  { NULL, 0, NULL, '\0' }
Packit 427e91
};
Packit 427e91
Packit 427e91
static const char option[] = "c:d:hv";
Packit 427e91
Packit 427e91
int
Packit 427e91
main(int argc, char *argv[])
Packit 427e91
{
Packit 427e91
  char devicename[32];
Packit 427e91
  int ret, err;
Packit 427e91
  snd_hwdep_t *handle;
Packit 427e91
Packit 427e91
  const char *directory = default_dir;
Packit 427e91
  int card = 0;
Packit 427e91
Packit 427e91
  int oindex;
Packit 427e91
  int c;
Packit 427e91
Packit 427e91
  while ( (c = getopt_long(argc, argv, option, long_option, &oindex)) != EOF )
Packit 427e91
  {
Packit 427e91
    switch(c)
Packit 427e91
    {
Packit 427e91
    case 'c':
Packit 427e91
      card = snd_card_get_index(optarg);
Packit 427e91
      if (card < 0 || card > 31) {
Packit 427e91
        fprintf(stderr, "Wrong -c argument '%s'\n", optarg);
Packit 427e91
        return EXIT_FAILURE;
Packit 427e91
      }
Packit 427e91
      break;
Packit 427e91
Packit 427e91
    case 'd':
Packit 427e91
      directory = optarg;
Packit 427e91
      break;
Packit 427e91
Packit 427e91
    case 'h':
Packit 427e91
      show_usage();
Packit 427e91
      return EXIT_SUCCESS;
Packit 427e91
Packit 427e91
    case 'v':
Packit 427e91
      show_version();
Packit 427e91
      return EXIT_SUCCESS;
Packit 427e91
Packit 427e91
    default:
Packit 427e91
      return EXIT_FAILURE;
Packit 427e91
    } /* switch */
Packit 427e91
  } /* while */
Packit 427e91
Packit 427e91
  ret = EXIT_FAILURE;
Packit 427e91
  snprintf(devicename, sizeof(devicename), "hw:%i,0", card);
Packit 427e91
  err = snd_hwdep_open(&handle, devicename, O_WRONLY);
Packit 427e91
  if (err < 0)
Packit 427e91
  {
Packit 427e91
    fprintf(stderr, "Error opening %s: %s\n", devicename, snd_strerror(err)); 
Packit 427e91
  }
Packit 427e91
  else
Packit 427e91
  {
Packit 427e91
    char filename[FILENAME_MAX];
Packit 427e91
    size_t len;
Packit 427e91
Packit 427e91
    struct sscape_bootblock  boot;
Packit 427e91
    struct sscape_microcode  microcode;
Packit 427e91
Packit 427e91
    microcode.code = _microcode;
Packit 427e91
    if ((len = get_directory(directory, filename, sizeof(filename))) == 0)
Packit 427e91
    {
Packit 427e91
      fprintf(stderr, "Invalid directory - pathname too long\n");
Packit 427e91
    }
Packit 427e91
    else if (get_bootfile(scope, filename + len, sizeof(filename) - len) == 0)
Packit 427e91
    {
Packit 427e91
      fprintf(stderr, "Invalid filename - full pathname too long\n");
Packit 427e91
    }
Packit 427e91
    else if (load_bootblock(filename, &boot) < 0)
Packit 427e91
    {
Packit 427e91
      fprintf(stderr, "Failed to load file [%s]: %s\n",
Packit 427e91
                      filename, strerror(errno));
Packit 427e91
    }
Packit 427e91
    else if (snd_hwdep_ioctl(handle, SND_SSCAPE_LOAD_BOOTB, &boot) < 0)
Packit 427e91
    {
Packit 427e91
      fprintf(stderr, "IOCTL error: %s\n", strerror(errno));
Packit 427e91
    }
Packit 427e91
    else if (get_mcodefile(boot.version & 0x0f,
Packit 427e91
                           filename + len, sizeof(filename) - len) == 0)
Packit 427e91
    {
Packit 427e91
      fprintf(stderr, "Invalid filename - full pathname too long\n"); 
Packit 427e91
    }
Packit 427e91
    else if (load_microcode(filename, &microcode) < 0)
Packit 427e91
    {
Packit 427e91
      fprintf(stderr, "Failed to load microcode [%s]\n", filename);
Packit 427e91
    }
Packit 427e91
    else if (snd_hwdep_ioctl(handle, SND_SSCAPE_LOAD_MCODE, &microcode) < 0)
Packit 427e91
    {
Packit 427e91
      fprintf(stderr, "IOCTL error: %s\n", strerror(errno));
Packit 427e91
    }
Packit 427e91
    else
Packit 427e91
    {
Packit 427e91
      printf("Microcode loaded.\n");
Packit 427e91
      ret = EXIT_SUCCESS;
Packit 427e91
    }
Packit 427e91
    snd_hwdep_close(handle);
Packit 427e91
  }
Packit 427e91
Packit 427e91
  return ret;
Packit 427e91
}
Packit 427e91