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

bayusb.c

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

/*
 *    bayusb.c  --  FlexNet driver for Baycom USB modem.
 *
 *    Copyright (C) 1999-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.
 *
 *
 *  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 "trx.h"
#include "win32client.h"

#define VERBOSE

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

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

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

#define APIFLG_COUNTMASK       0x0ffff
#define APIFLG_TERMINATE       0x10000
#define APIFLG_CLOSE           0x20000

static struct state {
      struct trxapi *api;
      unsigned int apiflags;
      CRITICAL_SECTION apilock;

      HANDLE hdevlife;

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

      u16 mode;

      UINT calibtimer;

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

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

static struct trx_thread_state *api_lock()
{
      struct trx_thread_state *servant = NULL;
      const struct trxapi_description *desc;
      struct trxapi *api;
      unsigned int i;

      EnterCriticalSection(&state.apilock);
      if (state.apiflags & (APIFLG_TERMINATE|APIFLG_CLOSE))
            goto out;
      if (!state.api) {
            for (i = 0;; i++) {
                  if (!(api = win32shmem_open_byindex(i)))
                        break;
                  desc = win32shmem_get_description(api);
                  if (desc && (!state.serial[0] || !strcmp(desc->instid, state.serial)))
                        break;
                  win32shmem_close(api);
            }
            if (api) {
                  snprintf(state.devname, sizeof(state.devname), "%s (%s)", desc->model, desc->instid);
                  servant = api->state;
                  win32shmem_lock(api);
                  if (servant->mode == MODE_DEAD || servant->flexnetlock) {
                        win32shmem_unlock(api);
                        win32shmem_close(api);
                  } else {
                        servant->flexnetlock = 1;
                        win32shmem_unlock(api);
                        SetEvent(state.hdevlife);
                        state.api = api;
                  }
            }
      }
      if (!state.api)
            goto out;
      servant = state.api->state;
      if (servant->mode == MODE_DEAD) {
            servant = NULL;
            state.apiflags |= APIFLG_CLOSE;
            SetEvent(state.api->hflxrxevent);
            if (!(state.apiflags & APIFLG_COUNTMASK)) {
                  win32shmem_lock(state.api);
                  state.api->state->flexnetlock = 0;
                  win32shmem_unlock(state.api);
                  win32shmem_close(state.api);
                  state.api = NULL;
                  state.apiflags &= ~APIFLG_CLOSE;
                  SetEvent(state.hdevlife);
            }
            goto out;
      }
      state.apiflags = (state.apiflags & ~APIFLG_COUNTMASK) | ((state.apiflags + 1) & APIFLG_COUNTMASK);
  out:
      LeaveCriticalSection(&state.apilock);
      return servant;
}

static void api_unlock(void)
{
      EnterCriticalSection(&state.apilock);
      state.apiflags = (state.apiflags & ~APIFLG_COUNTMASK) | ((state.apiflags - 1) & APIFLG_COUNTMASK);
      if ((state.apiflags & APIFLG_CLOSE) && !(state.apiflags & APIFLG_COUNTMASK)) {
            win32shmem_lock(state.api);
            state.api->state->flexnetlock = 0;
            win32shmem_unlock(state.api);
            win32shmem_close(state.api);
            state.api = NULL;
            state.apiflags &= ~APIFLG_CLOSE;
            SetEvent(state.hdevlife);
      }
      LeaveCriticalSection(&state.apilock);
}

static void api_close(void)
{
      EnterCriticalSection(&state.apilock);
      if (state.api) {
            state.apiflags |= APIFLG_CLOSE;
            SetEvent(state.api->hflxrxevent);
            if (!(state.apiflags & APIFLG_COUNTMASK)) {
                  win32shmem_lock(state.api);
                  state.api->state->flexnetlock = 0;
                  win32shmem_unlock(state.api);
                  win32shmem_close(state.api);
                  state.api = NULL;
                  state.apiflags &= ~APIFLG_CLOSE;
                  SetEvent(state.hdevlife);
            }
      }
      LeaveCriticalSection(&state.apilock);
}

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

/*
 * 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;

      verboselevel = ~0;
      syslogmsg = 1;
      /* 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;
      state.api = NULL;
      state.apiflags = 0;
      InitializeCriticalSection(&state.apilock);
      state.hdevlife = CreateEvent(NULL, FALSE, FALSE, "FlexNet Device State");
        return 1;
}

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

void l1_exit(HKEY hKey)
{
      EnterCriticalSection(&state.apilock);
      state.apiflags |= APIFLG_TERMINATE;
      LeaveCriticalSection(&state.apilock);
      api_close();
      l1_init_kanal(0, 0, MODE_off);
      RegSetValueEx(hKey, "SerialNumber", 0, REG_SZ, state.serial, strlen(state.serial)+1);
      EnterCriticalSection(&state.apilock);
      while (state.api) {
            LeaveCriticalSection(&state.apilock);
            Sleep(10);
            EnterCriticalSection(&state.apilock);
      }
      LeaveCriticalSection(&state.apilock);
      CloseHandle(state.hdevlife);
      DeleteCriticalSection(&state.apilock);
}

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

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

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

static void setdlgitems(HWND hDlg)
{
      struct trxapi *api;
      const struct trxapi_description *desc;
      struct trx_thread_state *servant;
        char buf[32];
      unsigned int i;
      HWND hcombo;

      GetDlgItemText(hDlg, IDC_SERIAL, buf, sizeof(buf));
      if (!strcmp(buf, "Any"))
            buf[0] = 0;
      if (!buf[0]) {
            api = win32shmem_open_byindex(0);
      } else {
            for (i = 0;; i++) {
                  if (!(api = win32shmem_open_byindex(i)))
                        break;
                  desc = win32shmem_get_description(api);
                  if (desc) {
                        if (!strcmp(desc->instid, buf))
                              break;
                  }
                  win32shmem_close(api);
            }
      }
      if (!api) {
            lprintf(10, "No modem found\n");
            /* gray out dialog */
            hcombo = GetDlgItem(hDlg, IDC_MODE);
            ComboBox_ResetContent(hcombo);
            SendMessage(hcombo, CB_ADDSTRING, 0, (LPARAM)"-");
            SendDlgItemMessage(hDlg, IDC_BITRATERX, EM_SETREADONLY, 1, 0);
            SendDlgItemMessage(hDlg, IDC_BITRATETX, EM_SETREADONLY, 1, 0);
            SendDlgItemMessage(hDlg, IDC_TXDELAY, EM_SETREADONLY, 1, 0);
            CheckDlgButton(hDlg, IDC_FULLDUPLEX, BST_INDETERMINATE);
            CheckDlgButton(hDlg, IDC_PTTMUTE, BST_INDETERMINATE);
            return;
      }
      servant = api->state;
      hcombo = GetDlgItem(hDlg, IDC_MODE);
      ComboBox_ResetContent(hcombo);
      SendMessage(hcombo, CB_ADDSTRING, 0, (LPARAM)"-");
      SendMessage(hcombo, CB_ADDSTRING, 0, (LPARAM)"fsk");
      SendMessage(hcombo, CB_ADDSTRING, 0, (LPARAM)"afsk");
      SendMessage(hcombo, CB_ADDSTRING, 0, (LPARAM)"external");
      SendMessage(hcombo, CB_ADDSTRING, 0, (LPARAM)"audio");
      switch (servant->cfg.adapt.mode) {
      case trxapi_baycomusb_mode_fsk:
            ComboBox_SetCurSel(hcombo, 1);
            break;

      case trxapi_baycomusb_mode_external:
            ComboBox_SetCurSel(hcombo, 3);
            break;

      case trxapi_baycomusb_mode_afsk:
            ComboBox_SetCurSel(hcombo, 2);
            break;

      case trxapi_baycomusb_mode_audio:
            ComboBox_SetCurSel(hcombo, 4);
            break;

      default:
            ComboBox_SetCurSel(hcombo, 0);
            break;
      }
      SendDlgItemMessage(hDlg, IDC_BITRATERX, EM_SETREADONLY, 0, 0);
      snprintf(buf, sizeof(buf), "%ld", servant->cfg.adapt.bitraterx);
      SetDlgItemText(hDlg, IDC_BITRATERX, buf);
      SendDlgItemMessage(hDlg, IDC_BITRATETX, EM_SETREADONLY, 0, 0);
      snprintf(buf, sizeof(buf), "%ld", servant->cfg.adapt.bitratetx);
      SetDlgItemText(hDlg, IDC_BITRATETX, buf);
      SendDlgItemMessage(hDlg, IDC_TXDELAY, EM_SETREADONLY, 0, 0);
      snprintf(buf, sizeof(buf), "%ld", servant->cfg.chacc.txdelay);
      SetDlgItemText(hDlg, IDC_TXDELAY, buf);
      CheckDlgButton(hDlg, IDC_FULLDUPLEX, servant->cfg.chacc.fulldup ? BST_CHECKED : BST_UNCHECKED);
      CheckDlgButton(hDlg, IDC_PTTMUTE, servant->cfg.adapt.pttmute ? BST_CHECKED : BST_UNCHECKED);
      win32shmem_close(api);
}

static unsigned int getdlgitems(HWND hDlg)
{
      struct trxapi *api;
      const struct trxapi_description *desc;
      struct trx_thread_state *servant;
      struct trxapi_baycomusb_adapter_config cf;
        char buf[32];
      unsigned int restart, i;

      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));
      if (!buf[0]) {
            api = win32shmem_open_byindex(0);
      } else {
            for (i = 0;; i++) {
                  if (!(api = win32shmem_open_byindex(i)))
                        break;
                  desc = win32shmem_get_description(api);
                  if (desc) {
                        if (!strcmp(desc->instid, buf))
                              break;
                  }
                  win32shmem_close(api);
            }
      }
      if (!api) {
            lprintf(10, "No modem found\n");
            return restart;
      }
      servant = api->state;
      cf = servant->cfg.adapt;
      GetDlgItemText(hDlg, IDC_MODE, buf, sizeof(buf));
      if (!strcmp(buf, "fsk"))
            cf.mode = trxapi_baycomusb_mode_fsk;
      else if (!strcmp(buf, "external"))
            cf.mode = trxapi_baycomusb_mode_external;
      else if (!strcmp(buf, "afsk"))
            cf.mode =  trxapi_baycomusb_mode_afsk;
      else if (!strcmp(buf, "audio"))
            cf.mode = trxapi_baycomusb_mode_audio;
      GetDlgItemText(hDlg, IDC_BITRATERX, buf, sizeof(buf));
      cf.bitraterx = strtoul(buf, NULL, 0);
      GetDlgItemText(hDlg, IDC_BITRATETX, buf, sizeof(buf));
      cf.bitratetx = strtoul(buf, NULL, 0);
      GetDlgItemText(hDlg, IDC_TXDELAY, buf, sizeof(buf));
      servant->cfg.chacc.txdelay = strtoul(buf, NULL, 0);
      servant->cfg.chacc.fulldup = IsDlgButtonChecked(hDlg, IDC_FULLDUPLEX) == BST_CHECKED;
      cf.pttmute = IsDlgButtonChecked(hDlg, IDC_PTTMUTE) == BST_CHECKED;
      if (checkreload_adapt(servant, &cf))
                servant->flags |= FLG_RELOADMODEM;
      servant->cfg.adapt = cf;
      servant->flags |= FLG_SAVECONFIG;
      win32shmem_close(api);
      return restart;
}

static BOOL CALLBACK EdParmDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
      struct trxapi *api;
      const struct trxapi_description *desc;
        HWND hcombo;
      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;
            for (index = 0, i = 1;; index++) {
                  if (!(api = win32shmem_open_byindex(index)))
                        break;
                  desc = win32shmem_get_description(api);
                  if (desc) {
                        SendMessage(hcombo, CB_ADDSTRING, 0, (LPARAM)desc->instid);
                        if (!strcmp(desc->instid, state.serial))
                              cursel = i;
                        i++;
                  }
                        win32shmem_close(api);
                }
            ComboBox_SetCurSel(hcombo, cursel);
            SetWindowText(hDlg, DRIVER_NAME" Configuration");
            setdlgitems(hDlg);
            break;
                
        case WM_COMMAND:
                switch (GET_WM_COMMAND_ID(wParam, lParam)) {
                case IDCANCEL:
                        EndDialog(hDlg, 0);
                        break;

                case IDOK:
                  restart = getdlgitems(hDlg);
                  EndDialog(hDlg, restart);
                        break;
                        
            case IDC_SERIAL:
                  setdlgitems(hDlg);
                  break;

            case IDC_FULLDUPLEX:
            case IDC_PTTMUTE:
                    if (GET_WM_COMMAND_CMD(wParam, lParam) != BN_CLICKED)
                        break;
                  switch (IsDlgButtonChecked(hDlg, GET_WM_COMMAND_ID(wParam, lParam))) {
                  case BST_CHECKED:
                        CheckDlgButton(hDlg, GET_WM_COMMAND_ID(wParam, lParam), BST_UNCHECKED);
                        break;

                  case BST_UNCHECKED:
                        CheckDlgButton(hDlg, GET_WM_COMMAND_ID(wParam, lParam), BST_CHECKED);
                        break;
                  }
                  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)
            api_close();
      return restart;
}

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

u16 l1_get_ch_cnt(void)
{
      return 1;
}

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

byte get_txdelay(byte kanal)
{
      struct trx_thread_state *servant;
      byte ret = 0;

      if (kanal)
            return 0;
      servant = api_lock();
      if (!servant)
            return 0;
      ret = servant->cfg.chacc.txdelay / 10;
      api_unlock();
      return ret;
}

void set_txdelay(byte kanal, byte delay)
{
      struct trx_thread_state *servant;

      if (kanal)
            return;
      servant = api_lock();
      if (!servant)
            return;
      servant = state.api->state;
      win32shmem_lock(state.api);
      servant->cfg.chacc.txdelay = delay * 10;
      servant->flags |= FLG_SAVECONFIG;
      win32shmem_unlock(state.api);
      api_unlock();
}

u16 get_mode(byte kanal)
{
      struct trx_thread_state *servant;
      u16 ret = state.mode & ~MODE_d;

      if (kanal)
            return 0;
      servant = api_lock();
      if (!servant)
            return ret;
      if (servant->cfg.chacc.fulldup)
            ret |= MODE_d;
      api_unlock();
      return ret;
}

u16 get_baud(byte kanal)
{
      struct trx_thread_state *servant;
      u16 ret = 0;

      if (kanal)
            return 0;
      servant = api_lock();
      if (!servant)
            return 0;
      ret = servant->cfg.adapt.bitratetx / 100;
      api_unlock();
      return ret;
}

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

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

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

byte l1_ch_active(byte kanal)
{
      return state.api != NULL;
}

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

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)
{
        struct trx_thread_state *servant;

      if (!(servant = api_lock()))
            return;
      win32shmem_lock(state.api);
      servant->leds = ((ledcode & LED_CON) ? 1 : 0) | ((ledcode & LED_STA) ? 2 : 0);
      servant->flags |= FLG_SETLEDS;
      win32shmem_unlock(state.api);
      api_unlock();
}

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

/*
 * state and servant must be locked!
 */

static unsigned int compute_state(struct trx_thread_state *servant, unsigned int *nextrx, unsigned int *nexttx)
{
      unsigned int nrtx = 0, nrrx = 0, nxttx, nxtrx, i;
      unsigned int st = 0;

      if (servant->mode != MODE_FSK && servant->mode != MODE_EXTERNAL && servant->mode != MODE_AFSK)
            goto nopkt;
      /* find tx packet */
      for (i = 0; i < NUMTXPACKETS; i++) {
            if (servant->du.p.txurb[i].urbstate == URBSTATE_UNUSED) {
                  if (!nrtx)
                        nxttx = i;
                  nrtx++;
                  continue;
            }
            if (servant->du.p.txurb[i].urbstate == URBSTATE_FILLED) {
                  nrtx = 0;
                  continue;
            }
      }
      /* find rx packet */
      i = servant->du.p.rxurbptr;
      do {
            if (servant->du.p.rxurb[i].urbstate == URBSTATE_CORBASEND)
                  servant->du.p.rxurb[i].urbstate = URBSTATE_UNUSED;
            /* stop at INPROGRESS urbs */
            if (servant->du.p.rxurb[i].urbstate == URBSTATE_DONE) {
                  if (!nrrx)
                        nxtrx = i;
                  nrrx++;
            } else if (servant->du.p.rxurb[i].urbstate != URBSTATE_UNUSED)
                  break;
            i = (i + 1) % NUMRXPACKETS;
      } while (i != servant->du.p.rxurbptr);
  nopkt:
      if (!nrrx)
            nxtrx = ~0;
      if (!nrtx)
            nxttx = ~0;
      if (nextrx)
            *nextrx = nxtrx;
      if (nexttx)
            *nexttx = nxttx;
      /* update status */
      if (servant->ptt)
            st |= CH_PTT;
      if (servant->dcd)
            st |= CH_DCD;
      if (nrrx > 0)
            st |= CH_RXB;
      if (!nrtx)
            st |= CH_TBY;
      return st;
}

byte l1_ch_state(byte kanal)
{
        struct trx_thread_state *servant;
      byte ret;

      if (kanal)
            return CH_DEAD;
      if (!(servant = api_lock()))
            return CH_DEAD;
      win32shmem_lock(state.api);
      ret = compute_state(servant, NULL, NULL);
      win32shmem_unlock(state.api);
      api_unlock();
      return ret;
}

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

u16 l1_scale(byte kanal)
{
      struct trx_thread_state *servant;
      unsigned long br;
      u16 ret = 0;

      if (kanal)
            return 0;
      if (!(servant = api_lock()))
            return 0;
      win32shmem_lock(state.api);
      br = servant->cfg.adapt.bitratetx;
      if (br >= 10)
            ret = 614400 / br;
      win32shmem_unlock(state.api);
      api_unlock();
      return ret;
}

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

static void CALLBACK stopcalib(HWND hwnd, UINT umsg, UINT idevent, DWORD dwtime)
{
      if (!api_lock())
            return;
      win32shmem_set_ptt(state.api, 0);
      api_unlock();
}

void l1_tx_calib(byte kanal, byte minutes)
{
      if (state.calibtimer)
            KillTimer(NULL, state.calibtimer);
      if (!api_lock())
            return;
      if (win32shmem_set_ptt(state.api, 1)) {
            state.calibtimer = SetTimer(NULL, 0, minutes * 60000, stopcalib);
            if (!state.calibtimer)
                  stopcalib(NULL, 0, 0, 0);
      }
      api_unlock();
}


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

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

byte l1_tx_frame(void)
{
      struct trx_thread_state *servant;
        unsigned int i, txd;

      if (!(servant = api_lock())) {
            state.stat.io_error++;
            return 1;
      }
      win32shmem_lock(state.api);
      compute_state(servant, NULL, &i);
      if (i >= NUMTXPACKETS)
            goto errpkt;
      if (servant->mode != MODE_FSK && servant->mode != MODE_EXTERNAL && servant->mode != MODE_AFSK)
            goto errio;
      if (state.txframe.len > sizeof(servant->du.p.txurb[i].b)-2)
            goto errio;
      txd = state.txframe.txdelay;
      if (!txd)
            txd = servant->cfg.chacc.txdelay / 10;
      txd *= servant->txdmul;
        if (!txd)
                txd = 1;
        servant->du.p.txurb[i].urb.buffer_length = state.txframe.len + 2;
      memcpy(&servant->du.p.txurb[i].b.buf[2], state.txframe.frame, state.txframe.len);
      servant->du.p.txurb[i].b.buf[0] = txd;
      servant->du.p.txurb[i].b.buf[1] = txd >> 8;
        servant->du.p.txurb[i].urbstate = URBSTATE_FILLED;
      win32shmem_unlock(state.api);
      win32shmem_wakeup(state.api);
      api_unlock();
      state.stat.tx_frames++;
      return 1;

  errio:
      win32shmem_unlock(state.api);
      api_unlock();
      state.stat.io_error++;
      return 1;

  errpkt:
      win32shmem_unlock(state.api);
      api_unlock();
      return 0;
}

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

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

L1FRAME far *l1_rx_frame(void)
{
      struct trx_thread_state *servant;
      unsigned int i;
      L1FRAME *rxframe;

      if (!(servant = api_lock()))
            return NULL;
      while (!(state.apiflags & (APIFLG_TERMINATE|APIFLG_CLOSE))) {
            win32shmem_lock(state.api);
            compute_state(servant, &i, NULL);
            if (i < NUMRXPACKETS) {
                  rxframe = &servant->du.p.rxurb[i].b.frame;
                  rxframe->kanal = 0;
                  rxframe->txdelay = 0;
                  rxframe->len = servant->du.p.rxurb[i].urb.actual_length-2;
                  servant->du.p.rxurb[i].urbstate = URBSTATE_CORBASEND;
                  win32shmem_unlock(state.api);
                  api_unlock();
                  return rxframe;
            }
            win32shmem_unlock(state.api);
            WaitForSingleObject(state.api->hflxrxevent, 10);
      }
      api_unlock();
      return NULL;
}

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

Generated by  Doxygen 1.6.0   Back to index