ezusbthamway.cpp
1 /***************************************************************************
2  Copyright (C) 2002-2015 Kentaro Kitagawa
3  kitagawa@phys.s.u-tokyo.ac.jp
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  You should have received a copy of the GNU Library General
11  Public License and a list of authors along with this program;
12  see the files COPYING and AUTHORS.
13 ***************************************************************************/
14 #include "ezusbthamway.h"
15 #include "charinterface.h"
16 #include <QFile>
17 #include <QDir>
18 #include <QApplication>
19 
20 #define CUSB_BULK_WRITE_SIZE 40000
21 
22 #define NOMINMAX
23 #include <windows.h>
24 extern "C" {
25  #include "cusb.h"
26  #include "fx2fw.h"
27 }
28 
29 #define CMD_DIPSW 0x11u
30 #define CMD_LED 0x12u
31 
32 #define ADDR_IDN 0x1fu
33 #define ADDR_CHARINTF 0xa0u
34 
35 #define THAMWAY_USB_FIRMWARE_FILE "fx2fw.bix"
36 #define THAMWAY_USB_GPIFWAVE1_FILE "slow_dat.bin" //for USB1.1
37 #define THAMWAY_USB_GPIFWAVE2_FILE "fullspec_dat.bin" //for USB2.0 burst-transfer enabled
38 #define THAMWAY_USB_GPIFWAVE_SIZE 172
39 
40 XMutex XWinCUSBInterface::s_mutex;
41 int XWinCUSBInterface::s_refcnt = 0;
42 std::deque<XWinCUSBInterface::USBDevice> XWinCUSBInterface::s_devices;
43 
44 void
45 XWinCUSBInterface::openAllEZUSBdevices() {
46  QDir dir(QApplication::applicationDirPath());
47  auto load_firm = [&dir](char *data, int expected_size, const char *filename){
48  QString path = filename;
49  dir.filePath(path);
50  if( !dir.exists())
51  throw XInterface::XInterfaceError(i18n_noncontext("USB GPIF/firmware file ") +
52  filename + i18n_noncontext(" not found."), __FILE__, __LINE__);
53  QFile file(dir.absoluteFilePath(path));
54  if( !file.open(QIODevice::ReadOnly))
55  throw XInterface::XInterfaceError(i18n_noncontext("USB GPIF/firmware file ") +
56  filename + i18n_noncontext(" not found."), __FILE__, __LINE__);
57  int size = file.read(data, expected_size);
58  if(size != expected_size)
59  throw XInterface::XInterfaceError(i18n_noncontext("USB GPIF/firmware file ") +
60  filename + i18n_noncontext(" is not proper."), __FILE__, __LINE__);
61  };
62 
63  char firmware[CUSB_DWLSIZE];
64  load_firm(firmware, CUSB_DWLSIZE, THAMWAY_USB_FIRMWARE_FILE);
65  char gpifwave1[THAMWAY_USB_GPIFWAVE_SIZE];
66  load_firm(gpifwave1, THAMWAY_USB_GPIFWAVE_SIZE, THAMWAY_USB_GPIFWAVE1_FILE);
67  char gpifwave2[THAMWAY_USB_GPIFWAVE_SIZE];
68  bool always_slow_usb = false;
69  try {
70  load_firm(gpifwave2, THAMWAY_USB_GPIFWAVE_SIZE, THAMWAY_USB_GPIFWAVE2_FILE);
71  }
72  catch (XInterface::XInterfaceError& e) {
73  e.print();
74  gMessagePrint(i18n_noncontext("Continues with slower USB speed."));
75  always_slow_usb = true;
76  }
77 
78  for(int i = 0; i < 8; ++i) {
79  void *handle = 0;
80  fprintf(stderr, "cusb_init #%d\n", i);
81  if(cusb_init(i, &handle, (uint8_t *)firmware,
82  (signed char*)"F2FW", (signed char*)"20070627")) {
83  //no device, or incompatible firmware.
84  continue;
85  }
86  uint8_t sw = readDIPSW(handle);
87  USBDevice dev;
88  dev.handle = handle;
89  dev.addr = sw;
90  dev.mutex.reset(new XRecursiveMutex);
91  s_devices.push_back(dev);
92  fprintf(stderr, "Setting GPIF waves for handle 0x%x, DIPSW=%x\n", (unsigned int)handle, (unsigned int)sw);
93  char *gpifwave = gpifwave2;
94  if(always_slow_usb || (dev.addr == DEV_ADDR_PROT))
95  gpifwave = gpifwave1;
96  setWave(handle, (const uint8_t*)gpifwave);
97 
98  for(int i = 0; i < 3; ++i) {
99  //blinks LED
100  setLED(handle, 0x00u);
101  msecsleep(70);
102  setLED(handle, 0xf0u);
103  msecsleep(60);
104  }
105  }
106  if(s_devices.empty())
107  throw XInterface::XInterfaceError(i18n_noncontext("USB-device open has failed."), __FILE__, __LINE__);
108 }
109 
110 void
111 XWinCUSBInterface::setWave(void *handle, const uint8_t *wave) {
112  std::vector<uint8_t> buf;
113  buf.insert(buf.end(), {CMD_MODE, MODE_GPIF | MODE_8BIT | MODE_ADDR | MODE_NOFLOW | MODE_DEBG, CMD_GPIF});
114  buf.insert(buf.end(), wave, wave + 8);
115  buf.insert(buf.end(), {MODE_FLOW});
116  buf.insert(buf.end(), wave + 8 + 32*4, wave + 8 + 32*4 + 36);
117  if(usb_bulk_write( &handle, CPIPE, &buf[0], buf.size()) < 0)
118  throw XInterface::XInterfaceError(i18n_noncontext("USB bulk writing has failed."), __FILE__, __LINE__);
119  const uint8_t cmdwaves[] = {CMD_WAVE0 /*SingleRead*/, CMD_WAVE1/*SingleWrite*/, CMD_WAVE2/*BurstRead*/, CMD_WAVE3/*BurstWrite*/};
120  for(int i = 0; i < sizeof(cmdwaves); ++i) {
121  buf.clear();
122  buf.insert(buf.end(), cmdwaves + i, cmdwaves + i + 1);
123  buf.insert(buf.end(), wave + 8 + 32*i, wave + 8 + 32*(i + 1));
124  if(usb_bulk_write( &handle, CPIPE, &buf[0], buf.size()) < 0)
125  throw XInterface::XInterfaceError(i18n_noncontext("USB bulk writing has failed."), __FILE__, __LINE__);
126  }
127 }
128 void
129 XWinCUSBInterface::closeAllEZUSBdevices() {
130  for(auto it = s_devices.begin(); it != s_devices.end(); ++it) {
131  try {
132  setLED(it->handle, 0);
133  }
134  catch (XInterface::XInterfaceError &e) {
135  e.print();
136  }
137 
138  fprintf(stderr, "cusb_close\n");
139  usb_close( &it->handle);
140  }
141  s_devices.clear();
142 }
143 
144 XWinCUSBInterface::XWinCUSBInterface(const char *name, bool runtime, const shared_ptr<XDriver> &driver, uint8_t addr_offset, const char* id)
145  : XCustomCharInterface(name, runtime, driver), m_handle(0), m_idString(id), m_addrOffset(addr_offset) {
146  XScopedLock<XMutex> slock(s_mutex);
147  try {
148  if( !s_refcnt)
149  openAllEZUSBdevices();
150  s_refcnt++;
151 
152  iterate_commit([=](Transaction &tr){
153  for(auto it = s_devices.begin(); it != s_devices.end(); ++it) {
154  XString idn;
155  if(strlen(id)) {
156  //for PG and DV series.
157  idn = getIDN(it->handle, 7);
158  if( !idn.length()) continue;
159  }
160  else {
161  //for PROT
162  if(it->addr != DEV_ADDR_PROT) continue;
163  idn = "PROT";
164  }
165  idn = formatString("%d:%s", it->addr, idn.c_str());
166  tr[ *device()].add(idn);
167  }
168  });
169  }
170  catch (XInterface::XInterfaceError &e) {
171  e.print();
172  }
173 }
174 
175 XWinCUSBInterface::~XWinCUSBInterface() {
176  if(isOpened()) close();
177 
178  XScopedLock<XMutex> slock(s_mutex);
179  s_refcnt--;
180  if( !s_refcnt)
181  closeAllEZUSBdevices();
182 }
183 
184 void
185 XWinCUSBInterface::open() throw (XInterfaceError &) {
186  Snapshot shot( *this);
187  try {
188  for(auto it = s_devices.begin(); it != s_devices.end(); ++it) {
189  int addr;
190  if(sscanf(shot[ *device()].to_str().c_str(), "%d:", &addr) != 1)
191  throw XInterface::XOpenInterfaceError(__FILE__, __LINE__);
192  if(addr == it->addr) {
193  m_handle = it->handle;
194  m_mutex = it->mutex;
195  }
196  }
197  if( !m_handle)
198  throw XInterface::XOpenInterfaceError(__FILE__, __LINE__);
199  }
200  catch (XInterface::XInterfaceError &e) {
201  m_handle = 0;
202  m_mutex.reset();
203  throw;
204  }
205  resetBulkWrite();
206 }
207 
208 void
209 XWinCUSBInterface::close() throw (XInterfaceError &) {
210  m_handle = 0;
211  m_mutex.reset();
212 }
213 
214 void
215 XWinCUSBInterface::resetBulkWrite() {
216  m_bBurstWrite = false;
217  m_buffer.clear();
218 }
219 void
220 XWinCUSBInterface::deferWritings() {
221  assert(m_buffer.size() == 0);
222  m_bBurstWrite = true;
223 }
224 void
225 XWinCUSBInterface::writeToRegister16(unsigned int addr, uint16_t data) {
226  if(m_bBurstWrite) {
227  writeToRegister8(addr, data % 0x100u);
228  writeToRegister8(addr + 1, data / 0x100u);
229  }
230  else {
232  writeToRegister8(addr, data % 0x100u);
233  writeToRegister8(addr + 1, data / 0x100u);
234  }
235 }
236 void
237 XWinCUSBInterface::writeToRegister8(unsigned int addr, uint8_t data) {
238  addr += m_addrOffset;
239  assert(addr < 0x100u);
240 
241  if(m_bBurstWrite) {
242  if(m_buffer.size() > CUSB_BULK_WRITE_SIZE) {
244  bulkWriteStored();
245  deferWritings();
246  }
247  m_buffer.push_back(addr);
248  m_buffer.push_back(data);
249  }
250  else {
252  uint8_t cmds[] = {CMD_BWRITE, 2, 0}; //2bytes to be written.
253  if(usb_bulk_write( &m_handle, CPIPE, cmds, sizeof(cmds)) < 0)
254  throw XInterface::XInterfaceError(i18n("USB bulk writing has failed."), __FILE__, __LINE__);
255  uint8_t cmds2[] = {(uint8_t)(addr), data};
256  if(usb_bulk_write( &m_handle, TFIFO, cmds2, sizeof(cmds2)) < 0)
257  throw XInterface::XInterfaceError(i18n("USB bulk writing has failed."), __FILE__, __LINE__);
258  }
259 }
260 void
261 XWinCUSBInterface::bulkWriteStored() {
263 
264  uint16_t len = m_buffer.size();
265  uint8_t cmds[] = {CMD_BWRITE, (uint8_t)(len % 0x100u), (uint8_t)(len / 0x100u)};
266  if(usb_bulk_write( &m_handle, CPIPE, cmds, sizeof(cmds)) < 0)
267  throw XInterface::XInterfaceError(i18n("USB bulk writing has failed."), __FILE__, __LINE__);
268  if(usb_bulk_write( &m_handle, TFIFO, (uint8_t*) &m_buffer[0], len) < 0)
269  throw XInterface::XInterfaceError(i18n("USB bulk writing has failed."), __FILE__, __LINE__);
270 
271  resetBulkWrite();
272 }
273 
274 void
275 XWinCUSBInterface::setLED(void *handle, uint8_t data) {
276  uint8_t cmds[] = {CMD_LED, data};
277  if(usb_bulk_write( &handle, CPIPE, cmds, sizeof(cmds)) < 0)
278  throw XInterface::XInterfaceError(i18n_noncontext("USB bulk writing has failed."), __FILE__, __LINE__);
279 }
280 
281 uint8_t
282 XWinCUSBInterface::readDIPSW(void *handle) {
283  uint8_t cmds[] = {CMD_DIPSW};
284  if(usb_bulk_write( &handle, CPIPE, cmds, sizeof(cmds)) < 0)
285  throw XInterface::XInterfaceError(i18n_noncontext("USB bulk writing has failed."), __FILE__, __LINE__);
286  uint8_t buf[10];
287  if(usb_bulk_read( &handle, RFIFO, buf, 1) != 1)
288  throw XInterface::XInterfaceError(i18n_noncontext("USB bulk reading has failed."), __FILE__, __LINE__);
289  return buf[0];
290 }
291 
292 XString
293 XWinCUSBInterface::getIDN(void *handle, int maxlen, int addroffset) {
294  //ignores till \0
295  for(int i = 0; ; ++i) {
296  char c = singleRead(handle, ADDR_IDN, addroffset);
297  if( !c)
298  break;
299  if(i > 255) {
300  return XString(); //failed
301  }
302  }
303  XString idn;
304  for(int i = 0; ; ++i) {
305  char c = singleRead(handle, ADDR_IDN, addroffset);
306  if( !c)
307  break;
308  idn += c;
309  if(i >= maxlen) {
310  break;
311  }
312  }
313  fprintf(stderr, "getIDN:%s\n", idn.c_str());
314  return idn;
315 }
316 uint8_t
317 XWinCUSBInterface::singleRead(unsigned int addr) {
319  return singleRead(m_handle, addr, m_addrOffset);
320 }
321 
322 uint8_t
323 XWinCUSBInterface::singleRead(void *handle, unsigned int addr, unsigned int addroffset) {
324  addr += addroffset;
325  assert(addr < 0x100u);
326  {
327  uint8_t cmds[] = {CMD_SWRITE, (uint8_t)(addr)};
328  if(usb_bulk_write( &handle, CPIPE, cmds, sizeof(cmds)) < 0)
329  throw XInterface::XInterfaceError(i18n_noncontext("USB bulk writing has failed."), __FILE__, __LINE__);
330  }
331  {
332  uint8_t cmds[] = {CMD_SREAD};
333  if(usb_bulk_write( &handle, CPIPE, cmds, sizeof(cmds)) < 0)
334  throw XInterface::XInterfaceError(i18n_noncontext("USB bulk writing has failed."), __FILE__, __LINE__);
335  uint8_t buf[10];
336  if(usb_bulk_read( &handle, RFIFO, buf, 1) != 1)
337  throw XInterface::XInterfaceError(i18n_noncontext("USB bulk reading has failed."), __FILE__, __LINE__);
338  return buf[0];
339  }
340 }
341 uint16_t
342 XWinCUSBInterface::readRegister16(unsigned int addr) {
344  return singleRead(addr) + singleRead(addr + 1) * (uint16_t)0x100u;
345 }
346 
347 void
348 XWinCUSBInterface::burstRead(unsigned int addr, uint8_t *buf, unsigned int cnt) {
350  addr += m_addrOffset;
351  assert(addr < 0x100u);
352  {
353  uint8_t cmds[] = {CMD_SWRITE, (uint8_t)(addr)};
354  if(usb_bulk_write( &m_handle, CPIPE, cmds, sizeof(cmds)) < 0)
355  throw XInterface::XInterfaceError(i18n("USB bulk writing has failed."), __FILE__, __LINE__);
356  }
357  const unsigned int blocksize = 512;
358  uint8_t cmds[] = {CMD_BREAD, blocksize % 0x100u, blocksize / 0x100u};
359  uint8_t bbuf[blocksize];
360  for(; cnt;) {
361  if(usb_bulk_write( &m_handle, CPIPE, cmds, sizeof(cmds)) < 0)
362  throw XInterface::XInterfaceError(i18n("USB bulk writing has failed."), __FILE__, __LINE__);
363  int i = usb_bulk_read( &m_handle, RFIFO, bbuf, blocksize);
364  if(i <= 0)
365  throw XInterface::XInterfaceError(i18n("USB bulk reading has failed."), __FILE__, __LINE__);
366  unsigned int n = std::min(cnt, (unsigned int)i);
367  std::copy(bbuf, bbuf + n, buf);
368  buf += n;
369  cnt -= n;
370  }
371 }
372 
373 void
374 XWinCUSBInterface::send(const char *str) throw (XCommError &) {
375  XScopedLock<XInterface> lock(*this);
376  XScopedLock<XWinCUSBInterface> lock2( *this);
377  try {
378  dbgPrint(driver()->getLabel() + " Sending:\"" + dumpCString(str) + "\"");
379  XString buf = str + eos();
380  for(int i = 0; i < buf.length(); ++i) {
381  writeToRegister8(ADDR_CHARINTF, (uint8_t)buf[i]);
382  }
383  }
384  catch (XCommError &e) {
385  e.print(driver()->getLabel() + i18n(" SendError, because "));
386  throw;
387  }
388 }
389 void
390 XWinCUSBInterface::receive() throw (XCommError &) {
392  XScopedLock<XWinCUSBInterface> lock2( *this);
393  msecsleep(20);
394  buffer_receive().clear();
395  try {
396  dbgPrint(driver()->getLabel() + " Receiving...");
397  for(int i = 0; ; ++i) {
398  uint8_t c = singleRead(ADDR_CHARINTF);
399  if( !c || (c == 0xffu))
400  break;
401  if( i > 256 )
402  throw XInterface::XCommError(i18n("USB string length exceeded the limit."), __FILE__, __LINE__);
403  buffer_receive().push_back(c);
404  }
405  buffer_receive().push_back('\0');
406  dbgPrint(driver()->getLabel() + " Received;\"" +
407  dumpCString((const char*)&buffer()[0]) + "\"");
408  }
409  catch (XCommError &e) {
410  e.print(driver()->getLabel() + i18n(" ReceiveError, because "));
411  throw;
412  }
413 }

Generated for KAME4 by  doxygen 1.8.3