Commit | Line | Data |
---|---|---|
20b1459a TJ |
1 | #include "ftdi.hpp" |
2 | #include "ftdi.h" | |
3 | ||
4 | namespace Ftdi | |
5 | { | |
6 | ||
7 | class Context::Private | |
8 | { | |
9 | public: | |
10 | Private() | |
11 | : ftdi(0), dev(0), open(false) | |
12 | {} | |
13 | ||
14 | bool open; | |
15 | ||
16 | struct ftdi_context* ftdi; | |
17 | struct usb_device* dev; | |
18 | ||
19 | std::string vendor; | |
20 | std::string description; | |
21 | std::string serial; | |
22 | }; | |
23 | ||
24 | /*! \brief Constructor. | |
25 | */ | |
26 | Context::Context() | |
27 | : d( new Private() ) | |
28 | { | |
29 | d->ftdi = ftdi_new(); | |
30 | } | |
31 | ||
32 | /*! \brief Destructor. | |
33 | */ | |
34 | Context::~Context() | |
35 | { | |
36 | if(d->open) | |
37 | close(); | |
38 | ||
39 | ftdi_free(d->ftdi); | |
40 | delete d; | |
41 | } | |
42 | ||
43 | bool Context::is_open() | |
44 | { | |
45 | return d->open; | |
46 | } | |
47 | ||
48 | int Context::open(int vendor, int product, const std::string& description, const std::string& serial) | |
49 | { | |
50 | int ret = 0; | |
51 | if(description.empty() && serial.empty()) | |
52 | ret = ftdi_usb_open(d->ftdi, vendor, product); | |
53 | else | |
54 | ret = ftdi_usb_open_desc(d->ftdi, vendor, product, description.c_str(), serial.c_str()); | |
55 | ||
56 | d->dev = usb_device(d->ftdi->usb_dev); | |
57 | ||
58 | if((ret = ftdi_usb_open_dev(d->ftdi, d->dev)) >= 0) | |
59 | { | |
60 | d->open = true; | |
61 | get_strings(); | |
62 | } | |
63 | ||
64 | return ret; | |
65 | } | |
66 | ||
67 | int Context::open(struct usb_device *dev) | |
68 | { | |
69 | int ret = 0; | |
70 | ||
71 | if(dev != 0) | |
72 | d->dev = dev; | |
73 | ||
74 | if(d->dev == 0) | |
75 | return -1; | |
76 | ||
77 | if((ret = ftdi_usb_open_dev(d->ftdi, d->dev)) >= 0) | |
78 | { | |
79 | d->open = true; | |
80 | get_strings(); | |
81 | } | |
82 | ||
83 | return ret; | |
84 | } | |
85 | ||
86 | int Context::close() | |
87 | { | |
88 | d->open = false; | |
89 | return ftdi_usb_close(d->ftdi); | |
90 | } | |
91 | ||
92 | int Context::reset() | |
93 | { | |
94 | return ftdi_usb_reset(d->ftdi); | |
95 | } | |
96 | ||
97 | int Context::flush(int mask) | |
98 | { | |
99 | int ret = 1; | |
100 | if(mask & Input) | |
101 | ret &= ftdi_usb_purge_rx_buffer(d->ftdi); | |
102 | if(mask & Output) | |
103 | ret &= ftdi_usb_purge_tx_buffer(d->ftdi); | |
104 | ||
105 | return ret; | |
106 | } | |
107 | ||
108 | int Context::set_interface(enum ftdi_interface interface) | |
109 | { | |
110 | return ftdi_set_interface(d->ftdi, interface); | |
111 | } | |
112 | ||
113 | void Context::set_usb_device(struct usb_dev_handle *dev) | |
114 | { | |
115 | ftdi_set_usbdev(d->ftdi, dev); | |
116 | d->dev = usb_device(dev); | |
117 | } | |
118 | ||
119 | int Context::set_baud_rate(int baudrate) | |
120 | { | |
121 | return ftdi_set_baudrate(d->ftdi, baudrate); | |
122 | } | |
123 | ||
124 | int Context::set_line_property(enum ftdi_bits_type bits, enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity) | |
125 | { | |
126 | return ftdi_set_line_property(d->ftdi, bits, sbit, parity); | |
127 | } | |
128 | ||
129 | int Context::set_line_property(enum ftdi_bits_type bits, enum ftdi_stopbits_type sbit, enum ftdi_parity_type parity, enum ftdi_break_type break_type) | |
130 | { | |
131 | return ftdi_set_line_property2(d->ftdi, bits, sbit, parity, break_type); | |
132 | } | |
133 | ||
134 | int Context::read(unsigned char *buf, int size) | |
135 | { | |
136 | return ftdi_read_data(d->ftdi, buf, size); | |
137 | } | |
138 | ||
139 | int Context::set_read_chunk_size(unsigned int chunksize) | |
140 | { | |
141 | return ftdi_read_data_set_chunksize(d->ftdi, chunksize); | |
142 | } | |
143 | ||
144 | int Context::read_chunk_size() | |
145 | { | |
146 | unsigned chunk = -1; | |
147 | if(ftdi_read_data_get_chunksize(d->ftdi, &chunk) < 0) | |
148 | return -1; | |
149 | ||
150 | return chunk; | |
151 | } | |
152 | ||
153 | ||
154 | int Context::write(unsigned char *buf, int size) | |
155 | { | |
156 | return ftdi_write_data(d->ftdi, buf, size); | |
157 | } | |
158 | ||
159 | int Context::set_write_chunk_size(unsigned int chunksize) | |
160 | { | |
161 | return ftdi_write_data_set_chunksize(d->ftdi, chunksize); | |
162 | } | |
163 | ||
164 | int Context::write_chunk_size() | |
165 | { | |
166 | unsigned chunk = -1; | |
167 | if(ftdi_write_data_get_chunksize(d->ftdi, &chunk) < 0) | |
168 | return -1; | |
169 | ||
170 | return chunk; | |
171 | } | |
172 | ||
173 | int Context::set_flow_control(int flowctrl) | |
174 | { | |
175 | return ftdi_setflowctrl(d->ftdi, flowctrl); | |
176 | } | |
177 | ||
178 | int Context::set_modem_control(int mask) | |
179 | { | |
180 | int dtr = 0, rts = 0; | |
181 | ||
182 | if(mask & Dtr) | |
183 | dtr = 1; | |
184 | if(mask & Rts) | |
185 | rts = 1; | |
186 | ||
187 | return ftdi_setdtr_rts(d->ftdi, dtr, rts); | |
188 | } | |
189 | ||
190 | int Context::set_dtr(bool state) | |
191 | { | |
192 | return ftdi_setdtr(d->ftdi, state); | |
193 | } | |
194 | ||
195 | int Context::set_rts(bool state) | |
196 | { | |
197 | return ftdi_setrts(d->ftdi, state); | |
198 | } | |
199 | ||
200 | int Context::set_latency(unsigned char latency) | |
201 | { | |
202 | return ftdi_set_latency_timer(d->ftdi, latency); | |
203 | } | |
204 | ||
205 | unsigned Context::latency() | |
206 | { | |
207 | unsigned char latency = 0; | |
208 | ftdi_get_latency_timer(d->ftdi, &latency); | |
209 | return latency; | |
210 | } | |
211 | ||
212 | unsigned short Context::poll_modem_status() | |
213 | { | |
214 | unsigned short status = 0; | |
215 | ftdi_poll_modem_status(d->ftdi, &status); | |
216 | return status; | |
217 | } | |
218 | ||
219 | ||
220 | int Context::set_event_char(unsigned char eventch, unsigned char enable) | |
221 | { | |
222 | return ftdi_set_event_char(d->ftdi, eventch, enable); | |
223 | } | |
224 | ||
225 | int Context::set_error_char(unsigned char errorch, unsigned char enable) | |
226 | { | |
227 | return ftdi_set_error_char(d->ftdi, errorch, enable); | |
228 | } | |
229 | ||
230 | int Context::bitbang_enable(unsigned char bitmask) | |
231 | { | |
232 | return ftdi_enable_bitbang(d->ftdi, bitmask); | |
233 | } | |
234 | ||
235 | int Context::bitbang_disable() | |
236 | { | |
237 | return ftdi_disable_bitbang(d->ftdi); | |
238 | } | |
239 | ||
240 | int Context::set_bitmode(unsigned char bitmask, unsigned char mode) | |
241 | { | |
242 | return ftdi_set_bitmode(d->ftdi, bitmask, mode); | |
243 | } | |
244 | ||
245 | int Context::read_pins(unsigned char *pins) | |
246 | { | |
247 | return ftdi_read_pins(d->ftdi, pins); | |
248 | } | |
249 | ||
250 | char* Context::error_string() | |
251 | { | |
252 | return ftdi_get_error_string(d->ftdi); | |
253 | } | |
254 | ||
255 | int Context::get_strings() | |
256 | { | |
257 | // Prepare buffers | |
258 | char vendor[512], desc[512], serial[512]; | |
259 | ||
260 | int ret = ftdi_usb_get_strings(d->ftdi, d->dev, vendor, 512, desc, 512, serial, 512); | |
261 | ||
262 | if(ret < 0) | |
263 | return -1; | |
264 | ||
265 | d->vendor = vendor; | |
266 | d->description = desc; | |
267 | d->serial = serial; | |
268 | ||
269 | return 1; | |
270 | } | |
271 | ||
272 | /*! \fn vendor | |
273 | * \fn description | |
274 | * \fn serial | |
275 | * \brief Device strings properties. | |
276 | */ | |
277 | const std::string& Context::vendor() | |
278 | { | |
279 | return d->vendor; | |
280 | } | |
281 | ||
282 | const std::string& Context::description() | |
283 | { | |
284 | return d->description; | |
285 | } | |
286 | ||
287 | const std::string& Context::serial() | |
288 | { | |
289 | return d->serial; | |
290 | } | |
291 | ||
292 | void Context::set_context(struct ftdi_context* context) | |
293 | { | |
294 | ftdi_free(d->ftdi); | |
295 | d->ftdi = context; | |
296 | } | |
297 | ||
298 | void Context::set_usb_device(struct usb_device *dev) | |
299 | { | |
300 | d->dev = dev; | |
301 | } | |
302 | ||
303 | struct ftdi_context* Context::context() | |
304 | { | |
305 | return d->ftdi; | |
306 | } | |
307 | ||
308 | class Eeprom::Private | |
309 | { | |
310 | public: | |
311 | Private() | |
312 | : context(0) | |
313 | {} | |
314 | ||
315 | struct ftdi_eeprom eeprom; | |
316 | struct ftdi_context* context; | |
317 | }; | |
318 | ||
319 | Eeprom::Eeprom(Context* parent) | |
320 | : d ( new Private() ) | |
321 | { | |
322 | d->context = parent->context(); | |
323 | } | |
324 | ||
325 | Eeprom::~Eeprom() | |
326 | { | |
327 | delete d; | |
328 | } | |
329 | ||
330 | void Eeprom::init_defaults() | |
331 | { | |
332 | return ftdi_eeprom_initdefaults(&d->eeprom); | |
333 | } | |
334 | ||
335 | void Eeprom::set_size(int size) | |
336 | { | |
337 | return ftdi_eeprom_setsize(d->context, &d->eeprom, size); | |
338 | } | |
339 | ||
340 | int Eeprom::size(unsigned char *eeprom, int maxsize) | |
341 | { | |
342 | return ftdi_read_eeprom_getsize(d->context, eeprom, maxsize); | |
343 | } | |
344 | ||
345 | int Eeprom::chip_id(unsigned int *chipid) | |
346 | { | |
347 | return ftdi_read_chipid(d->context, chipid); | |
348 | } | |
349 | ||
350 | int Eeprom::build(unsigned char *output) | |
351 | { | |
352 | return ftdi_eeprom_build(&d->eeprom, output); | |
353 | } | |
354 | ||
355 | int Eeprom::read(unsigned char *eeprom) | |
356 | { | |
357 | return ftdi_read_eeprom(d->context, eeprom); | |
358 | } | |
359 | ||
360 | int Eeprom::write(unsigned char *eeprom) | |
361 | { | |
362 | return ftdi_write_eeprom(d->context, eeprom); | |
363 | } | |
364 | ||
365 | int Eeprom::erase() | |
366 | { | |
367 | return ftdi_erase_eeprom(d->context); | |
368 | } | |
369 | ||
370 | class List::Private | |
371 | { | |
372 | public: | |
373 | Private() | |
374 | : list(0) | |
375 | {} | |
376 | ||
377 | struct ftdi_device_list* list; | |
378 | }; | |
379 | ||
380 | List::List(struct ftdi_device_list* devlist) | |
381 | : ListBase(), d( new Private() ) | |
382 | { | |
383 | if(devlist != 0) | |
384 | { | |
385 | // Iterate list | |
386 | Context* c = 0; | |
387 | for(d->list = devlist; d->list != 0; d->list = d->list->next) | |
388 | { | |
389 | c = new Context(); | |
390 | c->set_usb_device(d->list->dev); | |
391 | push_back(c); | |
392 | } | |
393 | ||
394 | // Store pointer | |
395 | d->list = devlist; | |
396 | } | |
397 | } | |
398 | ||
399 | List::~List() | |
400 | { | |
401 | // Deallocate instances | |
402 | for(iterator it = begin(); it != end(); it++) | |
403 | delete *it; | |
404 | ||
405 | // Clear list | |
406 | clear(); | |
407 | ftdi_list_free(&d->list); | |
408 | ||
409 | // Delete d-ptr | |
410 | delete d; | |
411 | } | |
412 | ||
413 | List* List::find_all(int vendor, int product) | |
414 | { | |
415 | struct ftdi_device_list* dlist = 0; | |
416 | struct ftdi_context ftdi; | |
417 | ftdi_init(&ftdi); | |
418 | ftdi_usb_find_all(&ftdi, &dlist, vendor, product); | |
419 | ftdi_deinit(&ftdi); | |
420 | return new List(dlist); | |
421 | } | |
422 | ||
423 | } |