Logo Search packages:      
Sourcecode: baycomusb version File versions  Download package

win32client.c

/*****************************************************************************/

/*
 *      win32client.c  --  Transceiver control client (Win32 shmem only).
 *
 *      Copyright (C) 2000, 2001
 *          Thomas Sailer (t.sailer@alumni.ethz.ch)
 *
 *      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, write to the Free Software
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Please note that the GPL allows you to use the driver, NOT the radio.
 *  In order to use the radio, you need a license from the communications
 *  authority of your country.
 *
 *  History:
 *   0.1  19.09.2000  Created
 *
 */

/*****************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "trxapi.h"

#include <sys/types.h>
#include <stdio.h>

#if defined(WIN32)
#include <windows.h>
#else
#include <dirent.h>
#endif

#include "win32client.h"
#include "trx.h"

/* --------------------------------------------------------------------- */

#define VERBOSE

#ifdef VERBOSE
#define verbose(x) x
#else
#define verbose(x)
#endif

/* --------------------------------------------------------------------- */

/* --------------------------------------------------------------------- */

#if defined(WIN32)

#if 0
static int start_service(void)
{
        int ret = -1;
        SC_HANDLE hscm, hserv;
        DWORD err;
        char *args[5] = { "-S", "-v", "9", "-s", "-ORBBindAddr=127.0.0.1" };
        
        hscm = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
        if (!hscm) {
                err = GetLastError();
                if (err != ERROR_CALL_NOT_IMPLEMENTED)
                        lprintf(0, "Cannot open SC manager, error %lu\n", err);
                return -1;
        }
        hserv = OpenService(hscm, SERVICENAME, SERVICE_ALL_ACCESS);
        if (!hserv) {
                err = GetLastError();
                lprintf(0, "Cannot open service, error %lu\n", err);
                goto closescm;
        }
        if (!StartService(hserv, 5, args)) {
                err = GetLastError();
                if (err != ERROR_SERVICE_ALREADY_RUNNING)
                        lprintf(0, "Cannot start service, error %lu\n", err);
                goto closeserv;
        }
        lprintf(0, "Service %s started successfully\n", SERVICENAME);
        ret = 0;

  closeserv:
        if (!CloseServiceHandle(hserv))
                lprintf(0, "Cannot close service handle, error %lu\n", GetLastError());
  closescm:
        if (!CloseServiceHandle(hscm))
                lprintf(0, "Cannot close service manager handle, error %lu\n", GetLastError());
        return ret;
}
#endif

#if 0
static void print_shmem(void)
{
      unsigned int i;
      HANDLE hshmem, hglobalshmem, hprocess;
      struct win32_global_state *globalstate;
      struct trx_thread_state *state;

      hglobalshmem = OpenFileMapping(FILE_MAP_READ, FALSE, "baycomusb");
      if (!hglobalshmem) {
            lprintf(0, "Cannot open baycomusb file mapping (error %lu)\n", GetLastError());
            return;
      }
      globalstate = MapViewOfFile(hglobalshmem, FILE_MAP_READ, 0, 0, 0);
      CloseHandle(hglobalshmem);
      if (!globalstate) {
            lprintf(0, "Cannot map shared memory segment (error %lu)\n", GetLastError());
            return;
      }
      if (strncmp(globalstate->signature, BAYUSBSIGNATURE, sizeof(globalstate->signature))) {
            lprintf(0, "Shared Memory Segment has invalid Signature %16s\n", globalstate->signature);
            goto err1;
      }
      hprocess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, globalstate->processid);
      if (!hprocess) {
            lprintf(0, "Cannot open server process %u (error %lu)\n", 
                  globalstate->processid, GetLastError());
            goto err1;
      }
      printf("Modems:\n");
      for (i = 0; i < MAXUSBMODEMS; i++) {
            if (!globalstate->modem[i].hshmem)
                  continue;
            if (!DuplicateHandle(hprocess, globalstate->modem[i].hshmem,
                             GetCurrentProcess(), &hshmem,
                             FILE_MAP_WRITE, FALSE, 0)) {
                  lprintf(0, "Cannot duplicate handle (error %lu)\n", GetLastError());
                  continue;
            }
            state = MapViewOfFile(hshmem, FILE_MAP_READ, 0, 0, 0);
            CloseHandle(hshmem);
            if (!state) {
                  lprintf(0, "Cannot map shared memory segment (error %lu)\n", GetLastError());
                  continue;
            }
            printf("dev %2u:  mode %u, serial %s\n", i, state->mode, state->serial);


            UnmapViewOfFile(state);
      }

  err2:
      CloseHandle(hprocess);
  err1:
      UnmapViewOfFile(globalstate);
}
/* MUTEX_ALL_ACCESS, EVENT_ALL_ACCESS, EVENT_MODIFY_STATE */
#endif

#if 0
void win32shmem_runserver(void)
{
        char windir[512], name[512], cmdname[512], cmdline[512], *cp;
        STARTUPINFO sti;
        PROCESS_INFORMATION pi;
      HANDLE hglobalshmem;

      hglobalshmem = OpenFileMapping(FILE_MAP_READ, FALSE, "baycomusb");
      if (hglobalshmem) {
            CloseHandle(hglobalshmem);
            return;
      }
      if (!GetWindowsDirectory(windir, sizeof(windir))) {
                lprintf(0, "Cannot get windows directory path\n");
                return;
        }
        if (!GetModuleFileName(GetModuleHandle(NULL), name, sizeof(name))) {
                lprintf(0, "Cannot determine executable name\n");
                return;
        }
        if ((cp = strrchr(name, '\\')))
                *cp = 0;
        else
                name[0] = 0;
        snprintf(cmdname, sizeof(cmdname), "%s\\rundll32.exe", windir);
      /*
       * Database calls (getXbyY) seem to hang for a very looooong time under
       * w9x if DNS is not or misconfigured. So we set the binding address to
       * 127.0.0.1, which only accepts connections from 127.0.0.1
       * and does no database calls
       */
        snprintf(cmdline, sizeof(cmdline), "%s %s\\bayusb.dll,server_entry_cmdline -v 9 -s" /*" -ORBBindAddr=127.0.0.1"*/, cmdname, name);
        GetStartupInfo(&sti);
        if (!CreateProcess(cmdname, cmdline, NULL, NULL, FALSE,
                           DETACHED_PROCESS | CREATE_DEFAULT_ERROR_MODE | HIGH_PRIORITY_CLASS,
                           NULL, NULL, &sti, &pi)) {
                lprintf(0, "Cannot start command %s, Error %lu\n", cmdname, GetLastError());
        } else
            Sleep(2000);
}
#else
void win32shmem_runserver(void)
{
        char name[512], cmdname[512], cmdline[512], *cp;
        STARTUPINFO sti;
        PROCESS_INFORMATION pi;
      HANDLE hglobalshmem;

      hglobalshmem = OpenFileMapping(FILE_MAP_READ, FALSE, "baycomusb");
      if (hglobalshmem) {
            CloseHandle(hglobalshmem);
            return;
      }
        if (!GetModuleFileName(GetModuleHandle(NULL), name, sizeof(name))) {
                lprintf(0, "Cannot determine executable name\n");
                return;
        }
        if ((cp = strrchr(name, '\\')))
                *cp = 0;
        else
                name[0] = 0;
        snprintf(cmdname, sizeof(cmdname), "%s\\baycomusbserv.exe", name);
      /*
       * Database calls (getXbyY) seem to hang for a very looooong time under
       * w9x if DNS is not or misconfigured. So we set the binding address to
       * 127.0.0.1, which only accepts connections from 127.0.0.1
       * and does no database calls
       */
        snprintf(cmdline, sizeof(cmdline), "%s -v 9 -s" /*" -ORBBindAddr=127.0.0.1"*/, cmdname);
        GetStartupInfo(&sti);
        if (!CreateProcess(cmdname, cmdline, NULL, NULL, FALSE,
                           DETACHED_PROCESS | CREATE_DEFAULT_ERROR_MODE | HIGH_PRIORITY_CLASS,
                           NULL, NULL, &sti, &pi)) {
                lprintf(0, "Cannot start command %s, Error %lu\n", cmdname, GetLastError());
        } else
            Sleep(2000);
}
#endif


#endif

/* --------------------------------------------------------------------- */

struct trxapi *win32shmem_open_byindex(unsigned int index)
{
      struct trxapi_description *d;
      struct trxapi *api;
      unsigned int i;
      HANDLE hshmem, hglobalshmem, hprocess, hmutex, hflxtxevent, hflxrxevent;
      struct win32_global_state *globalstate;
      struct trx_thread_state *state;
      static int audioglobalinit = 1;

      win32shmem_runserver();
      /* kludge!! */
      if (audioglobalinit) {
        audioglobalinit = 0;
        audio_globalinit();
      }
      hglobalshmem = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "baycomusb");
      if (!hglobalshmem) {
            verbose(lprintf(1, "Cannot open baycomusb file mapping (error %lu)\n", GetLastError()));
            return NULL;
      }
      globalstate = MapViewOfFile(hglobalshmem, FILE_MAP_ALL_ACCESS, 0, 0, 0);
      CloseHandle(hglobalshmem);
      if (!globalstate) {
            verbose(lprintf(1, "Cannot map shared memory segment (error %lu)\n", GetLastError()));
            return NULL;
      }
      if (strncmp(globalstate->signature, BAYUSBSIGNATURE, sizeof(globalstate->signature))) {
            verbose(lprintf(1, "Shared Memory Segment has invalid Signature %16s\n", globalstate->signature));
            goto err1;
      }
      hprocess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, globalstate->processid);
      if (!hprocess) {
            verbose(lprintf(1, "Cannot open server process %u (error %lu)\n", 
                  globalstate->processid, GetLastError()));
            goto err1;
      }
      for (i = 0; i < MAXUSBMODEMS; i++) {
            if (!globalstate->modem[i].hshmem)
                  continue;
            if (index) {
                  index--;
                  continue;
            }
            if (!DuplicateHandle(hprocess, globalstate->modem[i].hshmem,
                             GetCurrentProcess(), &hshmem,
                             FILE_MAP_ALL_ACCESS, FALSE, 0)) {
                  verbose(lprintf(1, "Cannot duplicate shmem handle (error %lu)\n", GetLastError()));
                  continue;
            }
            state = MapViewOfFile(hshmem, FILE_MAP_ALL_ACCESS, 0, 0, 0);
            CloseHandle(hshmem);
            if (!state) {
                  verbose(lprintf(1, "Cannot map shared memory segment (error %lu)\n", GetLastError()));
                  continue;
            }
            if (!DuplicateHandle(hprocess, state->hmutex,
                             GetCurrentProcess(), &hmutex,
                             MUTEX_ALL_ACCESS, FALSE, 0)) {
                  verbose(lprintf(1, "Cannot duplicate mutex handle (error %lu)\n", GetLastError()));
                  UnmapViewOfFile(state);
                  continue;
            }
            if (!DuplicateHandle(hprocess, state->hflxtxevent,
                             GetCurrentProcess(), &hflxtxevent,
                             EVENT_MODIFY_STATE, FALSE, 0)) {
                  verbose(lprintf(1, "Cannot duplicate tx event handle (error %lu)\n", GetLastError()));
                  UnmapViewOfFile(state);
                  CloseHandle(hmutex);
                  continue;
            }
            if (!DuplicateHandle(hprocess, state->hflxrxevent,
                             GetCurrentProcess(), &hflxrxevent,
                             EVENT_ALL_ACCESS, FALSE, 0)) {
                  verbose(lprintf(1, "Cannot duplicate rx event handle (error %lu)\n", GetLastError()));
                  UnmapViewOfFile(state);
                  CloseHandle(hmutex);
                  CloseHandle(hflxtxevent);
                  continue;
            }
            /* allocate new device */
            if (!(api = calloc(1, sizeof(struct trxapi))))
                  goto err3;
            api->state = state;
            api->hmutex = hmutex;
            api->hflxtxevent = hflxtxevent;
            api->hflxrxevent = hflxrxevent;
            /* retrieve description */
            if (!(d = calloc(1, sizeof(struct trxapi_description) + 
                         (1 + 1) * sizeof(struct trxapi_banddescription))))
                  goto errdesc;
            api->desc = d;
            d->rxbands = (struct trxapi_banddescription *)(d + 1);
            d->txbands = &d->rxbands[1];
            strncpy(d->manufacturer, "Holger Eckart/Baycom", sizeof(d->manufacturer));
            d->manufacturer[sizeof(d->manufacturer)-1] = 0;
            strncpy(d->model, "T7F/Baycom USB", sizeof(d->model));
            d->model[sizeof(d->model)-1] = 0;
            strncpy(d->copyright, "(C) 1999-2000 Holger Eckart/Baycom", sizeof(d->copyright));
            d->copyright[sizeof(d->copyright)-1] = 0;
            strncpy(d->instid, state->serial, sizeof(d->instid));
            d->instid[sizeof(d->instid)-1] = 0;
            d->nrrxbands = 1;
            d->nrtxbands = 1;
            d->rssimin = RSSI_MIN;
            d->rssimax = RSSI_MAX;
            for (i = 0; i < d->nrrxbands; i++) {
                  d->rxbands[i].low = 430000000;
                  d->rxbands[i].high = 440000000;
                  d->rxbands[i].step = 12500;
            }
            for (i = 0; i < d->nrtxbands; i++) {
                  d->txbands[i].low = 430000000;
                  d->txbands[i].high = 440000000;
                  d->txbands[i].step = 12500;
            }
        errdesc:
            /* retrieve audio devs */
            api->audiodevs = audio_get_device_list();
            return api;
      }

  err2:
      CloseHandle(hprocess);
  err1:
      UnmapViewOfFile(globalstate);
      return NULL;

  err3:
      UnmapViewOfFile(state);
      CloseHandle(hmutex);
      CloseHandle(hflxtxevent);
      CloseHandle(hflxrxevent);
      goto err2;
}
/* MUTEX_ALL_ACCESS, EVENT_ALL_ACCESS, EVENT_MODIFY_STATE */

void win32shmem_close(struct trxapi *api)
{
      if (!api)
            return;
      if (api->desc)
            free(api->desc);
      if (api->audiodevs)
            free(api->audiodevs);
      UnmapViewOfFile(api->state);
      CloseHandle(api->hmutex);
      CloseHandle(api->hflxtxevent);
      CloseHandle(api->hflxrxevent);
      free(api);
}

void win32shmem_lock(struct trxapi *api)
{
      if (!api)
            return;
      WaitForSingleObject(api->hmutex, INFINITE);
}

void win32shmem_unlock(struct trxapi *api)
{
      if (!api)
            return;
      ReleaseMutex(api->hmutex);
}

void win32shmem_wakeup(struct trxapi *api)
{
      if (!api)
            return;
      SetEvent(api->hflxtxevent);
}

int win32shmem_init(int *argc, char **argv)
{
      return 0;
}

const struct trxapi_description *win32shmem_get_description(struct trxapi *api)
{
      if (!api)
            return NULL;
      return api->desc;
}

int win32shmem_get_state(struct trxapi *api, struct trxapi_state *state)
{
      struct trx_thread_state *servant;

      if (!state || !api)
            return -1;
      servant = api->state;
      if (servant->mode == MODE_DEAD)
            return -1;
      win32shmem_lock(api);
        switch (servant->mode) {
        case MODE_FSK:
        case MODE_AFSK:
        case MODE_EXTERNAL:
                state->mode = trxapi_mode_packet;
                break;
 
        case MODE_AUDIO:
                state->mode = trxapi_mode_audio;
                break;
 
        default:
                state->mode = trxapi_mode_unspec;
        }
        if (servant->flags & (FLG_T7FERROR | FLG_MODEMERROR)) {
                state->rxfreq = 0;
                state->txfreq = 0;
        } else {
                state->rxfreq = 430000000 + 12500*servant->rxdiv;
                state->txfreq = 430000000 + 12500*servant->txdiv;
        }
        state->ptt = servant->ptt ? 1 : 0;
        state->manualptt = (servant->flags & FLG_MANUALPTT) ? 1 : 0;
        state->dcd = servant->dcd ? 1 : 0;
        state->rssi = RSSI_MIN+(servant->rssi*((RSSI_MAX-RSSI_MIN)/255.0));
      win32shmem_unlock(api);
      return 0;
}

int win32shmem_set_ptt(struct trxapi *api, unsigned int ptt)
{
      struct trx_thread_state *servant;
      
      if (!api)
            return -1;
      servant = api->state;
      if (servant->mode == MODE_DEAD)
            return -1;
      win32shmem_lock(api);
        if (ptt)
                servant->flags |= FLG_MANUALPTT;
        else
                servant->flags &= ~FLG_MANUALPTT;
        servant->flags |= FLG_SETPTT;
      win32shmem_unlock(api);
      return 0;
}

int win32shmem_set_frequency(struct trxapi *api, trxapi_frequency_t rx, trxapi_frequency_t tx)
{
      struct trx_thread_state *servant;
        unsigned int dr, dt;
      
      if (!api)
            return -1;
      servant = api->state;
      if (servant->mode == MODE_DEAD)
            return -1;
        if (rx < 430000000)
                rx = 0;
        else
                rx -= (430000000-12500/2);
        if (tx < 430000000)
                tx = 0;
        else
                tx -= (430000000-12500/2);
        if (rx > 10000000)
                dr = 800;
        else
                dr = ((unsigned int)rx) / 12500;
        if (tx > 10000000)
                dt = 800;
        else
                dt = ((unsigned int)tx) / 12500;
      win32shmem_lock(api);
        servant->newrxdiv = dr;
        servant->newtxdiv = dt;
        servant->flags |= FLG_SETFREQ | FLG_SAVECONFIG;
        servant->cfg.freq.rx = 430000000 + 12500 * dr;
        servant->cfg.freq.tx = 430000000 + 12500 * dt;
      win32shmem_unlock(api);
      return 0;
}

/* Raw UART */
int win32shmem_uart_send(struct trxapi *api, const char *str)
{
      struct trx_thread_state *servant;
        int r;

      if (!api || !str)
            return -1;
      servant = api->state;
      if (servant->mode == MODE_DEAD)
            return -1;
      win32shmem_lock(api);
        r = addtxfifo(servant, str, strlen(str));
      win32shmem_unlock(api);
      if (r)
            return -1;
      return 0;
}

int win32shmem_uart_receive(struct trxapi *api, unsigned long *ptr, char *str, unsigned int strsz)
{
      struct trx_thread_state *servant;
      unsigned int i, p;
                                                            
      if (!api || !str || strsz < 2 || !ptr)
            return -1;
      servant = api->state;
      if (servant->mode == MODE_DEAD)
            return -1;
      win32shmem_lock(api);
      p = *ptr;
        i = getrxfifo(servant, &p, str, strsz-1);
      *ptr = p;
      win32shmem_unlock(api);
      str[i] = 0;
      return 0;
}

/* Configuration stuff */
int win32shmem_baycomusb_adapter_get_config(struct trxapi *api, struct trxapi_baycomusb_adapter_config *cfg)
{
      struct trx_thread_state *servant;

      if (!api || !cfg)
            return -1;
      servant = api->state;
      if (servant->mode == MODE_DEAD)
            return -1;
      win32shmem_lock(api);
      *cfg = servant->cfg.adapt;
      win32shmem_unlock(api);
      return 0;
}

int win32shmem_baycomusb_adapter_set_config(struct trxapi *api, const struct trxapi_baycomusb_adapter_config *cfg)
{
      struct trx_thread_state *servant;
      unsigned char rfsq;

      if (!api || !cfg)
            return -1;
      servant = api->state;
      if (servant->mode == MODE_DEAD)
            return -1;
      win32shmem_lock(api);
      if (checkreload_adapt(servant, cfg))
            servant->flags |= FLG_RELOADMODEM;  
      servant->cfg.adapt = *cfg;
        /* clamp values */
        if (servant->cfg.adapt.rfsquelch <= RSSI_MIN) {
                servant->cfg.adapt.rfsquelch = RSSI_MIN;
                rfsq = 0;
        } else if (servant->cfg.adapt.rfsquelch >= RSSI_MAX) {
                servant->cfg.adapt.rfsquelch = RSSI_MAX;
                rfsq = 255;
        } else
                rfsq = (servant->cfg.adapt.rfsquelch - RSSI_MIN) * (255.0/(RSSI_MAX-RSSI_MIN));
#if defined(WIN32) || defined(USERMODEDRV)
        servant->audioparam.rfsquelch = rfsq;
#endif
      servant->flags |= FLG_SAVECONFIG;
      win32shmem_unlock(api);
      return 0;
}

const struct trxapi_baycomusb_adapter_audio_devs *win32shmem_baycomusb_adapter_get_audiodevices(struct trxapi *api)
{
      if (!api)
            return NULL;
      return api->audiodevs;
}


int win32shmem_channel_access_get_config(struct trxapi *api, struct trxapi_channel_access_config *cfg)
{
      return -1;
}

int win32shmem_channel_access_set_config(struct trxapi *api, const struct trxapi_channel_access_config *cfg)
{
      return -1;
}


int win32shmem_interface_get_config(struct trxapi *api, struct trxapi_interface_config *cfg)
{
      return -1;
}

int win32shmem_interface_set_config(struct trxapi *api, const struct trxapi_interface_config *cfg)
{
      return -1;
}

int win32shmem_modem_disconnect_get_config(struct trxapi *api, struct trxapi_modem_disconnect_config *cfg)
{
      struct trx_thread_state *servant;

      if (!api || !cfg)
            return -1;
      servant = api->state;
      if (servant->mode == MODE_DEAD)
            return -1;
      win32shmem_lock(api);
      *cfg = servant->cfg.mdisc;
      win32shmem_unlock(api);
      return 0;
}

int win32shmem_modem_disconnect_set_config(struct trxapi *api, const struct trxapi_modem_disconnect_config *cfg)
{
      struct trx_thread_state *servant;

      if (!api || !cfg)
            return -1;
      servant = api->state;
      if (servant->mode == MODE_DEAD)
            return -1;
      win32shmem_lock(api);
      if (checkreload_mdisc(servant, cfg))
            servant->flags |= FLG_RELOADMODEM;
      servant->cfg.mdisc = *cfg;
      servant->flags |= FLG_SAVECONFIG;
      win32shmem_unlock(api);
      return 0;
}

/* Audio Stuff */

int win32shmem_get_audio_state(struct trxapi *api, struct trxapi_audio_state *state)
{
      struct trx_thread_state *servant;
      
      if (!api || !state)
            return -1;
      servant = api->state;
      if (servant->mode != MODE_AUDIO)
            return -1;
      win32shmem_lock(api);
        state->samplerate = AUDIOSAMPLINGRATE;
        state->micbufsz = sizeof(servant->du.a.isrc.abuf);
        state->micbufptr = servant->du.a.isrc.aptr;
        state->spkbufsz = sizeof(servant->du.a.osrc.abuf);
        state->spkbufptr = servant->du.a.osrc.aptr;
        state->micsigpwr = servant->du.a.isrc.sigpwr;
        state->spksigpwr = servant->du.a.osrc.sigpwr;
        state->spknoisepwr = servant->du.a.osrc.noisepwr;
      win32shmem_unlock(api);
      return 0;
}

int win32shmem_get_audio_mic_samples(struct trxapi *api, unsigned long ptr, unsigned long len, unsigned char *samples)
{
      struct trx_thread_state *servant;
      unsigned int x;

      if (!api || !samples || len <= 0)
            return -1;
      servant = api->state;
      if (servant->mode != MODE_AUDIO)
            return -1;
      win32shmem_lock(api);
        if (len > sizeof(servant->du.a.isrc.abuf) || ptr >= sizeof(servant->du.a.isrc.abuf))
            goto err;
        x = sizeof(servant->du.a.isrc.abuf) - ptr;
        if (x > len)
                x = len;
        memcpy(samples, &servant->du.a.isrc.abuf[ptr], x);
        len -= x;
        if (len)
                memcpy(&samples[x], servant->du.a.isrc.abuf, len);
      win32shmem_unlock(api);
      return 0;

  err:
      win32shmem_unlock(api);
      return -1;
}

int win32shmem_get_audio_spk_samples(struct trxapi *api, unsigned long ptr, unsigned long len, unsigned char *samples)
{
      struct trx_thread_state *servant;
      unsigned int x;
      
      if (!api || !samples || len <= 0)
            return -1;
      servant = api->state;
      if (servant->mode != MODE_AUDIO)
            return -1;
      win32shmem_lock(api);
        if (len > sizeof(servant->du.a.osrc.abuf) || ptr >= sizeof(servant->du.a.osrc.abuf))
            goto err;
        x = sizeof(servant->du.a.osrc.abuf) - ptr;
        if (x > len)
                x = len;
        memcpy(samples, &servant->du.a.osrc.abuf[ptr], x);
        len -= x;
        if (len)
                memcpy(&samples[x], servant->du.a.osrc.abuf, len);
      win32shmem_unlock(api);
      return 0;

  err:
      win32shmem_unlock(api);
      return -1;
}

int win32shmem_set_audio_dtmf(struct trxapi *api, long ch)
{
      struct trx_thread_state *servant;
        static const unsigned char dtmftransl[0x10] = {
                0x13, 0x00, 0x10, 0x20, 0x01, 0x11, 0x21, 0x02,
                0x12, 0x22, 0x30, 0x31, 0x32, 0x33, 0x03, 0x23
        };
        static const unsigned int freqlogrp[4] = { 697, 770, 852, 941 };
        static const unsigned int freqhigrp[4] = { 1209, 1336, 1477, 1633 };
        unsigned int sr, freq0 = 0, freq1 = 0, tr;

      if (!api)
            return -1;
      servant = api->state;
      if (servant->mode != MODE_AUDIO)
            return -1;
      sr = servant->du.a.p.srateusb;
      win32shmem_lock(api);
        if (ch == 16) {
                if (sr > 0)
                        freq0 = (1750*65536 + sr/2) / sr;
        } else if (ch >= 0 && ch <= 15) {
                tr = dtmftransl[ch & 15];
                freq0 = (freqlogrp[tr & 15]*65536+sr/2)/sr;
                freq1 = (freqhigrp[tr >> 4]*65536+sr/2)/sr;
        } else if (ch != -1)
            goto err;
        servant->du.a.isrc.freq0 = freq0;
        servant->du.a.isrc.freq1 = freq1;
        servant->du.a.isrc.ph0 = 0;
        servant->du.a.isrc.ph1 = 0;
      win32shmem_unlock(api);
      return 0;

  err:
      win32shmem_unlock(api);
      return -1;
}

/* --------------------------------------------------------------------- */

Generated by  Doxygen 1.6.0   Back to index