USBUART
A library for reading/wring data via USB-UART adapters
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules
uartcat.cpp
Go to the documentation of this file.
1 
5 /* This file is part of USBUART Library. http://hutorny.in.ua/projects/usbuart
6  *
7  * Copyright (C) 2016 Eugene Hutorny <eugene@hutorny.in.ua>
8  *
9  * The USBUART Library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License v2
11  * as published by the Free Software Foundation;
12  *
13  * The USBUART Library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with the USBUART Library; if not, see
20  * <http://www.gnu.org/licenses/gpl-2.0.html>.
21  */
22 
23 #include <cstdio>
24 #include <cstring>
25 #include <chrono>
26 #include <signal.h>
27 #include <unistd.h>
28 #include <stdlib.h>
29 #include "usbuart.h"
30 
31 static bool terminated = false;
32 
33 static void doexit(int signal) {
34  terminated = true;
35 }
36 
37 void show_err(int err) {
38  fprintf(stderr,"err(%d)==%s\n", err, strerror(err));
39 }
40 using namespace usbuart;
41 using namespace std::chrono;
42 
43 static inline bool is_good(int status) noexcept {
44  return status == status_t::alles_gute;
45 }
46 
47 static inline bool is_usable(int status) noexcept {
48  return status == (status_t::usb_dev_ok | status_t::read_pipe_ok) ||
49  status == (status_t::usb_dev_ok | status_t::write_pipe_ok) ||
50  status == status_t::alles_gute;
51 }
52 
53 //TODO add options 'keep running with read pipe' 'keep running with write pipe'
54 //TODO add option for (not-) printing elapsed milliseconds
55 //TODO option to disable canonical terminal mode
56 int main(int argc, char** argv) {
57  channel chnl {0, 1};
58  device_addr addr;
59  device_id devid;
60  const char* dlm, *ifc;
61  long a, b, c = 0;
62 
63 // fprintf(stderr,"err(84)==%s\n", strerror(84));
64 
65  if( argc < 2 ) {
66  fprintf(stderr,"device address (e.g. 001/002) "
67  "or device id (e.g. a123:456b) is missing\n");
68  return -1;
69  }
70  dlm = strchr(argv[1], '/');
71  if( ! dlm )
72  dlm = strchr(argv[1], ':');
73  if( ! dlm ) {
74  fprintf(stderr,"Invalid argument '%s', expected something like\n"
75  "001/002, 001/002:1, a123:456b or a123:456b:a \n", argv[1]);
76  return -1;
77  }
78  ifc = strchr(dlm+1,':');
79  a = strtoul(argv[1],NULL,*dlm == ':' ? 16 : 10);
80  b = strtoul(dlm+1,NULL,*dlm == ':' ? 16 : 10);
81  if( ifc ) c = strtoul(ifc+1,NULL, *dlm == ':' ? 16 : 10);
82  addr.busid = a;
83  addr.devid = b;
84  addr.ifc = c;
85  devid.vid = a;
86  devid.pid = b;
87  devid.ifc = c;
88 
89  context::setloglevel(loglevel_t::debug);
90 
91  context ctx;
92 
93  int res, status = 0;
94 
95  if( *dlm == ':' ) {
96  res = ctx.attach(devid, chnl, _115200_8N1n);
97  if( res ) {
98  fprintf(stderr,"Error %d attaching device %04x:%04x:%x\n",
99  -res, devid.vid, devid.pid, devid.ifc);
100  return -res;
101  }
102  } else {
103  res = ctx.attach(addr, chnl, _115200_8N1n);
104  if( res ) {
105  fprintf(stderr,"Error %d attaching device %03d/%03d:%d\n",
106  -res, addr.busid, addr.devid, addr.ifc);
107  return -res;
108  }
109  }
110 
111  signal(SIGINT, doexit);
112  signal(SIGQUIT, doexit);
113 
114  int count_down = 4;
115  int timeout = 1; //500;
116  steady_clock::time_point started = std::chrono::steady_clock::now();
117 
118  while(!terminated && (res=ctx.loop(timeout)) >= -error_t::no_channel) {
119  if( ! is_usable(status = ctx.status(chnl)) ) break;
120  if( res == -error_t::no_channel || ! is_good(status) ) {
121  timeout = 100;
122  if( --count_down <= 0 ) break;
123  }
124  fsync(1);
125  }
126  milliseconds elapsed = duration_cast<milliseconds>(steady_clock::now() - started);
127  fprintf(stderr,"elapsed %lld ms\n", elapsed.count());
128 
129  fprintf(stderr,"status %d res %d\n", status, res);
130  ctx.close(chnl);
131  ctx.loop(100);
132  if( res < -error_t::no_channel ) {
133  fprintf(stderr,"Terminated with error %d\n",-res);
134  } else
135  res = 0;
136 
137  signal(SIGINT, SIG_DFL);
138  signal(SIGQUIT, SIG_DFL);
139  return res;
140 }
static loglevel_t setloglevel(loglevel_t lvl) noexcept
Set logging level.
Definition: core.cpp:1026
void close(channel) noexcept
Close channel, detaches files from USB device.
Definition: core.cpp:955
uint8_t ifc
Interface number.
Definition: usbuart.h:87
Device address in terms bus ID, device number.
Definition: usbuart.h:84
API header for USBUART Library.
uint16_t vid
Vendor ID.
Definition: usbuart.h:92
uint16_t pid
Product ID.
Definition: usbuart.h:93
I/O channel, represented by a pair of file descriptors.
Definition: usbuart.h:70
int loop(int timeout) noexcept
Run libusb and async I/O message loops.
Definition: core.cpp:996
uint8_t devid
Device Number.
Definition: usbuart.h:86
USBUART namespace.
Definition: usbuart.h:29
Device ID (Vendor ID/Product ID).
Definition: usbuart.h:91
USBUART API facade class.
Definition: usbuart.h:226
requested channel does not exist
int attach(device_id id, channel ch, const eia_tia_232_info &pi) noexcept
Attach pair of file descriptors to the USB device using VID/PID.
Definition: core.cpp:935
uint8_t ifc
Interface number.
Definition: usbuart.h:94
uint8_t busid
USB Bus ID.
Definition: usbuart.h:85
int status(channel) noexcept
Returns combination of status_t bit or negative on error.
Definition: core.cpp:975