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

bayusb_old2.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 "trxclient.h"

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

#define DRIVER_NAME     "BaycomUSB"
#define DRIVER_VERSION  "0.2"

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

static struct state {
      unsigned int terminate;
      Trx_Control obj;
      HANDLE hobjmutex;
      HANDLE hdevlife;

            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;
      unsigned int fullduplex;

      UINT calibtimer;

      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;
}

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

/*
 * 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, regval;
      int argc = 0;
      char *argv[1] = { NULL };
      static int orbinit = 1;
      
      /* initialize ORB */
      if (orbinit && trx_initorb(&argc, argv))
                return 0;
      orbinit = 0;
      /* get serial from registry */
      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;
      reglen = sizeof(regval);
      if (RegQueryValueEx(hKey, "TxDelay", NULL, &regtype, (void *)&regval, &reglen) != ERROR_SUCCESS ||
          regtype != REG_DWORD)
            regval = 5;
      state.txdelay = regval;
      reglen = sizeof(regval);
      if (RegQueryValueEx(hKey, "FullDuplex", NULL, &regtype, (void *)&regval, &reglen) != ERROR_SUCCESS ||
          regtype != REG_DWORD)
            regval = 0;
      state.fullduplex = regval;
      state.terminate = 0;
        state.status = CH_DEAD;
      state.obj = CORBA_OBJECT_NIL;
      state.hdevlife = CreateEvent(NULL, FALSE, FALSE, "FlexNet Device State");
      state.hobjmutex = CreateMutex(NULL, FALSE, NULL);
        return 1;
}

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

void l1_exit(HKEY hKey)
{
      DWORD regval;

      state.terminate = 1;
      while (state.obj)
            Sleep(10);
        l1_init_kanal(0, 0, MODE_off);
      RegSetValueEx(hKey, "SerialNumber", 0, REG_SZ, state.serial, strlen(state.serial)+1);
      regval = state.txdelay;
      RegSetValueEx(hKey, "TxDelay", 0, REG_DWORD, (void *)&regval, sizeof(regval));
      regval = state.fullduplex;
      RegSetValueEx(hKey, "FullDuplex", 0, REG_DWORD, (void *)&regval, sizeof(regval));   
      CloseHandle(state.hdevlife);
      CloseHandle(state.hobjmutex);
}

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

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

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

static BOOL CALLBACK EdParmDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
        CORBA_Environment ev;
        Trx_TrxDescription *desc;
        Trx_Control obj;
        HWND hcombo;
        char buf[32];
      unsigned int restart, i, index;
        int cursel;

      switch (uMsg) {
      case WM_INITDIALOG:
                hcombo = GetDlgItem(hDlg, IDC_SERIAL);
                SendMessage(hcombo, CB_ADDSTRING, 0, (LPARAM)"Any");
            cursel = state.serial[0] ? -1 : 0;
            WaitForSingleObject(state.hobjmutex, INFINITE);
            CORBA_exception_init(&ev);
            for (index = 0, i = 1;; index++) {
                      if (!(obj = trx_resolve_byindex(index)))
                        break;
                  Trx_Control_GetDescription(obj, &desc, &ev);
                  if (ev._major == CORBA_NO_EXCEPTION) {
                        SendMessage(hcombo, CB_ADDSTRING, 0, (LPARAM)desc->instid);
                        if (!strcmp(desc->instid, state.serial))
                              cursel = i;
                        CORBA_free(desc);
                        i++;
                  }
                        CORBA_exception_free(&ev);
                        CORBA_Object_release(obj, &ev);
                        CORBA_exception_free(&ev);
                }
            ReleaseMutex(state.hobjmutex);
            ComboBox_SetCurSel(hcombo, cursel);
                snprintf(buf, sizeof(buf), "%d", state.txdelay);
                SetDlgItemText(hDlg, IDC_TXDELAY, buf);
                CheckDlgButton(hDlg, IDC_FULLDUPLEX, state.fullduplex ? BST_CHECKED : BST_UNCHECKED);
            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 (!strcmp(buf, "Any"))
                        buf[0] = 0;
                        restart = strcmp(buf, state.serial);
                        strncpy(state.serial, buf, sizeof(state.serial));
                  GetDlgItemText(hDlg, IDC_TXDELAY, buf, sizeof(buf));
                        state.txdelay = strtoul(buf, NULL, 0);
                        state.fullduplex = IsDlgButtonChecked(hDlg, IDC_FULLDUPLEX) == BST_CHECKED;
            EndDialog(hDlg, restart);
                        break;
                        
                default:      
                        break;
                }
                break;
      
      default:
            return FALSE;
      }
      return TRUE;
}

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

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

      if (restart) {
            WaitForSingleObject(state.hobjmutex, INFINITE);
            CORBA_exception_init(&ev);
            if (state.obj) {
                        Trx_Control_FlexNetUnlock(state.obj, &ev);
                        CORBA_exception_free(&ev);
                  CORBA_Object_release(state.obj, &ev);
                }
            CORBA_exception_free(&ev);
            state.obj = CORBA_OBJECT_NIL;
            ReleaseMutex(state.hobjmutex);
      }
      return restart;
}

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

u16 l1_get_ch_cnt(void)
{
      return 1;

}

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

byte get_txdelay(byte kanal)
{
      return state.txdelay / 10;
}

void set_txdelay(byte kanal, byte delay)
{
      state.txdelay = 10 * delay;
}

u16 get_mode(byte kanal)
{
      return (state.mode & ~MODE_d) | (state.fullduplex ? MODE_d : 0);
}

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)
{
        CORBA_Environment ev;

      WaitForSingleObject(state.hobjmutex, INFINITE);
      if (state.obj) {
            CORBA_exception_init(&ev);
            Trx_Control_FlexNetSetLEDS(state.obj, !!(ledcode & LED_CON), !!(ledcode & LED_STA), &ev);
            CORBA_exception_free(&ev);
      }
      ReleaseMutex(state.hobjmutex);
}

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

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)
{
        CORBA_Environment ev;

      WaitForSingleObject(state.hobjmutex, INFINITE);
      if (state.obj) {
            CORBA_exception_init(&ev);
            Trx_Control_SetPTT(state.obj, CORBA_FALSE, &ev);
            CORBA_exception_free(&ev);
      }
      ReleaseMutex(state.hobjmutex);
}

void l1_tx_calib(byte kanal, byte minutes)
{
        CORBA_Environment ev;

      if (state.calibtimer)
            KillTimer(NULL, state.calibtimer);
      WaitForSingleObject(state.hobjmutex, INFINITE);
      if (state.obj) {
            CORBA_exception_init(&ev);
            Trx_Control_SetPTT(state.obj, CORBA_TRUE, &ev);
            CORBA_exception_free(&ev);
      }
      ReleaseMutex(state.hobjmutex);
      state.calibtimer = SetTimer(NULL, 0, minutes * 60000, stopcalib);
      if (!state.calibtimer)
            stopcalib(NULL, 0, 0, 0);
}


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

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

byte l1_tx_frame(void)
{
        CORBA_Environment ev;
      Trx_FlexNetPacket pkt = { 0, };
      byte ret = 0;

        pkt.txdelay = state.txframe.txdelay;
        if (!pkt.txdelay)
                pkt.txdelay = state.txdelay / 10;
      pkt.data._buffer = state.txframe.frame;
      pkt.data._length = pkt.data._maximum = state.txframe.len;
      WaitForSingleObject(state.hobjmutex, INFINITE);
      if (!state.obj) {
            ReleaseMutex(state.hobjmutex);
            state.stat.io_error++;
            return 1;
      }
      CORBA_exception_init(&ev);
      Trx_Control_FlexNetSendPacket(state.obj, &pkt, &ev);
      if (ev._major == CORBA_NO_EXCEPTION) {
            ret = 1;
            state.stat.tx_frames++;
      }
      CORBA_exception_free(&ev);
      ReleaseMutex(state.hobjmutex);
      return ret;
}

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

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

L1FRAME far *l1_rx_frame(void)
{
        CORBA_Environment ev;
      CORBA_unsigned_long bitrate;
        Trx_TrxDescription *desc;
      Trx_FlexNetPollOneState *poll;
        Trx_Control obj;
      unsigned int i;
        byte st;
        
      WaitForSingleObject(state.hobjmutex, INFINITE);
      for (;;) {
            if (state.terminate) {
                  if (state.obj) {
                        CORBA_exception_init(&ev);
                                Trx_Control_FlexNetUnlock(state.obj, &ev);
                                CORBA_exception_free(&ev);
                        CORBA_Object_release(state.obj, &ev);
                        CORBA_exception_free(&ev);
                        state.obj = CORBA_OBJECT_NIL;
                  }
                  ReleaseMutex(state.hobjmutex);
                  return NULL;
            }
            if (!state.obj) {
                  state.status = CH_DEAD;
                  SetEvent(state.hdevlife);
                  for (i = 0; i < 20; i++) {
                        if (state.terminate)
                              break;
                        ReleaseMutex(state.hobjmutex);
                        Sleep(50);
                        WaitForSingleObject(state.hobjmutex, INFINITE);
                  }
                  if (state.terminate)
                        continue;
                  for (i = 0;; i++) {
                        CORBA_exception_init(&ev);
                        if (!(obj = trx_resolve_byindex(i)))
                              break;
                        Trx_Control_GetDescription(obj, &desc, &ev);
                        if (ev._major == CORBA_NO_EXCEPTION && 
                            (!state.serial[0] || !strcmp(desc->instid, state.serial)))
                              break;
                        CORBA_exception_free(&ev);
                        CORBA_Object_release(obj, &ev);
                        CORBA_exception_free(&ev);
                  }
                  if (!obj)
                        goto wait;
                  snprintf(state.devname, sizeof(state.devname), "%s (%s)", desc->model, desc->instid);
                  CORBA_free(desc);
                        if (!Trx_Control_FlexNetLock(obj, &ev) || ev._major != CORBA_NO_EXCEPTION) {
                                CORBA_exception_free(&ev);
                                CORBA_Object_release(obj, &ev);
                        CORBA_exception_free(&ev);
                                goto wait;        
                        }
                        Trx_Control_FlexNetGetBitrate(obj, &bitrate, &ev);
                  if (ev._major != CORBA_NO_EXCEPTION)
                        bitrate = 1;
                  CORBA_exception_free(&ev);
                  if (bitrate < 1)
                        bitrate = 1;
                  state.scale = 614400 / bitrate;
                  state.baud = bitrate / 100;
                  state.status = 0;
                  SetEvent(state.hdevlife);
                  state.obj = obj;
                }
                CORBA_exception_init(&ev);
                Trx_Control_FlexNetPollOne(state.obj, &poll, &ev);
                if (ev._major != CORBA_NO_EXCEPTION) {
                        CORBA_exception_free(&ev);
                        Trx_Control_FlexNetUnlock(state.obj, &ev);
                        CORBA_exception_free(&ev);
                        CORBA_Object_release(state.obj, &ev);
                        CORBA_exception_free(&ev);
                        state.obj = CORBA_OBJECT_NIL;
                        goto wait;
                }
                CORBA_exception_free(&ev);
                st = state.status;
                if (poll->ptt)
                        state.status |= CH_PTT;
                else
                        state.status &= ~CH_PTT;
                if (poll->dcd)
                        state.status |= CH_DCD;
                else
                        state.status &= ~CH_DCD;
                if (poll->nrpkt > 1)
                        state.status |= CH_RXB;
                else
                        state.status &= ~CH_RXB;
                if (poll->dead)
                        state.status |= CH_DEAD;
                else
                        state.status &= ~CH_DEAD;
                if ((state.status ^ st) & CH_DEAD)
                        SetEvent(state.hdevlife);
                if (!poll->pkt.data._length) {
                        CORBA_free(poll);
                        goto wait;
                }
                state.rxframe.kanal = 0;
                state.rxframe.txdelay = poll->pkt.txdelay;
                state.rxframe.len = poll->pkt.data._length;
                memcpy(state.rxframe.frame, poll->pkt.data._buffer, state.rxframe.len);
                CORBA_free(poll);
                ReleaseMutex(state.hobjmutex);
                return &state.rxframe;
                
          wait:
            ReleaseMutex(state.hobjmutex);
            Sleep(10);
            WaitForSingleObject(state.hobjmutex, INFINITE);
      }
}

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

Generated by  Doxygen 1.6.0   Back to index