USBUART
A library for reading/wring data via USB-UART adapters
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules
pl2303.cpp
Go to the documentation of this file.
1 
5 /* This file is part of USBUART Library. http://usbuart.info/
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 <libusb.h>
24 #include <endian.h>
25 #include "usbuart.hpp"
26 
27 namespace usbuart {
28 
29 class pl2303 : public generic {
30 public:
31  static const struct interface _ifc;
32 
33  struct pl2303_protocol_setup {
34  uint32_t baudrate_le;/* little endian baud rate */
35  uint8_t stopbits; /* straight value of eia_tia_232_info.stopbits */
36  uint8_t parity; /* straight value of eia_tia_232_info.parity */
37  uint8_t databits; /* straight value of eia_tia_232_info.databits */
38  } __attribute__((packed));
39 
40  static_assert(sizeof(pl2303_protocol_setup)==7,"pl2303_protocol_setup misaligned");
41 
42  static constexpr uint8_t init_rq = 0x01;
43  static constexpr uint8_t get_protocol_rqt = 0xa1;
44  static constexpr uint8_t get_protocol_req = 0x21;
45  static constexpr uint8_t set_protocol_rqt = 0x21;
46  static constexpr uint8_t set_protocol_req = 0x20;
47  static constexpr uint8_t break_rqtype = 0x21;
48  static constexpr uint8_t break_request = 0x23;
49 
56  static constexpr uint8_t reset_rd_req = 0x08;
57  static constexpr uint8_t reset_wr_req = 0x09;
58 
59  size_t chunksize() const noexcept { return 256; }
60 
61  inline pl2303(libusb_device_handle* d, uint8_t num) throw(error_t)
62  : generic(d, _ifc, num) {}
63 
64  void probe() const throw(error_t) {
65  uint8_t ignr;
66  read_cv (init_rq, 0x8484, ignr);
67  write_cv(init_rq, 0x0404, 0);
68  read_cv (init_rq, 0x8484, ignr);
69  read_cv (init_rq, 0x8383, ignr);
70  read_cv (init_rq, 0x8484, ignr);
71  write_cv(init_rq, 0x0404, 1);
72  read_cv (init_rq, 0x8484, ignr);
73  read_cv (init_rq, 0x8383, ignr);
74  write_cv(init_rq, 0x0000, 1);
75  write_cv(init_rq, 0x0001, 0);
76  //TODO (ifc.chip == chip::legacy )? (r = write(request, 2, 0x24)) :
77  write_cv(init_rq, 2, 0x44);
78  }
79  void setbaudrate(baudrate_t baudrate) const throw(error_t) {
80  pl2303_protocol_setup setup;
81  control(get_protocol_rqt, get_protocol_req, &setup, sizeof(setup));
82  setup.baudrate_le = htole32(baudrate);
83  control(set_protocol_rqt, set_protocol_req, &setup, sizeof(setup));
84  }
85  void setup(const eia_tia_232_info& info) const throw(error_t) {
86  pl2303_protocol_setup setup;
87 
88  setup.baudrate_le = htole32(info.baudrate);
89  setup.databits = info.databits;
90  setup.parity = info.parity;
91  setup.stopbits = info.stopbits;
92 
93  log.i(__,"protocol {%d,%d,%d,%d}",setup.baudrate_le,
94  setup.databits, setup.parity, setup.stopbits);
95  control(set_protocol_rqt, set_protocol_req, &setup, sizeof(setup));
96  reset();
98  }
99  void sendbreak() const throw(error_t) {
100  control(break_rqtype, break_request, nullptr, 0);
101  }
102  void reset() const throw(error_t) {
103  /* no documented reset sequence */
104  }
105 
106  static inline bool devid(libusb_device_handle* handle, device_id& did);
107 
108  static class factory : driver::factory {
109  void probe(libusb_device_handle*,uint8_t) const throw(error_t);
110  driver* create(libusb_device_handle*, uint8_t) const throw(error_t);
111  } _factory;
112 
113 };
114 
115 class pl2303hx : public pl2303 {
116 public:
117  inline pl2303hx(libusb_device_handle* d, uint8_t num) throw(error_t)
118  : pl2303(d, num) {}
119  void reset() const throw(error_t) {
120  write_cv(reset_rd_req, 0, 0);
121  write_cv(reset_wr_req, 0, 0);
122  }
123 };
124 
125 
126 const struct interface pl2303::_ifc = {
127  0x3|LIBUSB_ENDPOINT_IN,
128  0x2|LIBUSB_ENDPOINT_OUT,
129  256
130 };
131 
132 pl2303::factory pl2303::_factory;
133 
134 void pl2303::factory::probe(libusb_device_handle* h,
135  uint8_t num) const throw(error_t) {
136  pl2303 driver(h, num);
137  driver.probe();
138 }
139 
140 inline bool pl2303::devid(libusb_device_handle* handle, device_id& did) {
141  libusb_device* dev = libusb_get_device(handle);
142  libusb_device_descriptor desc;
143  if( libusb_get_device_descriptor(dev, &desc) < 0 ) return false;
144  did.vid = desc.idVendor;
145  did.pid = desc.idProduct;
146  return
147  desc.bDeviceClass != 0x00 && desc.bDeviceClass != 0x02 &&
148  desc.bDeviceClass != 0xFF && desc.bMaxPacketSize0 == 0x40;
149 }
150 
151 
152 driver* pl2303::factory::create(libusb_device_handle* handle, uint8_t num)
153  const throw(error_t) {
154  static constexpr const uint32_t table[] = {
155  #include "pl2303.inc"
156  };
157  device_id did = { 0, 0, 0};
158  bool hx = pl2303::devid(handle, did);
159  uint32_t id = devid32(did);
160  if( ! id ) return nullptr;
161  bool found = false;
162  for(auto&& i : table) {
163  if( (found = (i == id)) )
164  break;
165  }
166  if( ! found ) return nullptr;
167  log.i(__,"probing %s for %04x:%04x", "pl2303", did.vid, did.pid);
168  try { probe(handle, num); }
169  catch(error_t err) {
170  log.i(__,"probe %s error %d for %04x:%04x",
171  "pl2303", +err, did.vid, did.pid);
172  throw err;
173  }
174  return hx ? new pl2303hx(handle, num) : new pl2303(handle, num);
175 }
176 
177 } /* namespace usbuart */
uint32_t baudrate_t
Baud rate data type.
Definition: usbuart.h:35
virtual void setbaudrate(baudrate_t) const =0
set baud rate only, keep other protocol properties intact
implementation header USBUART Library
void setup(const eia_tia_232_info &) const
setup protocol on the hardware level
Definition: usbuart.hpp:143
USBUART namespace.
Definition: usbuart.h:29
void sendbreak() const
Send break.
Definition: usbuart.hpp:134
error_t
API Error codes.
Definition: usbuart.h:177
void reset() const
set baud rate only, keep other protocol properties intact
Definition: usbuart.hpp:135