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

bayusb_old.c

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

/*
 *    bayusb.c  --  FlexNet driver for Baycom USB modem.
 *
 *    Copyright (C) 1999-2000
 *          Thomas Sailer (sailer@ife.ee.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.
 *
 *
 *  History:
 *   0.1  23.06.1999  Created
 *   0.2  07.01.2000  Expanded to usbdevfs capabilities
 *
 */

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

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

#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <stdlib.h>

#include "flexdrv.h"
#include "resource.h"

#include "pktio.h"
#include "baycomusb.h"

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

#define DRIVER_NAME     "BaycomUSB"
#define DRIVER_VERSION  "0.1"

#define RX_RUNNING   0
#define RX_RESTART   1
#define RX_TERMINATE 2

#define TX_NORMAL    0
#define TX_LOCKPKT   1
#define TX_TERMINATE 2

struct pkthandle {
      struct pktio *pkt;
      unsigned int refcnt;
};

static struct state {
      volatile unsigned int terminate;
      volatile unsigned int rxactive;
      struct pkthandle *pkt;
      struct configentry *cfg;

            char serial[16];   /* device serial number, or NULL string for any device */
      char devname[32];

        byte baud;
      byte mode;
      byte status;

      unsigned int scale;
      unsigned int txdelay;

      UINT calibtimer;
      unsigned int stopcalib;

      HANDLE hdevlife;
      HANDLE hpktmutex;

      L1FRAME txframe;
      L1FRAME rxframe;
      L1_STATISTICS stat;
} state = { 0, };

#define REGISTRYPATH "SOFTWARE\\FlexNet\\BaycomUSB"
#define REGHKEY      HKEY_LOCAL_MACHINE

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

int lprintf(unsigned vl, const char *format, ...)
{
        va_list ap;
        char buf[512];
        int r;

      va_start(ap, format);
        r = vsnprintf(buf, sizeof(buf), format, ap);
      va_end(ap);
        OutputDebugString(buf);
        return r;
}

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

static struct pkthandle *pktget(void)
{
      struct pkthandle *r;

      WaitForSingleObject(state.hpktmutex, INFINITE);
      r = state.pkt;
      if (r)
            r->refcnt++;
      ReleaseMutex(state.hpktmutex);
      return r;
}

static void pktput(struct pkthandle *pkt)
{
      unsigned int r;

      if (!pkt)
            return;
      WaitForSingleObject(state.hpktmutex, INFINITE);
      if (pkt->refcnt)
            pkt->refcnt--;
      r = pkt->refcnt;
      ReleaseMutex(state.hpktmutex);
      if (r)
            return;
      pkt_close(pkt->pkt);
      free(pkt);
}

static void pktrelease(void)
{
      struct pkthandle *pkt;
      unsigned int r = 1;

      WaitForSingleObject(state.hpktmutex, INFINITE);
      pkt = state.pkt;
      state.pkt = NULL;
      if (pkt) {
            if (pkt->refcnt)
                  pkt->refcnt--;
            r = pkt->refcnt;
      }
      ReleaseMutex(state.hpktmutex);
      if (r)
            return;
      pkt_close(pkt->pkt);
      free(pkt);
}

static void pktopen(void)
{
      struct pkthandle *pkt = malloc(sizeof(struct pkthandle));
      struct pkthandle *pkt2;

      if (!pkt)
            return;
      pkt->refcnt = 1;
      pkt->pkt = pkt_open(state.serial, 0);
      if (!pkt->pkt) {
            free(pkt);
            return;
      }
      WaitForSingleObject(state.hpktmutex, INFINITE);
      pkt2 = state.pkt;
      state.pkt = pkt;
      ReleaseMutex(state.hpktmutex);
      if (pkt2)
            pktput(pkt2);
}

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

/*
 * Treiber-Init. Sofern mehrfach aufgerufen, kommt vorher jeweils l1_exit()
 * Hier also alle Ressourcen allokieren, aber noch nicht starten sofern
 * dazu die Parameter gebraucht werden. Die kommen spaeter per l1_init_kanal()
 */

int init_device(HKEY hKey)
{
      DWORD regtype, reglen;

      reglen = sizeof(state.serial);
      if (RegQueryValueEx(hKey, "SerialNumber", NULL, &regtype, state.serial, &reglen) != ERROR_SUCCESS ||
          regtype != REG_SZ)
            state.serial[0] = 0;
      state.serial[sizeof(state.serial)-1] = 0;
      state.terminate = state.rxactive = 0;
        state.status = CH_DEAD;
      state.cfg = NULL;
      state.hdevlife = CreateEvent(NULL, FALSE, FALSE, "FlexNet Device State");
      state.hpktmutex = CreateMutex(NULL, FALSE, NULL);
        return 1;
}

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

void l1_exit(HKEY hKey)
{
      state.terminate = 1;
      while (state.rxactive)
            Sleep(10);
      pktrelease();
        l1_init_kanal(0, 0, MODE_off);
      RegSetValueEx(hKey, "SerialNumber", 0, REG_SZ, state.serial, strlen(state.serial)+1);
      CloseHandle(state.hdevlife);
      CloseHandle(state.hpktmutex);
}

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

byte *config_info(byte kanal)
{
      return state.devname;
}

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

static BOOL CALLBACK EdParmDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
        HWND hcombo;
        HKEY regkey;
        LONG err;
        DWORD index;
        DWORD len;
        char buf[32];
      unsigned int restart, i;
        int cursel;

      switch (uMsg) {
      case WM_INITDIALOG:
                hcombo = GetDlgItem(hDlg, IDC_SERIAL);
                SendMessage(hcombo, CB_ADDSTRING, 0, (LPARAM)"Any");
                err = RegOpenKeyEx(REGHKEY, REGISTRYPATH, 0, KEY_READ, &regkey);
                if (err == ERROR_SUCCESS) {
                        cursel = state.serial[0] ? -1 : 0;
                        for (i = 1, index = 0;; index++) {
                                len = sizeof(buf);
                                if ((RegEnumKeyEx(regkey, index, buf, &len, NULL, NULL, NULL, NULL)) != ERROR_SUCCESS)
                                        break;
                                if (buf[0] >= '0' && buf[0] <= '9') {       
                                        SendMessage(hcombo, CB_ADDSTRING, 0, (LPARAM)buf);
                                        if (!strcmp(buf, state.serial))
                                                cursel = i;
                                        i++;
                                }
                        }
                        ComboBox_SetCurSel(hcombo, cursel);
                        RegCloseKey(regkey);
                }
            SetWindowText(hDlg, DRIVER_NAME" Configuration");
            break;
                
        case WM_COMMAND:
                switch (GET_WM_COMMAND_ID(wParam, lParam)) {
                case IDCANCEL:
                        EndDialog(hDlg, 0);
                        break;

                case IDOK:
                        GetDlgItemText(hDlg, IDC_SERIAL, buf, sizeof(buf));
                        if (buf[0] < '0' || buf[0] > '9')
                                buf[0] = 0;
                        restart = strcmp(buf, state.serial);
                        strncpy(state.serial, buf, sizeof(state.serial));
                  EndDialog(hDlg, restart);
                        break;
                        
                default:      
                        break;
                }
                break;
      
      default:
            return FALSE;
      }
      return TRUE;
}

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

int config_device(byte max_channels, HWND hDlg, byte channel)
{
      int restart = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_DIALOG1), hDlg, EdParmDlgProc, 0);

      if (restart)
            pktrelease();
      return restart;
}

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

u16 l1_get_ch_cnt(void)
{
      return 1;

}

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

byte get_txdelay(byte kanal)
{
        byte txd = 0;
        
      if (state.cfg)
            txd = state.cfg->chaccess.txdelay / 10;
        lprintf(10, "get_txdelay: %u\n", txd);
      return txd;
}

void set_txdelay(byte kanal, byte delay)
{
      if (state.cfg)
            state.cfg->chaccess.txdelay = 10 * delay;
}

u16 get_mode(byte kanal)
{
      return state.mode;
}

u16 get_baud(byte kanal)
{
      return state.baud;
}

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

byte l1_init_kanal(byte kanal, u16 chbaud, u16 chmode)
{
      state.mode = chmode;
      return 1;
}

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

byte l1_ch_active(byte kanal)
{
      return 1;
}

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

char far *l1_ident(byte kanal)
{
      return DRIVER_NAME;
}

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

char far *l1_version(byte kanal)
{
      return DRIVER_VERSION;
}

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

L1_STATISTICS far *l1_stat(byte kanal, byte delete)
{
      L1_STATISTICS *p = &state.stat;
      
      if (delete)
            p->tx_error = p->rx_overrun = p->rx_bufferoverflow =
            p->tx_frames = p->rx_frames = p->io_error = 0;
      return p;
}

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

void set_led(byte kanal, byte ledcode)
{
#if 0
      if (state.active)
            pkt_setled(state.pkt, ledcode);
#endif
}

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

byte l1_ch_state(byte kanal)
{
      return state.status;
}

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

u16 l1_scale(byte kanal)
{
      return state.scale;
}

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

static void CALLBACK stopcalib(HWND hwnd, UINT umsg, UINT idevent, DWORD dwtime)
{
      state.stopcalib = 1;
}

void l1_tx_calib(byte kanal, byte minutes)
{
      struct pkthandle *pkt = pktget();

      if (!pkt)
            return;
      if (state.calibtimer)
            KillTimer(NULL, state.calibtimer);
      state.stopcalib = 0;
      pkt_forceptt(pkt->pkt, 1);
      pktput(pkt);
      state.calibtimer = SetTimer(NULL, 0, minutes * 60000, stopcalib);
      if (!state.calibtimer)
            state.stopcalib = 1;
}


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

L1FRAME far *l1_get_framebuf(byte kanal)
{
      return &state.txframe;
}

byte l1_tx_frame(void)
{
      struct pkthandle *pkt = pktget();
        unsigned int txd;
      int r;

      if (!pkt) {
            state.stat.io_error++;
            return 1;
      }
        txd = state.txframe.txdelay;
        if (!txd && state.cfg)
                txd = state.cfg->chaccess.txdelay / 10;
      r = pkt_transmit(pkt->pkt, txd, state.txframe.frame, state.txframe.len);
      pktput(pkt);
      if (r == -1) {
            pktrelease();
            state.stat.io_error++;
            return 1;
      }
      if (r < 0)
            return 0;
      state.stat.tx_frames++;
      return 1;
}

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

/*
 * RX-Thread. Wartet auf RX-Bytes, verarbeitet sie und returned wenn
 * Handle zu oder Paket komplett
 */

L1FRAME far *l1_rx_frame(void)
{
      struct pkthandle *pkt;
      unsigned int i;
        char buf[32];
      byte st;
      int r;

      state.rxactive = 1;
      for (;;) {
            if (state.terminate) {
                  state.rxactive = 0;
                  return NULL;
            }
            if (!(pkt = pktget())) {
                  for (;;) {
                        pktopen();
                        if ((pkt = pktget()))
                              break;
                        state.status = CH_DEAD;
                        SetEvent(state.hdevlife);
                        for (i = 0; i < 20; i++) {
                              if (state.terminate) {
                                    state.rxactive = 0;
                                    return NULL;
                              }
                              Sleep(50);
                        }
                  }
                  pkt_getserial(pkt->pkt, buf, sizeof(buf));
                  buf[sizeof(buf)-1] = 0;
                  sprintf(state.devname, "BaycomUSB %s", buf);
                  state.cfg = config_lookup(buf);
                  r = pkt_getbitrate(pkt->pkt);
                  if (r < 1)
                        r = 1;
                  state.scale = 614400 / r;
                  state.baud = r / 100;
                  state.status = 0;
                  SetEvent(state.hdevlife);                 
            }
            if (state.stopcalib) {
                  state.stopcalib = 0;
                  pkt_forceptt(pkt->pkt, 0);
            }
            /* update status */
            r = pkt_getstatus(pkt->pkt);
            if (r < 0) {
                  pktput(pkt);
                  pktrelease();
                  state.stat.io_error++;
                  state.status = CH_DEAD;
                  SetEvent(state.hdevlife);
                  state.rxactive = 0;
                  return NULL;
            }
            st = 0;
            if (r & PKTSTAT_PTT)
                  st |= CH_PTT;
            if (r & PKTSTAT_DCD)
                  st |= CH_DCD;
            if (r & PKTSTAT_RXB)
                  st |= CH_RXB;
            state.status = st;
            /* try to receive */
            if (st & CH_RXB) {
                  r = pkt_receive(pkt->pkt, state.rxframe.frame, sizeof(state.rxframe.frame));
                  if (r < 0) {
                        pktput(pkt);
                        pktrelease();
                        state.stat.io_error++;
                        state.status = CH_DEAD;
                        SetEvent(state.hdevlife);
                        state.rxactive = 0;
                        return NULL;
                  }
                  if (r > 0) {
                        pktput(pkt);
                        state.rxframe.len = r;
                        state.rxframe.kanal = 0;
                        state.rxframe.txdelay = 0;
                        state.rxactive = 0;
                        return &state.rxframe;
                  }
            }
            pktput(pkt);
            Sleep(10);
      }
}

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

Generated by  Doxygen 1.6.0   Back to index