Ejemplo n.º 1
0
static int df10ch_control_in_transfer(df10ch_ctrl_t *ctrl, uint8_t req, uint16_t val, uint16_t index, unsigned int timeout, uint8_t *buf, uint16_t buflen) {
    // Use a return buffer always so that the controller is able to send a USB reply status
    // This is special for VUSB at controller side
  unsigned char rcbuf[1];
  int len = buflen;
  int n = 0, retrys = 0;

  if (!len) {
      buf = rcbuf;
      len = 1;
  }

    // Because VUSB at controller sends ACK reply before CRC check of received data we have to retry sending request our self if data is corrupted
  while (retrys < 3) {
      n = libusb_control_transfer(ctrl->dev, LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, req, val, index, buf, len, timeout);
      if (n != LIBUSB_ERROR_INTERRUPTED)
      {
          if (n < 0)
            ++ctrl->driver->transfer_err_cnt;
          if (n >= 0 || n != LIBUSB_ERROR_PIPE)
              break;
          ++retrys;
          DFATMO_LOG(DFLOG_ERROR, "%s: sending USB control transfer message %d failed (pipe error): retry %d", ctrl->id, req, retrys);
      }
  }

  if (n < 0) {
      DFATMO_LOG(DFLOG_ERROR, "%s: sending USB control transfer message %d failed: %s", ctrl->id, req, libusb_strerror(n));
      return -1;
  }

  if (n != buflen) {
      DFATMO_LOG(DFLOG_ERROR, "%s: sending USB control transfer message %d failed: read %d bytes but expected %d bytes", ctrl->id, req, n, buflen);
      return -1;
  }

  return 0;
}
Ejemplo n.º 2
0
static int serial_driver_open(output_driver_t *this_gen, atmo_parameters_t *p) {
  serial_output_driver_t *this = (serial_output_driver_t *) this_gen;
  const char *devname = NULL;
  const char *usb = NULL;
  const char *speed = NULL;
  char *t, *tp;
  char buf[256];
  dev_handle_t devfd;
  dev_speed_t bspeed;
  int ok;

  this->param = *p;
  this->devfd = INVALID_DEV_HANDLE;
  this->protocol = classic_proto;

  /* parse driver parameter */
  strncpy(this->driver_param, this->param.driver_param, sizeof(this->driver_param));
  t = strtok_r(this->driver_param, ";&", &tp);
  while (t != NULL) {
    char *v = strchr(t, ':');
    if (v == NULL)
      devname = t;
    else {
      *v++ = 0;
      if (!strcmp(t, "speed")) {
        speed = v;
      } else if (!strcmp(t, "proto")) {
        if (!strcmp(v, "classic"))
          this->protocol = classic_proto;
        else if (!strcmp(v, "df4ch"))
          this->protocol = df4ch_proto;
        else if (!strcmp(v, "amblone"))
          this->protocol = amblone_proto;
        else if (!strcmp(v, "karatelight"))
          this->protocol = karate_proto;
        else
          this->protocol = v;
      } else if (!strcmp(t, "amblone")) {
          this->escapes = amblone_escapes;
#ifndef WIN32
      } else if (!strcmp(t, "usb")) {
        usb = v;
#endif
      } else {
        snprintf(this->output_driver.errmsg, sizeof(this->output_driver.errmsg), "keyword '%s' unknown", t);
        return -1;
      }
    }
    t = strtok_r(NULL, ";&", &tp);
  }

  if (usb == NULL && (devname == NULL || strspn(devname, " ") == strlen(devname)))
    devname = DEFAULT_PORT;

#ifndef WIN32
  char buf1[64];
  if (usb != NULL) {
    /* Lookup serial USB device name */
    regex_t preg;
    devname = NULL;

    int rc = regcomp(&preg, usb, REG_EXTENDED | REG_NOSUB);
    if (rc) {
      regerror(rc, &preg, buf, sizeof(buf));
      snprintf(this->output_driver.errmsg, sizeof(this->output_driver.errmsg), "illegal device identification pattern '%s': %s", usb, buf);
      regfree(&preg);
      return -1;
    }

    FILE *procfd = fopen("/proc/tty/driver/usbserial", "r");
    if (!procfd) {
      strerror_r(errno, buf, sizeof(buf));
      snprintf(this->output_driver.errmsg, sizeof(this->output_driver.errmsg), "could not open '/proc/tty/driver/usbserial': %s", buf);
      regfree(&preg);
      return -1;
    }

    while (fgets(buf, sizeof(buf), procfd)) {
      char *s;
      if (!regexec(&preg, buf, 0, NULL, 0) && (s = index(buf, ':'))) {
        *s = 0;
        snprintf(buf1, sizeof(buf1), "/dev/ttyUSB%s", buf);
        devname = buf1;
        break;
      }
    }
    fclose(procfd);
    regfree(&preg);
    if (!devname) {
      snprintf(this->output_driver.errmsg, sizeof(this->output_driver.errmsg), "could not find usb device with pattern '%s' in '/proc/tty/driver/usbserial'", usb);
      return -1;
    }
  }
#endif

  DFATMO_LOG(DFLOG_INFO, "serial port device: '%s'", devname);

    /* open serial port device */
  devfd = OPEN_DEVICE(devname);
  if (devfd == INVALID_DEV_HANDLE) {
    GET_SYS_ERR_MSG(buf);
    snprintf(this->output_driver.errmsg, sizeof(this->output_driver.errmsg), "could not open serial port device '%s': %s", devname, buf);
    return -1;
  }

    /* configure serial port */
  bspeed = SPEED_CONST(38400);
  if (speed == NULL)
    speed = "38400";
  else {
    switch (atoi(speed)) {
    case 1200:
      bspeed = SPEED_CONST(1200);
      break;
    case 2400:
      bspeed = SPEED_CONST(2400);
      break;
    case 4800:
      bspeed = SPEED_CONST(4800);
      break;
    case 9600:
      bspeed = SPEED_CONST(9600);
      break;
    case 19200:
      bspeed = SPEED_CONST(19200);
      break;
    case 38400:
      bspeed = SPEED_CONST(38400);
      break;
    case 57600:
      bspeed = SPEED_CONST(57600);
      break;
    case 115200:
      bspeed = SPEED_CONST(115200);
      break;
#ifdef WIN32
    case 128000:
      bspeed = SPEED_CONST(128000);
      break;
    case 256000:
      bspeed = SPEED_CONST(256000);
      break;
#else
    case 230400:
      bspeed = SPEED_CONST(230400);
      break;
    case 460800:
      bspeed = SPEED_CONST(460800);
      break;
    case 500000:
      bspeed = SPEED_CONST(500000);
      break;
    case 576000:
      bspeed = SPEED_CONST(576000);
      break;
    case 921600:
      bspeed = SPEED_CONST(921600);
      break;
    case 1000000:
      bspeed = SPEED_CONST(1000000);
      break;
    case 1152000:
      bspeed = SPEED_CONST(1152000);
      break;
    case 1500000:
      bspeed = SPEED_CONST(1500000);
      break;
    case 2000000:
      bspeed = SPEED_CONST(2000000);
      break;
    case 2500000:
      bspeed = SPEED_CONST(2500000);
      break;
    case 3000000:
      bspeed = SPEED_CONST(3000000);
      break;
    case 3500000:
      bspeed = SPEED_CONST(3500000);
      break;
    case 4000000:
      bspeed = SPEED_CONST(4000000);
      break;
#endif
    default:
      snprintf(this->output_driver.errmsg, sizeof(this->output_driver.errmsg), "serial port device speed '%s' unsupported", speed);
      return -1;
    }
  }

  DFATMO_LOG(DFLOG_INFO, "serial port speed: %s", speed);

#ifdef WIN32
  {
    DCB dcbSerialParams = {0};
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);

    ok = GetCommState(devfd, &dcbSerialParams);
    if (ok) {
      dcbSerialParams.BaudRate = bspeed;
      dcbSerialParams.ByteSize = 8;
      dcbSerialParams.StopBits = TWOSTOPBITS;
      dcbSerialParams.Parity = NOPARITY;
      ok = SetCommState(devfd, &dcbSerialParams);
    }
  }
#else
  struct termios tio;
  memset(&tio, 0, sizeof(tio));
  tio.c_cflag = (CS8 | CSTOPB | CLOCAL);
  cfsetospeed(&tio, bspeed);
  ok = (tcsetattr(devfd, TCSANOW, &tio) == 0);
  if (ok)
    tcflush(devfd, TCIOFLUSH);
#endif
  if (!ok) {
    GET_SYS_ERR_MSG(buf);
    snprintf(this->output_driver.errmsg, sizeof(this->output_driver.errmsg), "configuration of serial port device '%s' failed: %s", devname, buf);
    CLOSE_DEVICE(devfd);
    return -1;
  }

  this->devfd = devfd;
  return 0;
}