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