Ad van der Weiden / Mbed 2 deprecated tcpft

Dependencies:   mbed ConfigFile

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers libft.c Source File

libft.c

Go to the documentation of this file.
00001 //this file was adapted by Ad for use in the mbed environment
00002 //currently all USB functionality has been disabled, this may change in the future
00003 //the comport functionality has been adapted to the mbed serial class
00004 //threads and semphores were replaced by other primitives
00005 //as a consequence also the ftlib.h was adapted
00006 
00007 /** @file
00008  *
00009  * Copyright (C) 2007 Erik Andresen erik@vontaene.de
00010  *
00011  * Open Source version of the fischertechnik ROBO Interface Library for Unix like systems
00012  *
00013  * Communication is done through a "transfer area" this is constantly updated.
00014  *
00015  * This library is free software; you can redistribute it and/or
00016  * modify it under the terms of the GNU Lesser General Public
00017  * License as published by the Free Software Foundation; either
00018  * version 2.1 of the License, or (at your option) any later version.
00019  *
00020  * This library is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00023  * Lesser General Public License for more details.
00024  *
00025  * You should have received a copy of the GNU Lesser General Public
00026  * License along with this library; if not, write to the Free Software
00027  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00028  *
00029  */
00030 
00031 /**
00032  * \example example.c
00033  *
00034  * \mainpage libft Index Page
00035  *
00036  * \section intro_sec Introduction
00037  *
00038  * libft is an Open Source version of the fischertechnik ROBO Interface Library for Unix like systems
00039  *
00040  * The goal is to create a library that is fully compatible with the ftlib by knobloch eletronic.
00041  *
00042  * This library should work on any systems supported by libusb, like Linux, BSD and Mac OS X and is released
00043  * under the GNU Lesser General Public License (LGPL)
00044  *
00045  * Included is the helper program "ftuploader" which allows you to upload programs to the Robo Interface.\n
00046  * Running ftuploader --help should give you an idea how to use it.\n
00047  * Also included is an Interface Diagnose utility. See section Interface Diagnose
00048  *
00049  * \section dl_sec Download
00050  * Current Version: 0.4.3
00051  *
00052  * See http://defiant.homedns.org/~erik/ft/libft/files/ \n
00053  * Download Latest version: http://defiant.homedns.org/~erik/ft/libft/files/libft-current.tar.gz
00054  *
00055  * \section req_sec Requirements
00056  * - libusb - http://libusb.sourceforge.net/
00057  * - cmake at least version 2.4 - http://cmake.org
00058  * - pthreads (Should be included with every modern posix compatible OS)
00059  *
00060  *
00061  * \section apidoc_sec API Documentation
00062  * \see libft.c
00063  *
00064  * \section install_sec Installation
00065  *
00066  * \subsection step1 Step 1: Compiling
00067  *
00068  * Type
00069  * - cmake .
00070  * - make
00071  * \subsection step2 Step 2: Installation
00072  * Type
00073  * - make install
00074  *
00075  * After installing you should run
00076  * - ldconfig
00077  *
00078  * to make the library known to your system. Make sure that /etc/ld.so.conf is configured to include /usr/local/li
00079  *
00080  * To install the diagnose utility type
00081  * - make diag
00082  *
00083  * Debian packages are available. Please read http://vontaene.de/apt/README.txt.\n
00084  * You can install them with apt-get install libft0 libft-doc libft-python libft-diag
00085  *
00086  * \subsection step3 Step 3: udev
00087  * When running udev you might want to copy the file fischertechnik.rules from the udev folder to /etc/udev/rules.d/ to get the correct permissions.\n
00088  * Udev then needs a reload with
00089  * - udevcontrol reload_rules
00090  *
00091  * You will now need to replug your device.
00092  *
00093  * \subsection step4 Step 4: Create Documentation\n
00094  * Type\n
00095  * - make doc\n
00096  * to create the html API documentation.
00097  *
00098  * \subsection step5 Step 5: Python
00099  * A Python interface to this library is available, see the python folder for details.\n
00100  * Type\n
00101  * make python\n
00102  *
00103  * in the python/ -folder to install the python module.
00104  * Use pydoc to read its documentation:
00105  * - pydoc robointerface in the shell
00106  * - help(robointerface) from the python interpreter
00107  *
00108  * \section diag_sec Interface Diagnose
00109  * You can find it in the folder diag/.\n
00110  * It requires the python module (see above) and PyQT4. You can launch it by running "sh ftdiagnose"
00111  * \image html diag1.png
00112  *
00113  * \section author_sec Author
00114  * Erik Andresen - erik@vontaene.de
00115  *
00116  * Please contact me for bugs or any suggestions
00117  *
00118  * Homepage of libft: http://defiant.homedns.org/~erik/ft/libft/
00119  *
00120  *
00121  * \section changes_sec Changes
00122  *
00123  * - 0.4.3:    - Bug fix: Extension digital inputs at RoboRF
00124  *        - ftdiagnose: Display connection status
00125  *        - Added functions: (not in Knobloch lib):
00126  *            - IsFtInterfaceConnected()
00127  *        - Python added functions:
00128  *            - IsConnected()
00129  * - 0.4.2:    - Python support to open the interface by serial
00130  *        - Some Bug fixes
00131  *         - Added functions: (not in Knobloch lib)
00132  *             - SetRealSerial()
00133  * - 0.4.1:
00134  *           - Added support to change the RF address.
00135  *         - Added functions: (not in Knobloch lib)
00136  *             - SetRFMode()
00137  *             - GetRFMode()
00138  *         - Added support for functions:
00139  *             - GetFtManufacturerStrg()
00140  *             - GetFtShortNameStrg()
00141  *             - GetFtLongNameStrg()
00142  *             - GetFtLibErrorString()
00143  *         - Some minor Bug fixes
00144  * - 0.4:
00145  *           - Hopefully support for more then one Robo Interface attached to an RF Link.
00146  *             - InitFtUsbDeviceList() will now also count the number of Robo Interfaces attached to an RF Link
00147  *         - Added support for the ft distance sensor
00148  *         - Added functions:
00149  *             - GetFtDeviceTypeString() (not in Knobloch lib)
00150  *         - Added support for functions:
00151  *             - SetFtDistanceSensorMode()
00152  *         - Python added functions:
00153  *             - GetNumFtUsbDevices()
00154  *             - RoboInterface.GetDeviceTypeString()
00155  *             - GetD1()
00156  *             - GetD2()
00157  *         - Added ft Diagnose utility.
00158  * - 0.3:
00159  *           - added (overwrite) --target option to the ftuploader
00160  *         - included some documentation
00161  *         - minor fixes
00162  *         - enhanced python layer
00163  *         - support for RF Module
00164  * - 0.2.1:
00165  *           - fixed Analog/Voltage Sensor calculations
00166  * - 0.2:
00167  *           - added udev file
00168  *         - experimental support for uploading to the interface (usb only)
00169  *         - included program ftuploader
00170  *         - add support for functions:
00171  *             - DownloadFtProgram()
00172  *             - StartFtProgram()
00173  *             - StopFtProgram()
00174  *             - DeleteFtProgram()
00175  *             - SetFtProgramActiv()
00176  *             - GetFtProgramName()
00177  *             - GetFtStatus()
00178  *             - GetFtFirmware()
00179  *             - GetFtFirmwareStrg()
00180  *             - GetFtSerialNr()
00181  *             - GetFtSerialNrStrg()
00182  *
00183  *
00184  * \section porting_sec Porting your program from the Knobloch Windows Library
00185  * When porting your program from the Knobloch Library for Microsoft Windows operation systems please note the following:
00186  * - The name of this library is libft, not ftlib (the Knobloch original) to follow the UNIX naming scheme
00187  * - Types like DWORD are replaced with their logical ANSI-C counterparts, like
00188  *   -# DWORD - long int
00189  *   -# LPCSTR - char *
00190  *   -# LPVOID - void *
00191  *   -# BYTE - unsigned char
00192  *   -# USHORT - unsigned short int
00193  *   -# UINT - unsigned int
00194  *   -# UCHAR - unsigned char
00195  * - The Windows Notifications stuff will probably never be supported.
00196  * - Some return codes might be different, so if something is going wrong, check this manual.
00197  *
00198  */
00199 #define MBED
00200 #define NOTNOW
00201 #define SPLITTRANSFER
00202 
00203 #ifdef MBED
00204 #include "mbed.h"
00205 #define usleep(x)    wait_us(x)
00206 #define sleep(x)    wait(x)
00207 #define LIBFT_VERSION_MAJOR 1
00208 #define LIBFT_VERSION_MINOR 0
00209 #define LIBFT_VERSION_PATCH 0
00210 Serial viaUsb(USBTX, USBRX);
00211 #else
00212 #include <stdio.h>
00213 #include <string.h>
00214 #include <pthread.h>
00215 #include <semaphore.h>
00216 #include <termios.h>
00217 #include <fcntl.h>
00218 #endif
00219 #ifdef USE_USB
00220 #include <usb.h>
00221 #else
00222 //some dummy USB stuff
00223 #endif
00224 #ifdef USE_DOWNLOAD
00225 #include "crc.h"
00226 #endif
00227 #include "ftlib.h "
00228 
00229 /** \cond doxygen ignore start */
00230 #define VERSION_MAJOR LIBFT_VERSION_MAJOR
00231 #define VERSION_MINOR LIBFT_VERSION_MINOR
00232 #define VERSION_PATCH LIBFT_VERSION_PATCH
00233 #define FT_VENDOR_ID 0x146a
00234 #define ROBO_IF_PRODUCT_ID 0x1
00235 #define EXT_IF_PRODUCT_ID 0x2
00236 #define RF_DATA_LINK_PRODUCT_ID 0x3
00237 #define ABF_IF_COMPLETE 0x8b // 0xf2
00238 #define INTERFACE_QUERY_TIME 10000 // &#65533;s == 5ms
00239 #define INTERFACE_QUERY_TIME_SERIAL 10000
00240 #define FT_ENDPOINT_INTERRUPT_IN 0x81
00241 #define FT_ENDPOINT_INTERRUPT_OUT 0x1
00242 #define FT_ENDPOINT_BULK_IN 0x82
00243 #define FT_ENDPOINT_BULK_OUT 0x2
00244 #define FT_RF_ENDPOINT_INTERRUPT_IN 0x82
00245 #define FT_RF_ENDPOINT_INTERRUPT_OUT 0x2
00246 #define FT_USB_TIMEOUT 1000
00247 #define FT_USB_TIMEOUT_LONG 10000
00248 
00249 #ifdef MBED
00250 #define BAUDRATE_II 9600
00251 #define BAUDRATE_RI 38400
00252 #else
00253 #define BAUDRATE_II B9600
00254 #define BAUDRATE_RI B38400
00255 #endif
00256 #define PROGRAM_UPLOAD_PACKET_SIZE 128
00257 
00258 #ifndef MIN
00259 #define MIN(a, b) ( (a)<=(b) ? (a) : (b) )
00260 #endif
00261 /** \endcond doxygen ignore end */
00262 
00263 
00264 /**
00265  * \brief Returns lib version
00266  *
00267  *  Returns the library version.
00268  *
00269  *  @return version as Major Minor Patch
00270  */
00271 long int GetLibVersion() {
00272     return VERSION_MAJOR<<16 | VERSION_MINOR<<8 | VERSION_PATCH;
00273 }
00274 
00275 
00276 /**
00277  * \brief Returns lib version
00278  *
00279  * Returns the library version.
00280  * The allocated space should be freed with free() later.
00281  *
00282  * @return Pointer to a string with the serial
00283  */
00284 char *GetLibVersionStrg() {
00285     long int ver = GetLibVersion();
00286     char *s = (char *)malloc(16);
00287     int byte1 = ver & 0xff;
00288     int byte2 = (ver & 0xff00) >> 8;
00289     int byte3 = (ver & 0xff0000) >> 16;
00290 
00291     snprintf(s, 16, "%d.%02d.%02d", byte3, byte2, byte1);
00292 
00293     return s;
00294 }
00295 
00296 
00297 /**
00298  * \brief Library initialization (dummy)
00299  *
00300  * Dummy for compatibility. Only used in original library.
00301  * @return Always FTLIB_ERR_SUCCESS
00302  */
00303 long int InitFtLib() {
00304     return FTLIB_ERR_SUCCESS;
00305 }
00306 
00307 
00308 /**
00309  * \brief Initiates and scans the USB bus
00310  *
00311  * This function has to be called before any other USB action.
00312  * It will set up USB basic variables and then scan the USB bus.
00313  *
00314  * @return Always FTLIB_ERR_SUCCESS. Not able to fail.
00315  */
00316 long int InitFtUsbDeviceList() {
00317 #ifdef USE_USB
00318     usb_init();
00319     usb_find_busses();
00320     usb_find_devices();
00321 #endif
00322     return FTLIB_ERR_SUCCESS;
00323 }
00324 
00325 
00326 /** \cond doxygen ignore start */
00327 static unsigned int GetNumFtDevicesFromRF(struct usb_device *dev) {
00328     unsigned int iNum = 0;
00329 #ifdef USE_USB
00330     usb_dev_handle *device;
00331     int ret;
00332     unsigned char buffer[35] = { 0 };
00333     int i;
00334 
00335     device = usb_open(dev);
00336 
00337     for (i=1; i<9; i++) {
00338         ret = usb_control_msg(device, 0xc0, 0x52, i<<8 | 0x05, 0, buffer, 35, FT_USB_TIMEOUT);
00339         if (ret < 0) fprintf(stderr, "Error sending control msg 0xC0 0x52\n");
00340         else if (buffer[0] == 0xfa && buffer[1] == 0) iNum++; // buffer[1] == 0xff => no device
00341     }
00342 
00343     usb_close(device);
00344 #endif
00345     return iNum;
00346 }
00347 
00348 
00349 static unsigned int GetNthFtDeviceFromRF(struct usb_device *dev, int iNum) {
00350     int ret=0;
00351 #ifdef USE_USB
00352     usb_dev_handle *device;
00353     unsigned char buffer[35] = { 0 };
00354     int i;
00355 
00356     device = usb_open(dev);
00357 
00358     for (i=1; i<9, iNum>0; i++) {
00359         ret = usb_control_msg(device, 0xc0, 0x52, i<<8 | 0x05, 0, buffer, 35, FT_USB_TIMEOUT);
00360         if (ret < 0) fprintf(stderr, "Error sending control msg 0xC0 0x52\n");
00361         else if (buffer[0] == 0xfa && buffer[1] == 0) iNum--; // buffer[1] == 0xff => no device
00362 
00363         ret = i;
00364     }
00365 
00366     usb_close(device);
00367 #endif
00368     return ret;
00369 }
00370 
00371 
00372 static int GetFtDeviceFromRFWithSerial(struct usb_device *dev, long int dwSN) {
00373 #ifdef USE_USB
00374     usb_dev_handle *device;
00375     int ret;
00376     unsigned char buffer[35] = { 0 };
00377     int i;
00378     long int serial;
00379 
00380     device = usb_open(dev);
00381 
00382     for (i=1; i<9; i++) {
00383         ret = usb_control_msg(device, 0xc0, 0x52, i<<8 | 0x05, 0, buffer, 35, FT_USB_TIMEOUT);
00384         if (ret < 0) fprintf(stderr, "Error sending control msg 0xC0 0x52\n");
00385         else if (buffer[0] == 0xfa && buffer[1] == 0) { // buffer[1] == 0xff => no device
00386             serial = buffer[6]<<24 | buffer[5]<<16 | buffer[4]<<8 | buffer[3];
00387 
00388             if (serial == dwSN) {
00389                 return i;
00390             }
00391         }
00392     }
00393 
00394     usb_close(device);
00395 #endif
00396     return 0;
00397 }
00398 /** \endcond doxygen ignore end */
00399 
00400 
00401 /**
00402  * \brief Get the count of found ft Interfaces over USB.
00403  *
00404  * If we find a Robo RF Data Link we will count the devices attached to it instead
00405  *
00406  * @return Number of ft Interface devices on the USB bus found.
00407  */
00408 unsigned int GetNumFtUsbDevice() {
00409     unsigned int iNum = 0;
00410 #ifdef USE_USB
00411     struct usb_device *dev;
00412     struct usb_bus *busses;
00413     struct usb_bus *bus;
00414     busses = usb_get_busses();
00415 
00416     for (bus = busses; bus; bus = bus->next) {
00417         for (dev = bus->devices; dev; dev = dev->next) {
00418             if (dev->descriptor.idVendor == FT_VENDOR_ID) {
00419                 if (dev->descriptor.idProduct == RF_DATA_LINK_PRODUCT_ID) {
00420                     iNum+=GetNumFtDevicesFromRF(dev);
00421                 }
00422                 iNum++;
00423             }
00424         }
00425     }
00426 #endif
00427     return iNum;
00428 }
00429 
00430 
00431 /** \cond doxygen ignore start */
00432 static int FtproductIDToInterfaceID(int iProductID) {
00433     switch (iProductID) {
00434         case ROBO_IF_PRODUCT_ID:
00435             return FT_ROBO_IF_USB;
00436         case EXT_IF_PRODUCT_ID:
00437             return FT_ROBO_IO_EXTENSION;
00438         case RF_DATA_LINK_PRODUCT_ID:
00439             return FT_ROBO_RF_DATA_LINK;
00440     }
00441 
00442     return 0;
00443 }
00444 
00445 
00446 static int FtInterfaceIDToProductID(int InterfaceID) {
00447     switch (InterfaceID) {
00448         case FT_ROBO_IF_USB:
00449             return ROBO_IF_PRODUCT_ID;
00450         case FT_ROBO_IO_EXTENSION:
00451             return EXT_IF_PRODUCT_ID;
00452         case FT_ROBO_RF_DATA_LINK:
00453             return RF_DATA_LINK_PRODUCT_ID;
00454     }
00455 
00456     return 0;
00457 }
00458 /** \endcond doxygen ignore end */
00459 
00460 
00461 /**
00462  * \brief Gets the handle to a ft USB device.
00463  *
00464  * Get the handle for the ft USB device with this number.
00465  * Passing just 0 as argument will use the first device found.
00466  *
00467  * Count the interfaces with GetNumFtUsbDevice()
00468  *
00469  * @see GetNumFtUsbDevice()
00470  * @param Num selected Interface. If unsure try 0.
00471  * @return The ft device or NULL if error
00472  */
00473 FT_HANDLE GetFtUsbDeviceHandle(unsigned char Num) {
00474 #ifdef USE_USB
00475     struct usb_device *dev;
00476     struct usb_bus *busses;
00477     struct usb_bus *bus;
00478     int i=0;
00479     FT_HANDLE ret;
00480     int count_ri_at_rf;
00481     busses = usb_get_busses();
00482 
00483     for (bus = busses; bus; bus = bus->next) {
00484         for (dev = bus->devices; dev; dev = dev->next) {
00485             if (dev->descriptor.idVendor == FT_VENDOR_ID) {
00486                 if (dev->descriptor.idProduct == RF_DATA_LINK_PRODUCT_ID) {
00487                     count_ri_at_rf = GetNumFtDevicesFromRF(dev);
00488                     i+=count_ri_at_rf;
00489                 }
00490                 if (i >= Num) { // '>=' because any RF will add more then 1 to the count
00491                     ret = (FT_HANDLE) malloc (sizeof(struct ft_handle_devices));
00492                     if (ret == NULL) {
00493                         perror("GetFtUsbDeviceHandle malloc");
00494                         return NULL;
00495                     }
00496                     ret->device = NULL;
00497                     ret->dev = dev;
00498                     ret->sdev = 0;
00499                     ret->type = FtproductIDToInterfaceID(dev->descriptor.idProduct);
00500                     sem_init(&ret->lock, 0, 1);
00501                     memset(&ret->transfer_area, 0, sizeof(struct _FT_TRANSFER_AREA));
00502                     ret->transfer_area.TransferAktiv = 0;
00503                     ret->query_time = INTERFACE_QUERY_TIME;
00504                     ret->transfer_area.RfModulNr = -1;
00505                     ret->interface_connected = 0;
00506 
00507                     if (dev->descriptor.idProduct == RF_DATA_LINK_PRODUCT_ID) {
00508                         ret->transfer_area.RfModulNr = GetNthFtDeviceFromRF(dev, Num);
00509                         if (ret->transfer_area.RfModulNr == 0) // user has chosen the RF Modul, so choose the first Interface at RF for the user
00510                             ret->transfer_area.RfModulNr = GetNthFtDeviceFromRF(dev, 1);
00511                         else
00512                             ret->type = FT_ROBO_IF_OVER_RF;
00513                     }
00514 
00515                     return ret;
00516                 }
00517                 i++;
00518             }
00519         }
00520     }
00521 #endif
00522     return NULL;
00523 }
00524 
00525 
00526 /**
00527  * \brief Gets the handle to a ft USB device with a specific serial number.
00528  *
00529  * Get the handle for the ft USB device with this number.
00530  * Serial is 1 for most devices, unless explicitly changed in the device.
00531  * Second argument can be FT_AUTO_TYPE.
00532  *
00533  * @param dwSN Serial of the USB Device
00534  * @param dwTyp Type of the USB Device: FT_AUTO_TYPE, FT_ROBO_IF_USB, FT_ROBO_IO_EXTENSION, FT_ROBO_IF_OVER_RF or FT_ROBO_RF_DATA_LINK
00535  * @return The ft device or NULL on error
00536  */
00537 FT_HANDLE GetFtUsbDeviceHandleSerialNr(long int dwSN, long int dwTyp) {
00538 #ifdef USE_USB
00539     int i;
00540     FT_HANDLE ret;
00541     for (i=0; i < GetNumFtUsbDevice(); i++) {
00542         ret = GetFtUsbDeviceHandle(i);
00543         OpenFtUsbDevice(ret);
00544 
00545         if ((dwTyp == FT_AUTO_TYPE || ret->type == dwTyp) && GetFtSerialNr(ret) == dwSN) {
00546             CloseFtDevice(ret);
00547             return ret;
00548         }
00549 
00550         CloseFtDevice(ret);
00551     }
00552 #endif
00553     return NULL;
00554 }
00555 
00556 
00557 //blocking
00558 int read(Serial *d, unsigned char *ptr, int n) {
00559     for (int i = 0; i< n; i++) {
00560         ptr[i] = d->getc();
00561     }
00562     return n;
00563 }
00564 int read(Serial *stream, unsigned char *buf, int n, int timeout_ms) {
00565     Timer t;
00566     t.start();
00567     int i = 0;
00568     while (t.read_ms() < timeout_ms && i < n) {
00569         if (stream->readable())
00570             buf[i++] = stream->getc();
00571     }
00572     return i;
00573 }
00574 
00575 //blocking
00576 int write(Serial *d, unsigned char *ptr, int n) {
00577     for (int i = 0; i< n; i++) {
00578         d->putc(ptr[i]);
00579     }
00580     return n;
00581 }
00582 int write(Serial *d, unsigned char *ptr, int n, int timeout_ms) {
00583     Timer t;
00584     t.start();
00585     int i = 0;
00586     while (t.read_ms() < timeout_ms && i < n) {
00587         if (d->writeable())
00588             d->putc(ptr[i++]);
00589     }
00590     return i;
00591 }
00592 
00593 //non-blocking
00594 int ft_handle_devices::write() {
00595     windex = 0;
00596     //sdev->attach(this, &ft_handle_devices::writeByte, Serial::TxIrq);//could be moved to FtThreadInit
00597     //sdev->attach(this, &ft_handle_devices::readByte, Serial::RxIrq);
00598     writeByte(); //write the first byte, callback will take care of the rest
00599     return num_write;
00600 }
00601 void ft_handle_devices::writeByte() {
00602     if (windex < num_write) {
00603         sdev->putc(out[windex++]);
00604         if (windex == num_write)
00605             rindex = 0;
00606     }
00607 }
00608 void ft_handle_devices::readByte() {
00609     if (rindex < num_read) {
00610         in[rindex++] = sdev->getc();
00611         if (rindex == num_read) {
00612             //sdev->attach(0,Serial::RxIrq);//could be moved to FtThreadFinish
00613             //sdev->attach(0,Serial::TxIrq);
00614             FtThreadEnd();
00615         }
00616     }
00617 }
00618 /**
00619  * \brief Gets the handle to a ft serial device.
00620  *
00621  * Get the handle for the ft Serial device at the selected serial port.
00622  *
00623  * @param sDevice filename of your serial device, like /dev/ttyS0.
00624  * @param dwTyp Interface type. FT_INTELLIGENT_IF, FT_INTELLIGENT_IF_SLAVE or FT_ROBO_IF_COM.
00625  * @param dwZyklus Cycle to retrieve analog values (only II). Try 10.
00626  * @return The ft device or NULL if error.
00627  */
00628 FT_HANDLE OpenFtCommDevice(char *sDevice, long int dwTyp, long int dwZyklus) {//makes a (blocking) comm request to the interface
00629     FT_HANDLE ret;
00630     unsigned char in[5];
00631     unsigned char on[] = " ft-Robo-ON-V1";
00632     on[0] = 0xA1;
00633 #ifdef MBED
00634     Serial *dev;
00635     switch (sDevice[3]) {
00636         case '1':
00637             dev = new Serial(p9, p10);
00638             break;
00639         case '2':
00640             dev = new Serial(p13, p14);
00641             break;
00642         case '3':
00643             dev = new Serial(p28, p27);
00644             break;
00645 //      default:  dev = new Serial(p9, p10); break;
00646         default:
00647             dev = &viaUsb;
00648             break;
00649     }
00650     ret = new ft_handle_devices;
00651 #else
00652     long int dev;
00653     if ((dev = open(sDevice, O_RDWR | O_NOCTTY)) < 0) {
00654         perror("OpenFtCommDevice open");
00655         return NULL;
00656     }
00657 
00658     if ((ret = (FT_HANDLE) malloc (sizeof(struct ft_handle_devices))) == NULL) {
00659         perror("GetFtUsbDeviceHandle malloc");
00660         return NULL;
00661     }
00662     ret->device = NULL;
00663     ret->dev = NULL;
00664 #endif
00665     ret->type = dwTyp;
00666     memset(&ret->transfer_area, 0, sizeof(struct _FT_TRANSFER_AREA));
00667     ret->transfer_area.TransferAktiv = 0;
00668     ret->analogcycle = dwZyklus/2.0+0.5;
00669     ret->query_time = INTERFACE_QUERY_TIME_SERIAL;
00670     ret->transfer_area.RfModulNr = -1;
00671     ret->interface_connected = 0;
00672 #ifdef MBED
00673     ret->lock = 1; //init the semaphore
00674     if (dev != &viaUsb) {
00675         if (dwTyp == FT_INTELLIGENT_IF || dwTyp == FT_INTELLIGENT_IF_SLAVE || dwTyp == FT_ROBO_IF_IIM)
00676             dev->baud(BAUDRATE_II);
00677         else // dwTyp == FT_ROBO_IF_COM
00678             dev->baud(BAUDRATE_RI);
00679     }
00680     ret->sdev = dev;
00681     if (dwTyp == FT_INTELLIGENT_IF) ret->transfer_area.BusModules = 1;
00682     else if (dwTyp == FT_INTELLIGENT_IF_SLAVE) ret->transfer_area.BusModules = 2;
00683     printf("about to send '%s'\n", on);
00684     if (dwTyp == FT_ROBO_IF_COM) {
00685         int sent = write(dev, on, strlen((const char*)on), 100/*ms*/);
00686 //        int sent = dev->printf("%s", on);
00687         printf("sent %d bytes to COM\n", sent);
00688         if (sent == strlen((const char*)on)) {
00689             if (read(dev, in, 5, 1000/*ms*/) == 5) {              //   if (dev->scanf("%5c", in) == 1) { does not work, could have to do with NUL chars or needs a lookahead char
00690                 printf("%02X: interface version: %d.%d.%d.%d\n", in[0], in[4], in[3], in[2], in[1]);
00691                 if ((in[0] ^ on[0]) ==  0x0FFU) {
00692                     printf("opening of %s OK\n", sDevice);
00693                 } else {
00694                     printf("return code is %02X but should be %02X\n", in[0], ~on[0]&0xFF);
00695                     delete ret;
00696                     return NULL;
00697                 }
00698             } else {
00699                 printf("read did not return 5\n");
00700                 delete ret;
00701                 return NULL;
00702             }
00703         } else {
00704             printf("only %d chars were sent i.o %d\n", sent, strlen((const char*)on));
00705             delete ret;
00706             return NULL;
00707         }
00708     }
00709     //printf("OpenFtCommDevice: Error communicating with serial\n");
00710     //delete ret;
00711     //return NULL;
00712 //}
00713 #else
00714     sem_init(&ret->lock, 0, 1);
00715     tcgetattr(dev, &ret->saveioset); /* save current modem settings */
00716     bzero(&ret->newioset, sizeof(struct termios));
00717     ret->newioset.c_cflag = CS8 | CLOCAL | CREAD;
00718     if (dwTyp == FT_INTELLIGENT_IF || dwTyp == FT_INTELLIGENT_IF_SLAVE || dwTyp == FT_ROBO_IF_IIM)
00719         ret->newioset.c_cflag |= BAUDRATE_II;
00720     else // dwTyp == FT_ROBO_IF_COM
00721         ret->newioset.c_cflag |= BAUDRATE_RI;
00722     ret->newioset.c_oflag = 0;
00723     ret->newioset.c_lflag = 0;
00724     ret->newioset.c_cc[VTIME] = 1;
00725     ret->newioset.c_cc[VMIN] = 0;
00726     tcflush(dev, TCIFLUSH);
00727     tcsetattr(dev, TCSANOW, &ret->newioset);
00728     ret->sdev = dev;
00729     if (dwTyp == FT_INTELLIGENT_IF) ret->transfer_area.BusModules = 1;
00730     else if (dwTyp == FT_INTELLIGENT_IF_SLAVE) ret->transfer_area.BusModules = 2;
00731 
00732     if (dwTyp == FT_ROBO_IF_COM && ((write(dev, &on, 14)) != 14 || (read(dev, &in, 5)) != 5 || in[0] != 0x5E)) {
00733         fprintf(stderr, "OpenFtCommDevice: Error communicating with serial\n");
00734         free(ret);
00735         return NULL;
00736     }
00737 #endif
00738     return ret;
00739 }
00740 
00741 
00742 /**
00743  * \brief Returns type of the interface
00744  *
00745  * This function will return the type of the interface that is behind the handle.
00746  *
00747  * @param hFt Handle of the device
00748  * @return NO_FT_DEVICE, FT_INTELLIGENT_IF, FT_INTELLIGENT_IF_SLAVE, FT_ROBO_IF_COM, FT_ROBO_IF_USB, FT_ROBO_IF_IIM, FT_ROBO_IF_OVER_RF, FT_ROBO_IO_EXTENSION or FT_ROBO_RF_DATA_LINK
00749  */
00750 long int GetFtDeviceTyp(FT_HANDLE hFt) {
00751     if (hFt == NULL) {
00752         fprintf(stderr, "GetFtDeviceTyp: No such device\n");
00753         return NO_FT_DEVICE;
00754     }
00755 
00756     return hFt->type;
00757 }
00758 
00759 
00760 /**
00761  * \brief Returns a string that identifies the interface with human words
00762  *
00763  * This function will give you a human readable string like "Robo Interface" you can work with.
00764  *
00765  * @param hFt Handle of the device
00766  * @param dest Buffer we can write the string to
00767  * @param len Maximum length of this buffer
00768  * @return FTLIB_ERR_SUCCESS or a failure
00769  */
00770 long int GetFtDeviceTypeString(FT_HANDLE hFt, char *dest, int len) {
00771     // Todo: Maybe let usb query the string from the device?
00772     if (hFt == NULL) {
00773         fprintf(stderr, "GetFtDeviceTyp: No such device\n");
00774         return NO_FT_DEVICE;
00775     }
00776 
00777     switch (GetFtDeviceTyp(hFt)) {
00778         case FT_INTELLIGENT_IF:
00779             strncpy(dest, "Intelligent Interface", len);
00780             break;
00781         case FT_INTELLIGENT_IF_SLAVE:
00782             strncpy(dest, "Intelligent Interface with slave", len);
00783             break;
00784         case FT_ROBO_IF_IIM:
00785             strncpy(dest, "Robo Interface II mode", len);
00786             break;
00787         case FT_ROBO_IF_COM:
00788             strncpy(dest, "Robo Interface over serial", len);
00789             break;
00790         case FT_ROBO_IF_USB:
00791             strncpy(dest, "Robo Interface over USB", len);
00792             break;
00793         case FT_ROBO_IO_EXTENSION:
00794             strncpy(dest, "Robo IO Extension", len);
00795             break;
00796         case FT_ROBO_RF_DATA_LINK:
00797             strncpy(dest, "Robo RF Datalink", len);
00798             break;
00799         case FT_ROBO_IF_OVER_RF:
00800             strncpy(dest, "Robo Interface over RF Datalink", len);
00801             break;
00802         default:
00803             strncpy(dest, "Unknown", len);
00804     }
00805 
00806     return FTLIB_ERR_SUCCESS;
00807 }
00808 
00809 
00810 
00811 /**
00812  * \brief Opens this USB device.
00813  *
00814  * This function will try to open the ft USB device that belongs to the ft handle hFt.
00815  * You can get the ft handle with GetFtUsbDeviceHandle() or GetFtUsbDeviceHandleSerialNr().
00816  *
00817  * @see GetFtUsbDeviceHandle()
00818  * @see GetFtUsbDeviceHandleSerialNr()
00819  * @param hFt ft USB Device to open
00820  * @return Number >= 0 on success, < 0 on error
00821  */
00822 long int OpenFtUsbDevice(FT_HANDLE hFt) {
00823 #ifdef USE_USB
00824     long int ret;
00825 
00826     if (hFt == NULL) {
00827         fprintf(stderr, "OpenFtUsbDevice: No such device\n");
00828         return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
00829     }
00830     hFt->device = usb_open(hFt->dev);
00831     ret = usb_claim_interface(hFt->device, 0);
00832     if (ret < 0) perror("usb_claim_interface");
00833 
00834     return ret;
00835 #else
00836     return FTLIB_ERR_NOT_SUPPORTED;
00837 #endif
00838 }
00839 
00840 
00841 /**
00842  * \brief Close the ft Device
00843  *
00844  * This function will close the ft Device and free its memory.
00845  *
00846  * @param hFt Handle of the Device to close.
00847  * @return A number < 0 on error.
00848  */
00849 long int CloseFtDevice(FT_HANDLE hFt) {//sends a comm request
00850     int ret = 0;
00851     unsigned char off = 0xA2;
00852     unsigned char in[1];
00853     unsigned char buf[1];
00854 
00855     if (hFt == NULL) {
00856         fprintf(stderr, "CloseFtDevice: No such device\n");
00857         return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
00858     }
00859 
00860     while (hFt->transfer_area.TransferAktiv != 0) {
00861         fprintf(stderr, "Transfer area still active\n");
00862         sleep(1);
00863     }
00864 
00865     switch (hFt->type) {
00866             // usb
00867 #ifdef USE_USB
00868         case FT_ROBO_RF_DATA_LINK:
00869         case FT_ROBO_IF_OVER_RF:
00870         case FT_ROBO_IF_USB:
00871         case FT_ROBO_IO_EXTENSION:
00872             ret = usb_release_interface(hFt->device, 0);
00873             if (ret < 0) {
00874                 fprintf(stderr, "CloseFtDevice(): Error in usb_release_interface()\n");
00875                 break;
00876             }
00877             ret = usb_close(hFt->device);
00878             break;
00879 #endif
00880             // serial
00881 #ifdef MBED
00882         case FT_ROBO_IF_COM:
00883             if (write(hFt->sdev, &off, 1) != 1 || read(hFt->sdev, in, 1) != 1 || (in[0]^off != 0xFF)) {
00884                 fprintf(stderr, "CloseFtDevice: Error communicating with serial\n");
00885             }
00886         case FT_ROBO_IF_IIM:
00887         case FT_INTELLIGENT_IF:
00888         case FT_INTELLIGENT_IF_SLAVE:
00889             delete hFt->sdev;
00890             ret = 0;
00891             break;
00892 #else
00893         case FT_ROBO_IF_COM:
00894             if ((write(hFt->sdev, &off, 1)) != 1 || (read(hFt->sdev, &in, 1)) != 1 || in[0] != 0x5D) {
00895                 fprintf(stderr, "CloseFtDevice: Error communicating with serial\n");
00896             }
00897         case FT_ROBO_IF_IIM:
00898         case FT_INTELLIGENT_IF:
00899         case FT_INTELLIGENT_IF_SLAVE:
00900             tcsetattr(hFt->sdev, TCSANOW, &hFt->saveioset);
00901             ret = close(hFt->sdev);
00902             break;
00903 #endif
00904     }
00905 #ifdef MBED
00906     delete hFt;
00907 #else
00908     free(hFt);
00909 #endif
00910     hFt = NULL;
00911     return ret;
00912 }
00913 
00914 
00915 /**
00916  * \brief Library deinitialization (dummy)
00917  *
00918  * Dummy for compatibility. Only used in original library.
00919  * @return Always FTLIB_ERR_SUCCESS
00920  */
00921 long int CloseFtLib() {
00922     return FTLIB_ERR_SUCCESS;
00923 }
00924 
00925 
00926 /**
00927  * \brief Check for Library initialization (dummy)
00928  *
00929  * Dummy for compatibility. Only used in original library.
00930  * @return Always FTLIB_ERR_LIB_IS_INITIALIZED since initialization is ignored in this version
00931  */
00932 long int IsFtLibInit() {
00933     return FTLIB_ERR_LIB_IS_INITIALIZED;
00934 }
00935 
00936 bool test_and_set(int& s) {
00937     bool tmp;
00938     __disable_irq();
00939     if (tmp = s>0)
00940         s--;
00941     __enable_irq();
00942     return tmp;
00943 }
00944 
00945 void increment(int& s) {
00946     __disable_irq();
00947     s++;
00948     __enable_irq();
00949 }
00950 #ifdef SPLITTRANSFER
00951 
00952 //version for mbed with split functionality
00953 
00954 void ft_handle_devices::FtThreadInit() {//setup buffers for this type of interface
00955     FT_TRANSFER_AREA *area = &transfer_area;
00956     num_write = ABF_IF_COMPLETE_NUM_WRITE;
00957     num_read = ABF_IF_COMPLETE_NUM_READ;
00958     usb_endpoint_write = FT_ENDPOINT_INTERRUPT_OUT;
00959     usb_endpoint_read = FT_ENDPOINT_INTERRUPT_IN;
00960     cycle=0;
00961 
00962     out[0] = ABF_IF_COMPLETE;
00963     area->TransferAktiv = 1;
00964     sdev->attach(this, &ft_handle_devices::writeByte, Serial::TxIrq);
00965     sdev->attach(this, &ft_handle_devices::readByte, Serial::RxIrq);
00966     busy = false;
00967 
00968     switch (type) {
00969         case FT_ROBO_IF_COM:
00970             out[0] = 0xf2;
00971             num_write = 17;
00972             num_read = 21;
00973             break;
00974         case FT_INTELLIGENT_IF:
00975             num_write = 2;
00976             break;
00977         case FT_INTELLIGENT_IF_SLAVE:
00978             num_write = 3;
00979             break;
00980 #ifdef USE_USB
00981         case FT_ROBO_IO_EXTENSION:
00982             out[0] = 0xf2;
00983             num_write = 6;
00984             num_read = 6;
00985             break;
00986         case FT_ROBO_IF_OVER_RF:
00987         case FT_ROBO_RF_DATA_LINK:
00988             usb_endpoint_write = FT_RF_ENDPOINT_INTERRUPT_OUT;
00989             usb_endpoint_read = FT_RF_ENDPOINT_INTERRUPT_IN;
00990 
00991             // init RF
00992             // 0x102 == first RF
00993             // 0x202 == 2nd RF
00994             // ...
00995             //ret = usb_control_msg(hFt->device, 0xc0, 0xfb, 0x102, 0x1, in, 2, FT_USB_TIMEOUT);
00996             ret = usb_control_msg(hFt->device, 0xc0, 0xfb, hFt->transfer_area.RfModulNr << 8 | 0x02, 0x1, in, 2, FT_USB_TIMEOUT);
00997             if (ret != 2) {
00998                 fprintf(stderr, "%d FtThread: Error initiating RF Module!\n");
00999                 area->TransferAktiv = 0;
01000             }
01001             break;
01002 #endif
01003     }
01004 }
01005 
01006 extern int trigger_interface;
01007 
01008 bool ft_handle_devices::guardedFtThreadBegin() {//called every 10ms by the main loop to issue a request, should be non-blocking, guarded by busy flag to avoid multiple pending requests
01009 //viaUsb.putc('.');
01010     __disable_irq();
01011     if (busy) {
01012         if (trigger_interface > 10) { //interface has not responded within 10 slots or response was missed
01013             putc('?',stderr);
01014             busy = false; //release the busy flag to reenable the request-reply process
01015         }
01016         __enable_irq();
01017         return false; //skip the timeslot when previous was not yet handled
01018     }
01019     busy = true;
01020     __enable_irq();
01021     FtThreadBegin();//here the request is sent to the interface
01022     return true;
01023 }
01024 
01025 void ft_handle_devices::FtThreadTrigger() {
01026         trigger_interface++;//this is polled by the main loop
01027     //printf("%d ", trigger_interface);
01028 }
01029 
01030 //here the real data exchange starts
01031 void ft_handle_devices::FtThreadBegin() {//called every 10ms to issue a request, should be non-blocking
01032     int ii_speed = 0;
01033     FT_TRANSFER_AREA *area = &transfer_area;
01034     if (!test_and_set(lock)) {//return when transferarea is in use
01035         busy = false; //release the mutex, otherwise the thread effectively stops
01036         return;//return because there is no point in sending a nonsense request, alternatively the lock can be ignored in which case the data may be inconsistent
01037     }
01038     out[1] = area->M_Main;
01039     out[2] = (area->MPWM_Main[0] & 0x7) | (area->MPWM_Main[1]<<3 & 0x38) | (area->MPWM_Main[2]<<6 & 0xC0);
01040     out[3] = (area->MPWM_Main[2] & 0x1) | (area->MPWM_Main[3]<<1 & 0xE) | (area->MPWM_Main[4]<<4 & 0x70) | (area->MPWM_Main[5]<<7 & 0x80);
01041     out[4] = (area->MPWM_Main[5] & 0x3) | (area->MPWM_Main[6]<<2 & 0x1C) | (area->MPWM_Main[7]<<5 & 0xE0);
01042     out[5] = area->M_Sub1;
01043     out[6] = (area->MPWM_Sub1[0] & 0x7) | (area->MPWM_Sub1[1]<<3 & 0x38) | (area->MPWM_Sub1[2]<<6 & 0xC0);
01044     out[7] = (area->MPWM_Sub1[2] & 0x1) | (area->MPWM_Sub1[3]<<1 & 0xE) | (area->MPWM_Sub1[4]<<4 & 0x70) | (area->MPWM_Sub1[5]<<7 & 0x80);
01045     out[8] = (area->MPWM_Sub1[5] & 0x3) | (area->MPWM_Sub1[6]<<2 & 0x1C) | (area->MPWM_Sub1[7]<<5 & 0xE0);
01046     out[9] = area->M_Sub2;
01047     out[10] = (area->MPWM_Sub2[0] & 0x7) | (area->MPWM_Sub2[1]<<3 & 0x38) | (area->MPWM_Sub2[2]<<6 & 0xC0);
01048     out[11] = (area->MPWM_Sub2[2] & 0x1) | (area->MPWM_Sub2[3]<<1 & 0xE) | (area->MPWM_Sub2[4]<<4 & 0x70) | (area->MPWM_Sub2[5]<<7 & 0x80);
01049     out[12] = (area->MPWM_Sub2[5] & 0x3) | (area->MPWM_Sub2[6]<<2 & 0x1C) | (area->MPWM_Sub2[7]<<5 & 0xE0);
01050     out[13] = area->M_Sub3;
01051     out[14] = (area->MPWM_Sub3[0] & 0x7) | (area->MPWM_Sub3[1]<<3 & 0x38) | (area->MPWM_Sub3[2]<<6 & 0xC0);
01052     out[15] = (area->MPWM_Sub3[2] & 0x1) | (area->MPWM_Sub3[3]<<1 & 0xE) | (area->MPWM_Sub3[4]<<4 & 0x70) | (area->MPWM_Sub3[5]<<7 & 0x80);
01053     out[16] = (area->MPWM_Sub3[5] & 0x3) | (area->MPWM_Sub3[6]<<2 & 0x1C) | (area->MPWM_Sub3[7]<<5 & 0xE0);
01054     out[17]    = 0;
01055     out[18]    = 0;
01056     out[19]    = 0;
01057     out[20]    = 0;
01058     out[21]    = 0;
01059     out[22]    = 0;
01060     out[23]    = 0;
01061     out[24]    = 0;
01062     out[25]    = 0;
01063     out[26]    = 0;
01064     out[27]    = 0;
01065     out[28]    = 0;
01066     out[29]    = 0;
01067     out[30]    = 0;
01068     out[31]    = 0;
01069 
01070     // For the II we need to simulate different speeds here
01071     if (type == FT_INTELLIGENT_IF || type == FT_INTELLIGENT_IF_SLAVE) {
01072         int iCurMotor;
01073         for (iCurMotor = 0; iCurMotor < 7; iCurMotor++) {
01074             if (area->MPWM_Main[iCurMotor] < ii_speed) out[1] &= ~(1 << iCurMotor);
01075             if (area->MPWM_Sub1[iCurMotor] < ii_speed) out[5] &= ~(1 << iCurMotor);
01076         }
01077 
01078         ii_speed++;
01079         if (ii_speed > 7) ii_speed = 0;
01080     }
01081 
01082     if (type == FT_INTELLIGENT_IF) {
01083         cycle++;
01084         num_read = 1;
01085         out[0] = 0xC1;
01086         if (cycle % 20) { // EX
01087             out[0] = 0xC5;
01088             num_read = 3;
01089         } else if (cycle % 10) { // EY
01090             out[0] = 0xC9;
01091             num_read = 3;
01092         }
01093     } else if (type == FT_INTELLIGENT_IF_SLAVE) {
01094         cycle++;
01095         num_read = 2;
01096         out[0] = 0xC2;
01097         out[2] = out[5];
01098         if (cycle % 20) { // EX
01099             out[0] = 0xC6;
01100             num_read = 4;
01101         } else if (cycle % 10) { // EY
01102             out[0] = 0xCA;
01103             num_read = 4;
01104         }
01105     }
01106 //viaUsb.putc('-');
01107     increment(lock);//release the lock on shared memeory
01108     int ret = 0;
01109     switch (type) {//send the request
01110 #ifdef USE_USB
01111         case FT_ROBO_IF_USB:
01112         case FT_ROBO_IO_EXTENSION:
01113         case FT_ROBO_IF_OVER_RF:
01114         case FT_ROBO_RF_DATA_LINK:
01115             ret = usb_interrupt_write(hFt->device, usb_endpoint_write, out, num_write, FT_USB_TIMEOUT);
01116             break;
01117 #endif
01118         case FT_ROBO_IF_COM:
01119         case FT_INTELLIGENT_IF:
01120         case FT_INTELLIGENT_IF_SLAVE:
01121             // ret = write(sdev, out, num_write);
01122             //sdev->dmaSend(out, num_write);
01123             ret = write();//start the transfer of the 'out' buffer, when complete the read_callback will receive the reply and when the reply is complete FtThreadEnd will be called
01124 //                viaUsb.putc(';');
01125             break;
01126     }
01127     if (ret != num_write) {
01128         interface_connected = 0;
01129         fprintf(stderr, "FtThread: Error writing to the Interface...exiting!\n");
01130     }
01131 }
01132 
01133 void ft_handle_devices::FtThreadEnd() {//called by the receiver/dma callback when the reply is complete
01134     int ret = 0;
01135     FT_TRANSFER_AREA *area = &transfer_area;
01136     switch (type) { //receive the reply
01137 #ifdef USE_USB
01138         case FT_ROBO_IF_USB:
01139         case FT_ROBO_IO_EXTENSION:
01140         case FT_ROBO_IF_OVER_RF:
01141         case FT_ROBO_RF_DATA_LINK:
01142             ret = usb_interrupt_read(hFt->device, usb_endpoint_read, in, num_read, FT_USB_TIMEOUT);
01143             break;
01144 #endif
01145         case FT_ROBO_IF_COM:
01146         case FT_INTELLIGENT_IF:
01147         case FT_INTELLIGENT_IF_SLAVE:
01148 //            ret = read(sdev, in, num_read);
01149             ret = num_read;
01150 //                viaUsb.putc('/');
01151             break;
01152     }
01153     if (ret != num_read) {
01154         interface_connected = 0;
01155         fprintf(stderr, "FtThread: Error reading from the Interface\n");
01156         return;
01157     }
01158 
01159     if (!test_and_set(lock)) {//skip when busy
01160         busy = false;
01161         return;
01162     }
01163     area->ChangeEg = area->E_Main != in[0] || area->E_Sub1 != in[1] || area->E_Sub2 != in[2] || area->E_Sub3 != in[3];
01164     area->E_Main = in[0];
01165     area->E_Sub1 = in[1];
01166     area->E_Sub2 = in[2];
01167     area->E_Sub3 = in[3];
01168     area->ChangeAn = 1; //assume that analog always changes (noise)
01169     area->AX = in[4];
01170     area->AY = in[5];
01171     area->A1 = in[6];
01172     area->A2 = in[7];
01173     area->AX |= (in[8] & 0x3) << 8;
01174     area->AY |= (in[8] & 0xC) << 6;
01175     area->A1 |= (in[8] & 0x30) << 4;
01176     area->A2 |= (in[8] & 0xC0) << 2;
01177     area->AZ = in[9];
01178     area->D1 = in[10];
01179     area->D2 = in[11];
01180     area->AV = in[12];
01181     area->AZ |= (in[13] & 0x3) << 8;
01182     area->D1 |= (in[13] & 0xC) << 6;
01183     area->D2 |= (in[13] & 0x30) << 4;
01184     area->AV |= (in[13] & 0xC0) << 2;
01185     if (area->IRKeys != in[14])
01186         area->ChangeIr = 1;
01187     area->IRKeys = in[14];
01188     area->BusModules = in[15];
01189     // 16
01190     area->AXS1 = in[17];
01191     area->AXS2 = in[18];
01192     area->AXS3 = in[19];
01193     area->AXS1 |= (in[20] & 0x3) << 8;
01194     area->AXS2 |= (in[20] & 0xC) << 6;
01195     area->AXS3 |= (in[20] & 0x30) << 4;
01196     // 21
01197     area->AVS1 = in[22];
01198     area->AVS2 = in[23];
01199     area->AVS3 = in[24];
01200     area->AVS1 |= (in[25] & 0x3) << 8;
01201     area->AVS2 |= (in[25] & 0xC) << 6;
01202     area->AVS3 |= (in[25] & 0x30) << 4;
01203     // 26...42
01204     if (type == FT_INTELLIGENT_IF) {
01205         if (cycle % analogcycle) { // EX
01206             area->AX = in[1] & (8<<in[2]);
01207         } else if (cycle % (2*analogcycle)) { // EY
01208             area->AY = in[1] & (8<<in[2]);
01209         }
01210     } else if (type == FT_INTELLIGENT_IF_SLAVE) {
01211         if (cycle % analogcycle) { // EX
01212             area->AX = in[1] & (8<<in[2]);
01213         } else if (cycle % (2*analogcycle)) { // EY
01214             area->AY = in[1] & (8<<in[2]);
01215         }
01216     }
01217     increment(lock);
01218     interface_connected = 1;
01219     if (ne.NotificationCallback) {
01220 //        printf("%02X\r", transfer_area.E_Main);
01221         (*ne.NotificationCallback)(ne.Context);
01222     }
01223     busy = false;
01224 }
01225 
01226 void ft_handle_devices::FtThreadFinish() {//called by StopFtTransferArea
01227 #ifdef USE_USB
01228     if (hFt->type == FT_ROBO_IF_OVER_RF || hFt->type == FT_ROBO_RF_DATA_LINK) {
01229         ret = usb_control_msg(hFt->device, 0xc0, 0x21, hFt->transfer_area.RfModulNr << 8, 0, in, 1, FT_USB_TIMEOUT);
01230         if (ret != 1 || in[0] != 0xd7) {
01231             fprintf(stderr, "Error uninitiating RF Module!\n");
01232         }
01233     }
01234 #endif
01235 #ifdef MBED
01236     sdev->attach(0,Serial::RxIrq);
01237     sdev->attach(0,Serial::TxIrq);
01238 #endif
01239     transfer_area.TransferAktiv = 0;
01240 }
01241 
01242 void ft_handle_devices::FtThread() {
01243 //    ::FtThread(this);
01244 //    printf("%02X\r", transfer_area.E_Main);
01245 //    viaUsb.putc('.');
01246 }
01247 
01248 #endif
01249 
01250 /**
01251  * \brief reset outputs
01252  *
01253  * Will clear all outputs.
01254  *
01255  * @return Always FTLIB_ERR_SUCCESS
01256  */
01257 long int ResetFtTransfer(FT_HANDLE hFt) {
01258     FT_TRANSFER_AREA *area = &hFt->transfer_area;
01259 
01260     area->M_Main = 0;
01261     area->M_Sub1 = 0;
01262     area->M_Sub2 = 0;
01263     area->M_Sub3 = 0;
01264 
01265     return FTLIB_ERR_SUCCESS;
01266 }
01267 
01268 
01269 /**
01270  * \brief Starts the communication thread.
01271  *
01272  * This function is needed to start the communication with the interface in passive mode.
01273  * Get the handle with GetFtUsbDeviceHandle(), GetFtUsbDeviceHandleSerialNr() or OpenFtCommDevice().
01274  *
01275  * @see GetFtUsbDeviceHandle()
01276  * @see GetFtUsbDeviceHandleSerialNr()
01277  * @see OpenFtCommDevice()
01278  * @param hFt Handle of the interface.
01279  * @param ignored The second argument is ignored in this version.
01280  * @return Everything except FTLIB_ERR_SUCCESS indicates an error.
01281  */
01282 long int StartFtTransferArea(FT_HANDLE hFt, NOTIFICATION_EVENTS* ev) {
01283     int ret;
01284 
01285     if (hFt == NULL) {
01286         fprintf(stderr, "StartFtTransferArea: No such device\n");
01287         return NO_FT_DEVICE;
01288     }
01289     if (ev)
01290         hFt->ne = *ev; //copy the entire struct
01291     else
01292         memset(&hFt->ne, 0, sizeof(NOTIFICATION_EVENTS));
01293 #ifdef MBED
01294 //at least for serial devices another solution must be found. A normal request/reply uses the entire 10 ms, this is OK but the CPU should not wait for it
01295 //either a buffer or a DMA scheme must be used to free CPU time, this means that at the beginning of the time slot the req. buffer is prepared and
01296 //handed over to IRQ/USB, the reply is gathered in a buffer and when complete the transfer area is updated.
01297     hFt->t = new Ticker;
01298     //printf("ticker created\n");
01299     hFt->FtThreadInit();//setup buffers and serial handlers
01300     //hFt->t->attach_us(hFt, &ft_handle_devices::FtThreadBegin, INTERFACE_QUERY_TIME);
01301     hFt->t->attach_us(hFt, &ft_handle_devices::FtThreadTrigger, INTERFACE_QUERY_TIME);//FtThreadTrigger just sets a global variable that is polled by the main loop, which subsequently calls guardedFtThreadBegin
01302     printf("thread attached\n");
01303     ret = 0;
01304 #else
01305     ret = pthread_create(&hFt->t, NULL, (void *)FtThread, hFt);
01306 #endif
01307     usleep(INTERFACE_QUERY_TIME*10);
01308     if (ret != 0) {
01309         perror("StartFtTransferArea pthread_create");
01310         return ret;
01311     }
01312 
01313     return FTLIB_ERR_SUCCESS;
01314 }
01315 
01316 
01317 /**
01318  * \brief Starts the communication thread.
01319  *
01320  * Since notification are ignored in this version, will just call StartFtTransferArea().
01321  *
01322  * @see StartFtTransferArea()
01323  */
01324 long int StartFtTransferAreaWithCommunication(FT_HANDLE hFt, NOTIFICATION_EVENTS* ignored) {
01325     return StartFtTransferArea(hFt, ignored);
01326 }
01327 
01328 
01329 /**
01330  * \brief Get the transfer area
01331  *
01332  * This function will return a pointer to the transfer area of the given handle.
01333  *
01334  * @param hFt Handle of the device.
01335  * @return transfer area or NULL on error.
01336  */
01337 FT_TRANSFER_AREA* GetFtTransferAreaAddress(FT_HANDLE hFt) {
01338     if (hFt == NULL) {
01339         fprintf(stderr, "GetFtTransferAreaAddress: No such device\n");
01340         return NULL;
01341     }
01342     return &hFt->transfer_area;
01343 }
01344 
01345 
01346 /**
01347  * \brief Stops the communication thread.
01348  * \warning Will block a few microseconds until thread stopped.
01349  *
01350  * This function will stop the communication thread.
01351  *
01352  * @see StartFtTransferArea()
01353  * @param hFt Handle of the Interface.
01354  * @return Everything except FTLIB_ERR_SUCCESS indicates an error.
01355  */
01356 long int StopFtTransferArea(FT_HANDLE hFt) {
01357     int ret;
01358 
01359     if (hFt == NULL) {
01360         fprintf(stderr, "StopFtTransferArea: No such device\n");
01361         return NO_FT_DEVICE;
01362     }
01363 
01364 #ifdef MBED
01365     hFt->t->detach();
01366     delete hFt->t;
01367     hFt->FtThreadFinish();
01368 #else
01369     usleep(INTERFACE_QUERY_TIME*10); // wait to make sure the last command is send to the interface
01370     if (hFt->transfer_area.TransferAktiv == 1) {
01371         hFt->transfer_area.TransferAktiv = 2; // cleaner then pthread_cancel()
01372     }
01373     if ((ret = pthread_join(hFt->t, NULL)) != 0) return ret;
01374 #endif
01375     return FTLIB_ERR_SUCCESS;
01376 }
01377 
01378 
01379 /**
01380  * \brief check if transfer is active.
01381  *
01382  * Check if we are currently communicating with the device.
01383  *
01384  * @param hFt Handle of the Interface.
01385  * @return FTLIB_ERR_THREAD_IS_RUNNING or FTLIB_ERR_THREAD_NOT_RUNNING
01386  */
01387 long int IsFtTransferActiv(FT_HANDLE hFt) {
01388     if (hFt == NULL) {
01389         fprintf(stderr, "StopFtTransferArea: No such device\n");
01390         return NO_FT_DEVICE;
01391     }
01392 
01393     if (hFt->transfer_area.TransferAktiv) return FTLIB_ERR_THREAD_IS_RUNNING;
01394 
01395     return FTLIB_ERR_THREAD_NOT_RUNNING;
01396 }
01397 
01398 
01399 #ifdef USE_DOWNLOAD
01400 /**
01401  * \brief Upload a program to the interface
01402  *
01403  * Upload (download from the perspective of the interface) a program to the interface.
01404  *
01405  * @param hFt Handle of the Interface
01406  * @param dwMemBlock Destination 0 (Flash 1), 1 (Flash 2) or 2 (Ram)
01407  * @param pbArray Pointer to the program to upload
01408  * @param dwSize Size of the program to upload
01409  * @param dwParameter 1 to Autostart this program, else 0.
01410  * @param pbName Name of the program to upload
01411  * @param dwNameLen Length of the name
01412  * @return FTLIB_ERR_SUCCESS if you got lucky
01413  */
01414 long int DownloadFtProgram(FT_HANDLE hFt, long int dwMemBlock, unsigned char *pbArray, long int dwSize, long int dwParameter, unsigned char *pbName, long int dwNameLen) {
01415     int ret;
01416     unsigned char buffer[128];
01417     long int i;
01418     crc_t crc;
01419     int memblockarg;
01420 
01421     if (hFt == NULL) {
01422         fprintf(stderr, "DownloadFtProgram: No such device\n");
01423         return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
01424     } else if (hFt->type != FT_ROBO_IF_USB) {
01425         fprintf(stderr, "DownloadFtProgram: Sorry, I can only handle the Robo Interface over USB at this time.\n");
01426         return FTLIB_ERR_NOT_SUPPORTED;
01427     }
01428 
01429     switch (dwMemBlock) {
01430         case 0x0:    // flash 1
01431             memblockarg = 0x100;
01432             if (dwParameter == 1) memblockarg += 0x100;
01433             break;
01434         case 0x1:    // flash 2
01435             memblockarg = 0x101;
01436             if (dwParameter == 1) fprintf(stderr, "Warning: Autostart for flash 2 not supported\n");
01437             break;
01438         case 0x2:    // ram
01439             memblockarg = 0x102;
01440             if (dwParameter == 1) fprintf(stderr, "Warning: Autostart for RAM not supported\n");
01441             break;
01442         case 0xf0:    // firmware A
01443             memblockarg = 0xf200;
01444             break;
01445         case 0xf1:    // firmware B
01446             memblockarg = 0xf201;
01447             break;
01448         default:
01449             fprintf(stderr, "Unknown Memblock Target\n");
01450             return FTLIB_ERR_DOWNLOAD_WRONG_MEM_BLOCK;
01451     }
01452 
01453     // init upload
01454     ret = usb_control_msg(hFt->device, 0xc0, 0xf0, 0x20, 0, buffer, 1, FT_USB_TIMEOUT_LONG);
01455     if (ret < 0) {
01456         fprintf(stderr, "Error sending control msg 0xC0 0xF0\n");
01457         return ret;
01458     }
01459     if (buffer[0] != 1) {
01460         fprintf(stderr, "Error uploading Program: Return value for 0xC0 0xF0 is 0x%x\n", buffer[0]);
01461         return FTLIB_ERR_DOWNLOAD;
01462     }
01463 
01464     // write name
01465     memset(buffer, 0, 128); // clean buffer
01466     if (pbName != NULL)
01467         strncpy(buffer, pbName, MIN(dwNameLen, 80)); // copy to buffer, so we not change the original content
01468     ret = usb_control_msg(hFt->device, 0x40, 0x10, memblockarg, dwSize/PROGRAM_UPLOAD_PACKET_SIZE, buffer, 80, FT_USB_TIMEOUT_LONG);
01469     if (ret < 0) {
01470         fprintf(stderr, "Error sending control msg 0x40 0x10\n");
01471         return ret;
01472     }
01473 
01474     // check
01475     ret = usb_control_msg(hFt->device, 0xC0, 0x20, 0x0, 0x0, buffer, 1, FT_USB_TIMEOUT_LONG);
01476     if (ret < 0) {
01477         fprintf(stderr, "Error sending control ms 0xC0 0x20g\n");
01478         return ret;
01479     }
01480     if (buffer[0] != dwMemBlock || (buffer[0] == 0 && memblockarg == 0xf200) || (buffer[0] == 1 && memblockarg == 0xf201)) {
01481         fprintf(stderr, "Upload Error: Target mismatch\n");
01482     }
01483 
01484     // write the data
01485     for (i=0; dwSize >= PROGRAM_UPLOAD_PACKET_SIZE; i++, dwSize -= PROGRAM_UPLOAD_PACKET_SIZE) {
01486         memset(buffer, 0, 128); // clean buffer
01487         memcpy(buffer, pbArray + (i*PROGRAM_UPLOAD_PACKET_SIZE), MIN(dwSize, PROGRAM_UPLOAD_PACKET_SIZE)); // make sure we not change the original content
01488 
01489         crc = crc_init();
01490         crc = crc_update(crc, buffer, PROGRAM_UPLOAD_PACKET_SIZE);
01491         crc = crc_finalize(crc);
01492 
01493         // write 128 byte
01494         /*printf("CRC: 0x%x\n", crc);
01495         printf("Paket: 0x%x\n", i+1);
01496         for(k=0; k<128; k++) {
01497             printf("0x%x ", buffer[k]);
01498             if ((k+1) % 16 == 0 && k != 0) printf("\n");
01499         }
01500         printf("\n");*/
01501         ret = usb_control_msg(hFt->device, 0x40, 0x11, i+1, crc, buffer, PROGRAM_UPLOAD_PACKET_SIZE, FT_USB_TIMEOUT_LONG);
01502         if (ret < 0) {
01503             fprintf(stderr, "Error sending control msg 0x40 0x11 0x%x\n", i+1);
01504             return ret;
01505         }
01506 
01507         // check
01508         ret = usb_control_msg(hFt->device, 0xC0, 0x20, 0x0, 0x0, buffer, 1, FT_USB_TIMEOUT_LONG);
01509         if (ret < 0) {
01510             fprintf(stderr, "Error sending control msg 0xC0 0x20\n");
01511             return ret;
01512         }
01513         if (buffer[0] != 1) {
01514             fprintf(stderr, "Error uploading Program: Return value for 0xC0, 0x20 is 0x%x\n", buffer[0]);
01515             return FTLIB_ERR_DOWNLOAD;
01516         }
01517     }
01518 
01519     return FTLIB_ERR_SUCCESS;
01520 }
01521 
01522 
01523 /**
01524  * \brief Start a program
01525  *
01526  * Will start a program that has been Successfully uploaded to the interface.
01527  *
01528  * @param hFt Handle of the Interface
01529  * @param dwMemBlock Destination 0 (Flash 1), 1 (Flash 2) or 2 (Ram)
01530  * @return FTLIB_ERR_SUCCESS or FTLIB_ERR_IF_NO_PROGRAM
01531  */
01532 long int StartFtProgram(FT_HANDLE hFt, long int dwMemBlock) {
01533     int ret;
01534     unsigned char buffer[2];
01535 
01536     if (hFt == NULL) {
01537         fprintf(stderr, "StartFtProgram: No such device\n");
01538         return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
01539     }
01540 
01541     switch (hFt->type) {
01542         case FT_ROBO_IF_USB:
01543             // note: serial documentation says 0xf4 here, sniffer says 0x12
01544             ret = usb_control_msg(hFt->device, 0xc0, 0x12, dwMemBlock, 0, buffer, 1, FT_USB_TIMEOUT_LONG);
01545             if (ret < 0) {
01546                 fprintf(stderr, "Error sending control msg 0xC0 0xF4\n");
01547                 return ret;
01548             }
01549             if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS;
01550             else return FTLIB_ERR_IF_NO_PROGRAM;
01551             break;
01552         case FT_ROBO_IF_COM:
01553             buffer[0] = 0xf4;
01554             buffer[1] = dwMemBlock;
01555             if ((write(hFt->sdev, &buffer, 2)) != 2 || (read(hFt->sdev, &buffer, 1)) != 1) {
01556                 return FTLIB_ERR_IF_NO_PROGRAM;
01557             }
01558             if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS;
01559             else return FTLIB_ERR_IF_NO_PROGRAM;
01560             break;
01561     }
01562 
01563     return FTLIB_ERR_NOT_SUPPORTED;
01564 }
01565 
01566 
01567 /**
01568  * \brief Stop a program
01569  *
01570  * Will stop the current running program that has been uploaded to the interface.
01571  *
01572  * @param hFt Handle of the Interface
01573  * @return FTLIB_ERR_SUCCESS or FTLIB_ERR_IF_NO_PROGRAM
01574  */
01575 long int StopFtProgram(FT_HANDLE hFt) {
01576     int ret;
01577     unsigned char buffer[1];
01578 
01579     if (hFt == NULL) {
01580         fprintf(stderr, "StopFtProgram: No such device\n");
01581         return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
01582     }
01583 
01584     switch (hFt->type) {
01585         case FT_ROBO_IF_USB:
01586             // note: serial documentation says 0xf8 here, sniffer says 0x13
01587             ret = usb_control_msg(hFt->device, 0xc0, 0x13, 0, 0, buffer, 1, FT_USB_TIMEOUT_LONG);
01588             if (ret < 0) {
01589                 fprintf(stderr, "Error sending control msg 0xC0 0x13\n");
01590                 return ret;
01591             }
01592 
01593             if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS;
01594             else return FTLIB_ERR_IF_NO_PROGRAM;
01595             break;
01596         case FT_ROBO_IF_COM:
01597             buffer[0] = 0xf8;
01598             if ((write(hFt->sdev, &buffer, 1)) != 1 || (read(hFt->sdev, &buffer, 1)) != 1) {
01599                 return FTLIB_ERR_IF_NO_PROGRAM;
01600             }
01601             if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS;
01602             else return FTLIB_ERR_IF_NO_PROGRAM;
01603             break;
01604     }
01605 
01606     return FTLIB_ERR_NOT_SUPPORTED;
01607 }
01608 
01609 
01610 /**
01611  * \brief Delete a program
01612  *
01613  * Will delete a program that has been uploaded to the interface.
01614  *
01615  * @param hFt Handle of the Interface
01616  * @param dwMemBlock Destination 0 (Flash 1), 1 (Flash 2) or 2 (Ram)
01617  * @return FTLIB_ERR_SUCCESS or FTLIB_ERR_IF_NO_PROGRAM
01618  */
01619 long int DeleteFtProgram(FT_HANDLE hFt, long int dwMemBlock) {
01620     int ret;
01621     unsigned char buffer[2];
01622 
01623     if (hFt == NULL) {
01624         fprintf(stderr, "DeleteFtProgram: No such device\n");
01625         return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
01626     }
01627 
01628     switch (hFt->type) {
01629         case FT_ROBO_IF_USB:
01630             ret = usb_control_msg(hFt->device, 0xc0, 0xf5, dwMemBlock, 0, buffer, 1, FT_USB_TIMEOUT_LONG);
01631             if (ret < 0) {
01632                 fprintf(stderr, "Error sending control msg 0xC0 0xF5\n");
01633                 return ret;
01634             }
01635 
01636             if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS;
01637             else return FTLIB_ERR_IF_NO_PROGRAM;
01638             break;
01639         case FT_ROBO_IF_COM:
01640             buffer[0] = 0xf5;
01641             buffer[1] = dwMemBlock;
01642             if ((write(hFt->sdev, &buffer, 2)) != 2 || (read(hFt->sdev, &buffer, 1)) != 1) {
01643                 return FTLIB_ERR_IF_NO_PROGRAM;
01644             }
01645             if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS;
01646             else return FTLIB_ERR_IF_NO_PROGRAM;
01647             break;
01648     }
01649 
01650     return FTLIB_ERR_NOT_SUPPORTED;
01651 }
01652 
01653 
01654 /**
01655  * \brief Activate a program
01656  *
01657  * Will activate a program that has been uploaded to the interface.
01658  *
01659  * @param hFt Handle of the Interface
01660  * @param dwMemBlock Destination 0 (Flash 1) or 1 (Flash 2)
01661  * @return FTLIB_ERR_SUCCESS or FTLIB_ERR_IF_NO_PROGRAM
01662  */
01663 long int SetFtProgramActiv(FT_HANDLE hFt, long int dwMemBlock) {
01664     int ret;
01665     unsigned char buffer[1];
01666 
01667     if (hFt == NULL) {
01668         fprintf(stderr, "SetFtProgramActiv: No such device\n");
01669         return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
01670     }
01671 
01672     switch (hFt->type) {
01673         case FT_ROBO_IF_USB:
01674             ret = usb_control_msg(hFt->device, 0xc0, 0xf9, dwMemBlock, 0, buffer, 1, FT_USB_TIMEOUT_LONG);
01675             if (ret < 0) {
01676                 fprintf(stderr, "Error sending control msg 0xC0 0xf9\n");
01677                 return ret;
01678             }
01679 
01680             if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS;
01681             else return FTLIB_ERR_IF_NO_PROGRAM;
01682             break;
01683         case FT_ROBO_IF_COM:
01684             buffer[0] = 0xf9;
01685             buffer[1] = dwMemBlock;
01686             if ((write(hFt->sdev, &buffer, 2)) != 2 || (read(hFt->sdev, &buffer, 1)) != 1) {
01687                 return FTLIB_ERR_IF_NO_PROGRAM;
01688             }
01689             if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS;
01690             else return FTLIB_ERR_IF_NO_PROGRAM;
01691             break;
01692     }
01693 
01694     return FTLIB_ERR_NOT_SUPPORTED;
01695 }
01696 
01697 
01698 /**
01699  * \brief Get the name of a program
01700  *
01701  * Will write the name of a program that has been uploaded to the interface to a given area.
01702  *
01703  * @param hFt Handle of the Interface
01704  * @param dwMemBlock Destination 0 (Flash 1), 1 (Flash 2) or 2 (Ram)
01705  * @param pName Pointer to the area where we can store the name
01706  * @param dwSize Size of the area to store the name to
01707  * @return FTLIB_ERR_SUCCESS or FTLIB_ERR_IF_NO_PROGRAM
01708  */
01709 long int GetFtProgramName(FT_HANDLE hFt, long int dwMemBlock, long int dwSize, void *pName) {
01710     int ret;
01711     unsigned char buffer[dwSize+1];
01712 
01713     if (hFt == NULL) {
01714         fprintf(stderr, "GetFtProgramName: No such device\n");
01715         return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
01716     }
01717 
01718     switch (hFt->type) {
01719         case FT_ROBO_IF_USB:
01720             ret = usb_control_msg(hFt->device, 0xc0, 0xfa, dwMemBlock, 0, buffer, dwSize + 1, FT_USB_TIMEOUT_LONG);
01721             if (ret < 0) {
01722                 fprintf(stderr, "Error sending control msg 0xC0 0xFA\n");
01723                 return ret;
01724             }
01725             memcpy(pName, buffer+1, ret-1);
01726 
01727             if (buffer[0] == 0x1) return FTLIB_ERR_SUCCESS;
01728             if (buffer[0] == 0xf3) return FTLIB_ERR_IF_NO_PROGRAM;
01729             return buffer[1];
01730             break;
01731         case FT_ROBO_IF_COM:
01732             buffer[0] = 0xfa;
01733             buffer[1] = dwMemBlock;
01734             if ((write(hFt->sdev, &buffer, 2)) != 2 || (ret = read(hFt->sdev, &buffer, dwSize+1)) < 0 || buffer[0] != 0x01) {
01735                 return FTLIB_ERR_IF_NO_PROGRAM;
01736             }
01737             memcpy(pName, buffer+1, ret-1);
01738             if (buffer[0] == 0x1) return FTLIB_ERR_SUCCESS;
01739             break;
01740     }
01741 
01742     return FTLIB_ERR_NOT_SUPPORTED;
01743 }
01744 
01745 
01746 /**
01747  * \brief Checks if a program is running
01748  *
01749  * Checks if a program is currently running.
01750  *
01751  * @param hFt Handle of the Interface
01752  * @param num Area where we can store the number of the running program.
01753  * @return 1 if a program is running, else 0
01754  */
01755 int GetFtStatus(FT_HANDLE hFt, int *num) {
01756     int ret;
01757     unsigned char buffer[3];
01758 
01759     if (hFt == NULL) {
01760         fprintf(stderr, "GetFtStatus: No such device\n");
01761         return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
01762     }
01763 
01764     switch (hFt->type) {
01765         case FT_ROBO_IF_USB:
01766             // test replace 0xf0 with 0x50
01767             ret = usb_control_msg(hFt->device, 0xc0, 0xf0, 0x3, 0, buffer, 3, FT_USB_TIMEOUT);
01768             if (ret < 0) {
01769                 fprintf(stderr, "Error sending control msg 0xC0 0xF0\n");
01770                 return ret;
01771             }
01772             ret = buffer[1];
01773             *num = buffer[2];
01774             break;
01775         case FT_ROBO_IF_COM:
01776             buffer[0] = 0xf0;
01777             buffer[1] = 0x3;
01778             if ((write(hFt->sdev, &buffer, 2)) != 2 || (ret = read(hFt->sdev, &buffer, 3)) < 0 || buffer[0] != 0xfc) {
01779                 return ret;
01780             }
01781             ret = buffer[1];
01782             *num = buffer[2];
01783             break;
01784         default:
01785             return FTLIB_ERR_NOT_SUPPORTED;
01786     }
01787 
01788     return ret;
01789 }
01790 #endif //USE_DOWNLOAD
01791 
01792 /**
01793  * \brief Get the firmware number of this interface.
01794  *
01795  * Returns the firmware number of the interface squashed into a single int.
01796  *
01797  * @param hFt Handle of the Interface
01798  * @return Firmware number as int byte4 | byte3 | byte2 | byte1, 0 on error.
01799  */
01800 long int GetFtFirmware(FT_HANDLE hFt) {//makes a blocking comm request
01801     int ret;
01802     unsigned char buffer[35] = { 0 };
01803     long int firmware = 0;
01804 
01805     if (hFt == NULL) {
01806         fprintf(stderr, "GetFtFirmware: No such device\n");
01807         return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
01808     }
01809 
01810 
01811     switch (hFt->type) {
01812         case FT_INTELLIGENT_IF:
01813         case FT_INTELLIGENT_IF_SLAVE:
01814             return 0;
01815 #ifdef USE_USB
01816         case FT_ROBO_IF_USB:
01817         case FT_ROBO_IO_EXTENSION:
01818         case FT_ROBO_RF_DATA_LINK:
01819             ret = usb_control_msg(hFt->device, 0xc0, 0xf0, 0x1, 0, buffer, 5, FT_USB_TIMEOUT);
01820             if (ret < 0) {
01821                 fprintf(stderr, "Error sending control msg 0xC0 0xF0\n");
01822                 return 0;
01823             }
01824             firmware = buffer[1] | buffer[2]<<8 | buffer[3]<<16 | buffer[4]<<24;
01825             break;
01826         case FT_ROBO_IF_OVER_RF:
01827             ret = usb_control_msg(hFt->device, 0xc0, 0x52, hFt->transfer_area.RfModulNr<<8 | 0x05, 0, buffer, 35, FT_USB_TIMEOUT);
01828             if (ret < 0) {
01829                 fprintf(stderr, "Error sending control msg 0xC0 0x52\n");
01830                 return 0;
01831             }
01832             if (buffer[0] == 0xfa && buffer[1] == 0) { // buffer[1] == 0xff => no device
01833                 firmware = buffer[23]<<24 | buffer[22]<<16 | buffer[21]<<8 | buffer[20];
01834             }
01835             break;
01836 #endif
01837         case FT_ROBO_IF_COM:
01838             buffer[0] = 0xf0;
01839             buffer[1] = 0x01;
01840 #ifdef MBED
01841 //printf("requesting FW\n");
01842             //ret = hFt->sdev->printf("%2c", buffer);
01843             ret = write(hFt->sdev, buffer, 2);
01844 //            printf("request was sent %d\n", ret);
01845 #else
01846             ret = write(hFt->sdev, &buffer, 2);
01847 #endif
01848             if (ret != 2) {
01849                 fprintf(stderr, "Error writing msg 0xF0 0x01\n");
01850                 return 0;
01851             }
01852 #ifdef MBED
01853             //ret = hFt->sdev->scanf("%5c", buffer)==1 ? 5 : 0 ;
01854             ret = read(hFt->sdev, buffer, 5);
01855 #else
01856             ret = read(hFt->sdev, &buffer, 5);
01857 #endif
01858             if (ret != 5) {
01859                 fprintf(stderr, "Error reading msg 0xF0 0x01\n");
01860                 return 0;
01861             }
01862             firmware = buffer[1] | buffer[2]<<8 | buffer[3]<<16 | buffer[4]<<24;
01863 //            printf("fw: %ld\n", firmware);
01864             break;
01865         default:
01866             return FTLIB_ERR_NOT_SUPPORTED;
01867     }
01868 
01869     return firmware;
01870 }
01871 
01872 
01873 /**
01874  * \brief Get the firmware number of this interface.
01875  *
01876  * Returns the firmware number of the interface with this handle.
01877  * The allocated space should be freed with free() later.
01878  *
01879  * @param hFt Handle of the Interface
01880  * @return Pointer to a string with the firmware
01881  */
01882 char *GetFtFirmwareStrg(FT_HANDLE hFt) {
01883     long int ifw = GetFtFirmware(hFt);
01884     char *s = (char *)malloc(16);
01885     int byte1 = ifw & 0xff;
01886     int byte2 = (ifw & 0xff00) >> 8;
01887     int byte3 = (ifw & 0xff0000) >> 16;
01888     int byte4 = (ifw & 0xff000000) >> 24;
01889 
01890     snprintf(s, 16, "%d.%02d.%02d.%02d", byte4, byte3, byte2, byte1);
01891 
01892     return s;
01893 }
01894 
01895 
01896 #ifndef NOTNOW
01897 /**
01898  * \brief Get the serial number of this interface.
01899  *
01900  * Returns the serial number of the interface squashed into a single int.
01901  *
01902  * @param hFt Handle of the Interface
01903  * @return Serial number as int byte4 | byte3 | byte2 | byte1, 0 on error.
01904  */
01905 long int GetFtSerialNr(FT_HANDLE hFt) {
01906     int ret;
01907     unsigned char buffer[35] = { 0 };
01908     long int serial = 0;
01909 
01910     if (hFt == NULL) {
01911         fprintf(stderr, "GetFtSerialNr: No such device\n");
01912         return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
01913     }
01914 
01915 
01916     switch (hFt->type) {
01917         case FT_INTELLIGENT_IF:
01918         case FT_INTELLIGENT_IF_SLAVE:
01919             return 0;
01920             break;
01921         case FT_ROBO_IF_USB:
01922             ret = usb_control_msg(hFt->device, 0xc0, 0xf0, 0x2, 0, buffer, 5, FT_USB_TIMEOUT);
01923             if (ret < 0) {
01924                 fprintf(stderr, "Error sending control msg 0xC0 0xF0\n");
01925                 return 0;
01926             }
01927             serial = buffer[1] + buffer[2]*100 + buffer[3]*10000 + buffer[4]*1000000;
01928             break;
01929         case FT_ROBO_IO_EXTENSION:
01930             ret = usb_control_msg(hFt->device, 0xc0, 0xf0, 0x2, 0, buffer, 14, FT_USB_TIMEOUT);
01931             if (ret < 0) {
01932                 fprintf(stderr, "Error sending control msg 0xC0 0xF0\n");
01933                 return 0;
01934             }
01935             serial = buffer[1] + buffer[2]*100 + buffer[3]*10000 + buffer[4]*1000000;
01936             break;
01937         case FT_ROBO_RF_DATA_LINK:
01938             ret = usb_control_msg(hFt->device, 0xc0, 0xf0, 0x2, 0, buffer, 14, FT_USB_TIMEOUT);
01939             if (ret < 0) {
01940                 fprintf(stderr, "Error sending control msg 0xC0 0x52\n");
01941                 return 0;
01942             }
01943             serial = buffer[1] + buffer[2]*100 + buffer[3]*10000 + buffer[4]*1000000;
01944             break;
01945         case FT_ROBO_IF_OVER_RF:
01946             ret = usb_control_msg(hFt->device, 0xc0, 0x52, hFt->transfer_area.RfModulNr<<8 | 0x05, 0, buffer, 35, FT_USB_TIMEOUT);
01947             if (ret < 0) {
01948                 fprintf(stderr, "Error sending control msg 0xC0 0x52\n");
01949                 return 0;
01950             }
01951             if (buffer[0] == 0xfa && buffer[1] == 0) { // buffer[1] == 0xff => no device
01952                 serial = buffer[6]*1000000 + buffer[5]*10000 + buffer[4]*100 + buffer[3];
01953             }
01954             break;
01955         case FT_ROBO_IF_COM:
01956             buffer[0] = 0xf0;
01957             buffer[1] = 0x02;
01958             ret = write(hFt->sdev, &buffer, 2);
01959             if (ret != 2) {
01960                 fprintf(stderr, "Error writing msg 0xF0 0x02\n");
01961                 return 0;
01962             }
01963             ret = read(hFt->sdev, &buffer, 5);
01964             if (ret != 5) {
01965                 fprintf(stderr, "Error reading msg 0xF0 0x02\n");
01966                 return 0;
01967             }
01968             serial = buffer[1] + buffer[2]*100 + buffer[3]*10000 + buffer[4]*1000000;
01969             break;
01970         default:
01971             return FTLIB_ERR_NOT_SUPPORTED;
01972     }
01973 
01974     return serial;
01975 }
01976 
01977 
01978 /**
01979  * \brief Get the serial number of this interface.
01980  *
01981  * Returns the serial number of the interface with this handle.
01982  * The allocated space should be freed with free() later.
01983  *
01984  * @param hFt Handle of the Interface
01985  * @return Pointer to a string with the serial
01986  */
01987 char *GetFtSerialNrStrg(FT_HANDLE hFt) {
01988     long int ifw = GetFtSerialNr(hFt);
01989     char *s = (char *)malloc(16);
01990     int byte1, byte2, byte3, byte4;
01991 
01992     byte1 = ifw % 100;
01993     ifw /= 100;
01994     byte2 = ifw % 100;
01995     ifw /= 100;
01996     byte3 = ifw % 100;
01997     ifw /= 100;
01998     byte4 = ifw % 100;
01999     ifw /= 100;
02000 
02001     snprintf(s, 16, "%d.%02d.%02d.%02d", byte4, byte3, byte2, byte1);
02002 
02003     return s;
02004 }
02005 
02006 
02007 /**
02008  * \brief Close all ft devices
02009  *
02010  * Dummy. Can't be supported. Only used in original library.
02011  *
02012  * @return Always FTLIB_ERR_NOT_SUPPORTED
02013  */
02014 long int CloseAllFtDevices() {
02015     return FTLIB_ERR_NOT_SUPPORTED;
02016 }
02017 
02018 
02019 /**
02020  * \brief Set the inputs D1 and D2 to distance oder voltage measuring
02021  *
02022  * This function allows to enable the inputs D1 and D2 to measure distances.
02023  * Must be called before StartFtTransferArea()
02024  *
02025  * Note by Hardware Vendor:
02026  * "Since the operating mode of the D1 / D2 inputs can be set by means of software, we recommend that no
02027  * voltage be supplied 'directly' to these connections in order to avoid damage to the interface during software
02028  * errors. Since the inputs are highly resistive, a resistance of approximately 200 Ohm - 470 Ohm should be
02029  * directly connected to the D1 / D2 socket (series connection). We recommend to connect the voltage range to
02030  * be measured 'behind' it."
02031  *
02032  * @param hFt Handle of the Interface
02033  * @param dwMode Set mode to IF_DS_INPUT_VOLTAGE (measure voltage) or IF_DS_INPUT_DISTANCE (measure distance)
02034  * @param dwTol1 Range of tolerance for D1. Try IF_DS_INPUT_TOL_STD (20).
02035  * @param dwTol2 Range of tolerance for D2. Try IF_DS_INPUT_TOL_STD (20).
02036  * @param dwLevel1 Threshold for D1. Try 100.
02037  * @param dwLevel2 Threshold for D2. Try 100.
02038  * @param dwRepeat1 Repition value for D1. Try IF_DS_INPUT_REP_STD (3).
02039  * @param dwRepeat2 Repition value for D2. Try IF_DS_INPUT_REP_STD (3).
02040  * @return FTLIB_ERR_SUCCESS on success
02041  */
02042 long int SetFtDistanceSensorMode(FT_HANDLE hFt, long int dwMode, long int dwTol1, long int dwTol2, long int dwLevel1, long int dwLevel2, long int dwRepeat1, long int dwRepeat2) {
02043     int ret;
02044     unsigned char buffer[] =  {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // 34
02045     int i;
02046 
02047     buffer[1] = dwTol1;
02048     buffer[2] = dwTol2;
02049     buffer[3] = dwLevel1;
02050     buffer[4] = dwLevel1>>8;
02051     buffer[5] = dwLevel2;
02052     buffer[6] = dwLevel2>>8;
02053     buffer[7] = dwRepeat1;
02054     buffer[8] = dwRepeat2;
02055 
02056     if (hFt == NULL) {
02057         fprintf(stderr, "GetFtFirmware: No such device\n");
02058         return FTLIB_ERR_PORT_NUMBER_IS_NULL;
02059     }
02060 
02061     switch (hFt->type) {
02062         case FT_ROBO_IF_USB:
02063             ret = usb_control_msg(hFt->device, 0x40, 0xf1, 0x1, dwMode, buffer+1, 8, FT_USB_TIMEOUT);
02064             if (ret != 8) {
02065                 fprintf(stderr, "Error sending control msg 0x40 0xf1\n");
02066                 return ret;
02067             }
02068             break;
02069         case FT_ROBO_RF_DATA_LINK:
02070         case FT_ROBO_IF_OVER_RF:
02071             ret = usb_control_msg(hFt->device, 0x40, 0x53, hFt->transfer_area.RfModulNr<<8 | 0x01, 0, buffer, 34, FT_USB_TIMEOUT);
02072             if (ret != 34) {
02073                 fprintf(stderr, "Error sending control msg 0x40 0x53\n");
02074                 return ret;
02075             }
02076             break;
02077         case FT_ROBO_IF_COM:
02078             // move data in array for two bytes
02079             for (i=10; i>=3; i--) {
02080                 buffer[i] = buffer[i-2];
02081             }
02082             buffer[0] = 0xf1;
02083             buffer[1] = 0x01;
02084             buffer[2] = dwMode;
02085             if ((write(hFt->sdev, &buffer, 11)) != 11 || (read(hFt->sdev, &buffer, 1)) != 1 || buffer[0] != 0x01) {
02086                 fprintf(stderr, "SetFtDistanceSensorMode: Error communicating with serial\n");
02087                 return buffer[0];
02088             }
02089             break;
02090         default:
02091             return FTLIB_ERR_NOT_SUPPORTED;
02092     }
02093 
02094     usleep(100000); // wait before continue, else it doesn't always work
02095 
02096     return FTLIB_ERR_SUCCESS;
02097 }
02098 
02099 
02100 /**
02101  * \brief Sets the frequency and call sign for a Robo Interface or RF Data Link.
02102  *
02103  * Sets the frequency and call sign which allows to control multiple Interfaces at one RF Data Link.
02104  * The value won't be lost on power failure.
02105  *
02106  * @param hFt Handle of the Interface
02107  * @param frequency to use. May be between 2 and 80.
02108  * @param callSign call sign for this Interface. May be between 1 and 8. (ignored for the RF Data Link)
02109  * @return FTLIB_ERR_SUCCESS on success
02110  */
02111 long int SetRFMode(FT_HANDLE hFt, long int frequency, long int callSign) {
02112     int ret;
02113     unsigned char buffer[5];
02114 
02115     if (hFt == NULL) {
02116         fprintf(stderr, "GetFtFirmware: No such device\n");
02117         return FTLIB_ERR_PORT_NUMBER_IS_NULL;
02118     } else if (frequency < 2 || frequency > 80) {
02119         return FTLIB_ERR_INVALID_PARAM;
02120     } else if (callSign > 8) {
02121         return FTLIB_ERR_INVALID_PARAM;
02122     }
02123 
02124     switch (hFt->type) {
02125         case FT_ROBO_RF_DATA_LINK:
02126             ret = usb_control_msg(hFt->device, 0xc0, 0xfb, 1, frequency, buffer, 2, FT_USB_TIMEOUT);
02127             if (ret != 2 || buffer[0] != 0xfe || buffer[1] != 0) {
02128                 fprintf(stderr, "Error sending control msg 0xc0 0xfb\n");
02129                 return ret;
02130             }
02131             break;
02132         case FT_ROBO_IF_USB:
02133             // not or-ing 1 to frequency seems to disable the modul
02134             ret = usb_control_msg(hFt->device, 0xc0, 0xfb, (callSign<<8) | 1, (1<<8) | frequency, buffer, 2, FT_USB_TIMEOUT);
02135             if (ret != 2 || buffer[0] != 0xfe || buffer[1] != 0) {
02136                 fprintf(stderr, "Error sending control msg 0xc0 0xfb\n");
02137                 return ret;
02138             }
02139             break;
02140         case FT_ROBO_IF_COM:
02141             buffer[0] = 0xfb;
02142             buffer[1] = 0x1;
02143             buffer[2] = 0x7f;
02144             buffer[3] = frequency;
02145             buffer[4] = callSign;
02146             if ((write(hFt->sdev, &buffer, 5)) != 5 || (ret = read(hFt->sdev, &buffer, 2)) != 2 || buffer[0] != 0xfe) {
02147                 fprintf(stderr, "SetRFMode: Error communicating with serial\n");
02148                 return ret;
02149             }
02150             break;
02151         default:
02152             return FTLIB_ERR_NOT_SUPPORTED;
02153     }
02154 
02155     return FTLIB_ERR_SUCCESS;
02156 }
02157 
02158 
02159 /**
02160  * \brief Gets the frequency and call sign of a Robo Interface or RF Data Link.
02161  *
02162  * Sets the frequency and call sign which allows to control multiple Interfaces at one RF Data Link.
02163  *
02164  * @param hFt Handle of the Interface
02165  * @param frequency Points to a place to store the frequency.
02166  * @param callSign Points to a place to store the callSign. (Value will be 0 for the RF Data Link)
02167  * @return FTLIB_ERR_SUCCESS on success
02168  */
02169 long int GetRFMode(FT_HANDLE hFt, long int *frequency, long int *callSign) {
02170     int ret;
02171     unsigned char buffer[8];
02172 
02173     if (hFt == NULL) {
02174         fprintf(stderr, "GetFtFirmware: No such device\n");
02175         return FTLIB_ERR_PORT_NUMBER_IS_NULL;
02176     }
02177 
02178     switch (hFt->type) {
02179         case FT_ROBO_IF_USB:
02180         case FT_ROBO_RF_DATA_LINK:
02181             ret = usb_control_msg(hFt->device, 0xc0, 0xfb, 0x81, 0, buffer, 8, FT_USB_TIMEOUT);
02182             if (ret != 8) {
02183                 fprintf(stderr, "Error sending control msg 0xc0 0xfb\n");
02184                 return ret;
02185             }
02186             *frequency = buffer[6];
02187             *callSign = buffer[7];
02188             break;
02189         case FT_ROBO_IF_COM:
02190             buffer[0] = 0xfb;
02191             buffer[1] = 0x81;
02192             if ((write(hFt->sdev, &buffer, 2)) != 2 || (ret = read(hFt->sdev, &buffer, 8)) != 8 || buffer[0] != 0x7e) {
02193                 fprintf(stderr, "GetRFMode: Error communicating with serial\n");
02194                 return ret;
02195             }
02196             *frequency = buffer[6];
02197             *callSign = buffer[7];
02198             break;
02199         default:
02200             return FTLIB_ERR_NOT_SUPPORTED;
02201     }
02202 
02203     return FTLIB_ERR_SUCCESS;
02204 }
02205 
02206 
02207 /**
02208  * \brief Switches between the real serial and 0001 of a device.
02209  *
02210  * Every ft Interface is shipped with 0001 as serial.
02211  * Nevertheless each has its own serial which can be activated.
02212  *
02213  * @param hFt Handle of the Interface
02214  * @param bOn 0 to use 0001, else the real serial
02215  * @return FTLIB_ERR_SUCCESS on success
02216  */
02217 long int SetRealSerial(FT_HANDLE hFt, unsigned char bOn) {
02218     int ret;
02219     // on: 2 0xd2 0x3a
02220     // off: 1 0x81 0x6f
02221     // RF: 2 d8 77 vs 1 8b 22
02222     // Whats the number?
02223     // SetSerial(hFt, 5386);
02224     unsigned char buffer[16] = {0xaf, 0x83, 0x55, 0xa1, 1, 0, 0, 0, 1, 0x81, 0x6f, 0, 0, 0, 0, 0};
02225 
02226     if (hFt == NULL) {
02227         fprintf(stderr, "GetFtFirmware: No such device\n");
02228         return FTLIB_ERR_PORT_NUMBER_IS_NULL;
02229     }
02230 
02231     switch (hFt->type) {
02232         case FT_ROBO_IF_USB:
02233             if (bOn) {
02234                 buffer[8] = 2;
02235                 buffer[9] = 0xd2;
02236                 buffer[10] = 0x3a;
02237             } else {
02238                 buffer[8] = 1;
02239                 buffer[9] = 0x81;
02240                 buffer[10] = 0x6f;
02241             }
02242             ret = usb_control_msg(hFt->device, 0x40, 0xaf, 0x83, 0, buffer, 16, 200000);
02243             if (ret != 16) {
02244                 fprintf(stderr, "Error sending control msg 0x40 0xaf\n");
02245                 return ret;
02246             }
02247             break;
02248         case FT_ROBO_IF_OVER_RF:
02249             if (bOn) {
02250                 buffer[8] = 2;
02251                 buffer[9] = 0xd8;
02252                 buffer[10] = 0x77;
02253             } else {
02254                 buffer[8] = 1;
02255                 buffer[9] = 0x8b;
02256                 buffer[10] = 0x22;
02257             }
02258             ret = usb_control_msg(hFt->device, 0x40, 0xaf, 0x83, 0, buffer, 16, 200000);
02259             if (ret != 16) {
02260                 fprintf(stderr, "Error sending control msg 0x40 0xaf\n");
02261                 return ret;
02262             }
02263             break;
02264         case FT_ROBO_IO_EXTENSION:
02265             if (bOn) {
02266                 buffer[8] = 2;
02267                 buffer[9] = 0x5f;
02268                 buffer[10] = 0x28;
02269             } else {
02270                 buffer[8] = 1;
02271                 buffer[9] = 0x0c;
02272                 buffer[10] = 0x7d;
02273             }
02274             ret = usb_control_msg(hFt->device, 0x40, 0xaf, 0x83, 0, buffer, 16, 200000);
02275             if (ret != 16) {
02276                 fprintf(stderr, "Error sending control msg 0x40 0xaf\n");
02277                 return ret;
02278             }
02279             break;
02280         case FT_ROBO_IF_COM:
02281             if ((write(hFt->sdev, &buffer, 16)) != 16 || (ret = read(hFt->sdev, &buffer, 2)) != 2 || buffer[0] != 0x7c) {
02282                 fprintf(stderr, "SetRealSerial: Error communicating with serial\n");
02283                 return ret;
02284             }
02285             break;
02286         default:
02287             return FTLIB_ERR_NOT_SUPPORTED;
02288     }
02289 
02290     return FTLIB_ERR_SUCCESS;
02291 }
02292 
02293 
02294 
02295 /**
02296  * @brief Gets the Manufacturer of the Interface
02297  *
02298  * Will return the Manufacturer of a fischertechnik USB device.
02299  * The allocated space should be freed with free() later.
02300  *
02301  * @param hFt Handle of the Interface
02302  * @return Pointer to the string with the name
02303  */
02304 char *GetFtManufacturerStrg(FT_HANDLE hFt) {
02305     char *buffer = (char *)malloc(128);
02306     memset(buffer, '\0', 128);
02307 
02308     if (hFt == NULL) {
02309         fprintf(stderr, "GetFtFirmware: No such device\n");
02310     }
02311 
02312     switch (hFt->type) {
02313         case FT_ROBO_IF_USB:
02314         case FT_ROBO_RF_DATA_LINK:
02315         case FT_ROBO_IF_OVER_RF:
02316             usb_get_string_simple(hFt->device, 1, buffer, 128);
02317             break;
02318     }
02319 
02320     return buffer;
02321 }
02322 
02323 
02324 /**
02325  * @brief Gets the short name of the Interface
02326  *
02327  * Will return the short name of a fischertechnik USB device.
02328  * The allocated space should be freed with free() later.
02329  *
02330  * @param hFt Handle of the Interface
02331  * @return Pointer to the string with the name
02332  */
02333 char *GetFtShortNameStrg(FT_HANDLE hFt) {
02334     char *buffer = (char *)malloc(128);
02335     memset(buffer, '\0', 128);
02336 
02337     if (hFt == NULL) {
02338         fprintf(stderr, "GetFtFirmware: No such device\n");
02339     }
02340 
02341     switch (hFt->type) {
02342         case FT_ROBO_IF_USB:
02343         case FT_ROBO_RF_DATA_LINK:
02344         case FT_ROBO_IF_OVER_RF:
02345             usb_get_string_simple(hFt->device, 5, buffer, 128);
02346             break;
02347     }
02348 
02349     return buffer;
02350 }
02351 
02352 
02353 /**
02354  * @brief Gets the long name of the Interface
02355  *
02356  * Will return the long name of a fischertechnik USB device.
02357  * The allocated space should be freed with free() later.
02358  *
02359  * @param hFt Handle of the Interface
02360  * @return Pointer to the string with the name
02361  */
02362 char *GetFtLongNameStrg(FT_HANDLE hFt) {
02363     char *buffer = (char *)malloc(128);
02364     memset(buffer, '\0', 128);
02365 
02366     if (hFt == NULL) {
02367         fprintf(stderr, "GetFtFirmware: No such device\n");
02368     }
02369 
02370     switch (hFt->type) {
02371         case FT_ROBO_IF_USB:
02372         case FT_ROBO_RF_DATA_LINK:
02373         case FT_ROBO_IF_OVER_RF:
02374             usb_get_string_simple(hFt->device, 2, buffer, 128);
02375             break;
02376     }
02377 
02378     return buffer;
02379 }
02380 #endif //NOTNOW
02381 
02382 /**
02383  * @brief Tells if we successfuly got a connection to the Interface
02384  *
02385  * @param hFt Handle of the Interface
02386  * @return 0 if the Interface is not connected
02387  */
02388 char IsFtInterfaceConnected(FT_HANDLE hFt) {
02389     return hFt->interface_connected;
02390 }
02391 
02392 
02393 /**
02394  * @brief Gets the description of an error
02395  *
02396  * Will return a description of an error.
02397  * The allocated space should be freed with free() later.
02398  *
02399  * The return value is the constant as string if parameter dwTyp is 0,
02400  * else a verbose description of the error.
02401  *
02402  * @param dwErrorCode Error Code
02403  * @param dwTyp Type of the return value (see description)
02404  * @return Pointer to a string (see description)
02405  */
02406 char *GetFtLibErrorString(long int dwErrorCode, long int dwTyp) {
02407     char *buffer = (char *)malloc(128);
02408 
02409     switch (dwErrorCode) {
02410         case FTLIB_ERR_IF_NO_PROGRAM:
02411             if (dwTyp) strncpy(buffer, "There is no program stored to work with", 128);
02412             else strncpy(buffer, "FTLIB_ERR_IF_NO_PROGRAM", 128);
02413             break;
02414         case FTLIB_ERR_SUCCESS:
02415             if (dwTyp) strncpy(buffer, "Everything is fine", 128);
02416             else strncpy(buffer, "FTLIB_ERR_SUCCESS", 128);
02417             break;
02418         case FTLIB_ERR_THREAD_IS_RUNNING:
02419             if (dwTyp) strncpy(buffer, "Thread has been started successfully", 128);
02420             else strncpy(buffer, "FTLIB_ERR_THREAD_IS_RUNNING", 128);
02421             break;
02422         case FTLIB_ERR_DOWNLOAD:
02423             if (dwTyp) strncpy(buffer, "Failed to upload the program", 128);
02424             else strncpy(buffer, "FTLIB_ERR_DOWNLOAD", 128);
02425             break;
02426         case FTLIB_ERR_DOWNLOAD_WRONG_MEM_BLOCK:
02427             if (dwTyp) strncpy(buffer, "Bad target to upload the program to", 128);
02428             else strncpy(buffer, "FTLIB_ERR_DOWNLOAD_WRONG_MEM_BLOCK", 128);
02429             break;
02430         case FTLIB_ERR_INVALID_PARAM:
02431             if (dwTyp) strncpy(buffer, "A parameter specified has a wrong value", 128);
02432             else strncpy(buffer, "FTLIB_ERR_INVALID_PARAM", 128);
02433             break;
02434         case FTLIB_ERR_LIB_IS_INITIALIZED:
02435             if (dwTyp) strncpy(buffer, "This library has been initialized", 128);
02436             else strncpy(buffer, "FTLIB_ERR_LIB_IS_INITIALIZED", 128);
02437             break;
02438         case FTLIB_ERR_NOT_SUPPORTED:
02439             if (dwTyp) strncpy(buffer, "The requested action is not supported", 128);
02440             else strncpy(buffer, "FTLIB_ERR_NOT_SUPPORTED", 128);
02441             break;
02442         case FTLIB_ERR_PORT_NUMBER_IS_NULL:
02443             if (dwTyp) strncpy(buffer, "No handle given", 128);
02444             else strncpy(buffer, "FTLIB_ERR_PORT_NUMBER_IS_NULL", 128);
02445             break;
02446         case FTLIB_ERR_THREAD_NOT_RUNNING:
02447             if (dwTyp) strncpy(buffer, "Unable to start the thread", 128);
02448             else strncpy(buffer, "FTLIB_ERR_THREAD_NOT_RUNNING", 128);
02449             break;
02450         default:
02451             strncpy(buffer, "Unknown", 128);
02452     }
02453 
02454     return buffer;
02455 }
02456 
02457 
02458 /** \cond doxygen ignore start */
02459 //! \todo
02460 long int SetFtDeviceCommMode(FT_HANDLE hFt, long int dwMode, long int dwParameter, unsigned short *puiValue) {
02461     return 0;
02462 }
02463 
02464 
02465 //! \todo
02466 long int GetFtDeviceSetting(FT_HANDLE hFt, FT_SETTING *pSet) {
02467     return 0;
02468 }
02469 
02470 
02471 //! \todo
02472 long int SetFtDeviceSetting(FT_HANDLE hFt, FT_SETTING *pSet) {
02473     return 0;
02474 }
02475 
02476 
02477 //! \todo
02478 long int SendFtMessage(FT_HANDLE hFt, unsigned char bHwId, unsigned char bSubId, long int dwMessage, long int dwWaitTime, long int dwOption) {
02479     return 0;
02480 }
02481 
02482 
02483 //! \todo
02484 long int ClearFtMessageBuffer(FT_HANDLE hFt) {
02485     return 0;
02486 }
02487 
02488 
02489 //! \todo
02490 long int GetFtMemoryLayout(FT_HANDLE hFt, unsigned char* pbArray, long int dwSize) {
02491     return 0;
02492 }
02493 
02494 
02495 //! \todo
02496 long int GetFtMemoryData(FT_HANDLE hFt, unsigned char * pbArray, long int dwSize, long int dwAddress) {
02497     return 0;
02498 }
02499 
02500 
02501 //! \todo
02502 long int WriteFtMemoryData(FT_HANDLE hFt, long int dwData, long int dwAddress) {
02503     return 0;
02504 }
02505 
02506 #ifndef SPLITTRANSFER
02507 /** \cond doxygen ignore start */
02508 static void *FtThread(FT_HANDLE hFt) {
02509     FT_TRANSFER_AREA *area = &hFt->transfer_area;
02510     int ret;
02511     unsigned char out[ABF_IF_COMPLETE_NUM_WRITE]; //= {ABF_IF_COMPLETE,1,0x07,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
02512     unsigned char in[ABF_IF_COMPLETE_NUM_READ];
02513     int num_write = ABF_IF_COMPLETE_NUM_WRITE;
02514     int num_read = ABF_IF_COMPLETE_NUM_READ;
02515     int usb_endpoint_write = FT_ENDPOINT_INTERRUPT_OUT;
02516     int usb_endpoint_read = FT_ENDPOINT_INTERRUPT_IN;
02517     int i=0;
02518     int ii_speed = 0;
02519 
02520     out[0] = ABF_IF_COMPLETE;
02521     area->TransferAktiv = 1;
02522 
02523     switch (hFt->type) {
02524         case FT_ROBO_IF_COM:
02525             out[0] = 0xf2;
02526             num_write = 17;
02527             num_read = 21;
02528             break;
02529         case FT_INTELLIGENT_IF:
02530             num_write = 2;
02531             break;
02532         case FT_INTELLIGENT_IF_SLAVE:
02533             num_write = 3;
02534             break;
02535 #ifdef USE_USB
02536         case FT_ROBO_IO_EXTENSION:
02537             out[0] = 0xf2;
02538             num_write = 6;
02539             num_read = 6;
02540             break;
02541         case FT_ROBO_IF_OVER_RF:
02542         case FT_ROBO_RF_DATA_LINK:
02543             usb_endpoint_write = FT_RF_ENDPOINT_INTERRUPT_OUT;
02544             usb_endpoint_read = FT_RF_ENDPOINT_INTERRUPT_IN;
02545 
02546             // init RF
02547             // 0x102 == first RF
02548             // 0x202 == 2nd RF
02549             // ...
02550             //ret = usb_control_msg(hFt->device, 0xc0, 0xfb, 0x102, 0x1, in, 2, FT_USB_TIMEOUT);
02551             ret = usb_control_msg(hFt->device, 0xc0, 0xfb, hFt->transfer_area.RfModulNr << 8 | 0x02, 0x1, in, 2, FT_USB_TIMEOUT);
02552             if (ret != 2) {
02553                 fprintf(stderr, "%d FtThread: Error initiating RF Module!\n");
02554                 area->TransferAktiv = 0;
02555             }
02556             break;
02557 #endif
02558     }
02559 //here the real data exchange starts
02560 #ifdef MBED
02561 //viaUsb.putc('.');
02562     /*while (area->TransferAktiv == 1)*/ { //procedure runs only once
02563         if (!test_and_set(hFt->lock)) //return when busy
02564             return 0;//return because there is no point in sending a nonsense request, alternatively the lock can be ignored in which case the data may be inconsistent
02565 #else
02566     while (area->TransferAktiv == 1) {//thread runs continuously
02567         sem_wait(&hFt->lock);//wait when busy
02568 #endif
02569         out[1] = area->M_Main;
02570         out[2] = (area->MPWM_Main[0] & 0x7) | (area->MPWM_Main[1]<<3 & 0x38) | (area->MPWM_Main[2]<<6 & 0xC0);
02571         out[3] = (area->MPWM_Main[2] & 0x1) | (area->MPWM_Main[3]<<1 & 0xE) | (area->MPWM_Main[4]<<4 & 0x70) | (area->MPWM_Main[5]<<7 & 0x80);
02572         out[4] = (area->MPWM_Main[5] & 0x3) | (area->MPWM_Main[6]<<2 & 0x1C) | (area->MPWM_Main[7]<<5 & 0xE0);
02573         out[5] = area->M_Sub1;
02574         out[6] = (area->MPWM_Sub1[0] & 0x7) | (area->MPWM_Sub1[1]<<3 & 0x38) | (area->MPWM_Sub1[2]<<6 & 0xC0);
02575         out[7] = (area->MPWM_Sub1[2] & 0x1) | (area->MPWM_Sub1[3]<<1 & 0xE) | (area->MPWM_Sub1[4]<<4 & 0x70) | (area->MPWM_Sub1[5]<<7 & 0x80);
02576         out[8] = (area->MPWM_Sub1[5] & 0x3) | (area->MPWM_Sub1[6]<<2 & 0x1C) | (area->MPWM_Sub1[7]<<5 & 0xE0);
02577         out[9] = area->M_Sub2;
02578         out[10] = (area->MPWM_Sub2[0] & 0x7) | (area->MPWM_Sub2[1]<<3 & 0x38) | (area->MPWM_Sub2[2]<<6 & 0xC0);
02579         out[11] = (area->MPWM_Sub2[2] & 0x1) | (area->MPWM_Sub2[3]<<1 & 0xE) | (area->MPWM_Sub2[4]<<4 & 0x70) | (area->MPWM_Sub2[5]<<7 & 0x80);
02580         out[12] = (area->MPWM_Sub2[5] & 0x3) | (area->MPWM_Sub2[6]<<2 & 0x1C) | (area->MPWM_Sub2[7]<<5 & 0xE0);
02581         out[13] = area->M_Sub3;
02582         out[14] = (area->MPWM_Sub3[0] & 0x7) | (area->MPWM_Sub3[1]<<3 & 0x38) | (area->MPWM_Sub3[2]<<6 & 0xC0);
02583         out[15] = (area->MPWM_Sub3[2] & 0x1) | (area->MPWM_Sub3[3]<<1 & 0xE) | (area->MPWM_Sub3[4]<<4 & 0x70) | (area->MPWM_Sub3[5]<<7 & 0x80);
02584         out[16] = (area->MPWM_Sub3[5] & 0x3) | (area->MPWM_Sub3[6]<<2 & 0x1C) | (area->MPWM_Sub3[7]<<5 & 0xE0);
02585         out[17]    = 0;
02586         out[18]    = 0;
02587         out[19]    = 0;
02588         out[20]    = 0;
02589         out[21]    = 0;
02590         out[22]    = 0;
02591         out[23]    = 0;
02592         out[24]    = 0;
02593         out[25]    = 0;
02594         out[26]    = 0;
02595         out[27]    = 0;
02596         out[28]    = 0;
02597         out[29]    = 0;
02598         out[30]    = 0;
02599         out[31]    = 0;
02600 
02601         // For the II we need to simulate different speeds here
02602         if (hFt->type == FT_INTELLIGENT_IF || hFt->type == FT_INTELLIGENT_IF_SLAVE) {
02603             int iCurMotor;
02604             for (iCurMotor = 0; iCurMotor < 7; iCurMotor++) {
02605                 if (area->MPWM_Main[iCurMotor] < ii_speed) out[1] &= ~(1 << iCurMotor);
02606                 if (area->MPWM_Sub1[iCurMotor] < ii_speed) out[5] &= ~(1 << iCurMotor);
02607             }
02608 
02609             ii_speed++;
02610             if (ii_speed > 7) ii_speed = 0;
02611         }
02612 
02613         if (hFt->type == FT_INTELLIGENT_IF) {
02614             i++;
02615             num_read = 1;
02616             out[0] = 0xC1;
02617             if (i % 20) { // EX
02618                 out[0] = 0xC5;
02619                 num_read = 3;
02620             } else if (i % 10) { // EY
02621                 out[0] = 0xC9;
02622                 num_read = 3;
02623             }
02624         } else if (hFt->type == FT_INTELLIGENT_IF_SLAVE) {
02625             i++;
02626             num_read = 2;
02627             out[0] = 0xC2;
02628             out[2] = out[5];
02629             if (i % 20) { // EX
02630                 out[0] = 0xC6;
02631                 num_read = 4;
02632             } else if (i % 10) { // EY
02633                 out[0] = 0xCA;
02634                 num_read = 4;
02635             }
02636         }
02637 #ifdef MBED
02638 //viaUsb.putc('-');
02639         increment(hFt->lock);//release the lock on shared memeory
02640 #else
02641         sem_post(&hFt->lock);
02642 #endif
02643         ret = 0;
02644         switch (hFt->type) {//send the request
02645 #ifdef USE_USB
02646             case FT_ROBO_IF_USB:
02647             case FT_ROBO_IO_EXTENSION:
02648             case FT_ROBO_IF_OVER_RF:
02649             case FT_ROBO_RF_DATA_LINK:
02650                 ret = usb_interrupt_write(hFt->device, usb_endpoint_write, out, num_write, FT_USB_TIMEOUT);
02651                 break;
02652 #endif
02653             case FT_ROBO_IF_COM:
02654             case FT_INTELLIGENT_IF:
02655             case FT_INTELLIGENT_IF_SLAVE:
02656 #ifdef MBED
02657                 //ret = hFt->sdev->printf("%*c", num_write, out);
02658                 ret = write(hFt->sdev, out, num_write);
02659 //                viaUsb.putc(';');
02660 #else
02661                 ret = write(hFt->sdev, &out, num_write);
02662 #endif
02663                 break;
02664         }
02665         if (ret != num_write) {
02666             hFt->interface_connected = 0;
02667             fprintf(stderr, "FtThread: Error writing to the Interface...exiting!\n");
02668 #ifdef MBED
02669             return 0;
02670 #else
02671             break;
02672 #endif
02673         }
02674 
02675         ret = 0;
02676         switch (hFt->type) { //receive the reply
02677 #ifdef USE_USB
02678             case FT_ROBO_IF_USB:
02679             case FT_ROBO_IO_EXTENSION:
02680             case FT_ROBO_IF_OVER_RF:
02681             case FT_ROBO_RF_DATA_LINK:
02682                 ret = usb_interrupt_read(hFt->device, usb_endpoint_read, in, num_read, FT_USB_TIMEOUT);
02683                 break;
02684 #endif
02685             case FT_ROBO_IF_COM:
02686             case FT_INTELLIGENT_IF:
02687             case FT_INTELLIGENT_IF_SLAVE:
02688 #ifdef MBED
02689                 //ret = hFt->sdev->scanf("%*c", num_read, in)==1 ? num_read : 0 ;
02690                 ret = read(hFt->sdev, in, num_read);
02691 //                viaUsb.putc('/');
02692 #else
02693                 ret = read(hFt->sdev, &in, num_read);
02694 #endif
02695                 break;
02696         }
02697         if (ret != num_read) {
02698             hFt->interface_connected = 0;
02699             fprintf(stderr, "FtThread: Error reading from the Interface\n");
02700 #ifdef MBED
02701             return 0;
02702 #else
02703             usleep(hFt->query_time);
02704             continue;
02705 #endif
02706         }
02707 
02708 #ifdef MBED
02709         if (!test_and_set(hFt->lock))//skip when busy
02710             return 0;
02711 #else
02712         sem_wait(&hFt->lock);//wait when busy
02713 #endif
02714         area->E_Main = in[0];
02715         area->E_Sub1 = in[1];
02716         area->E_Sub2 = in[2];
02717         area->E_Sub3 = in[3];
02718         area->AX = in[4];
02719         area->AY = in[5];
02720         area->A1 = in[6];
02721         area->A2 = in[7];
02722         area->AX |= (in[8] & 0x3) << 8;
02723         area->AY |= (in[8] & 0xC) << 6;
02724         area->A1 |= (in[8] & 0x30) << 4;
02725         area->A2 |= (in[8] & 0xC0) << 2;
02726         area->AZ = in[9];
02727         area->D1 = in[10];
02728         area->D2 = in[11];
02729         area->AV = in[12];
02730         area->AZ |= (in[13] & 0x3) << 8;
02731         area->D1 |= (in[13] & 0xC) << 6;
02732         area->D2 |= (in[13] & 0x30) << 4;
02733         area->AV |= (in[13] & 0xC0) << 2;
02734         area->IRKeys = in[14];
02735         area->BusModules = in[15];
02736         // 16
02737         area->AXS1 = in[17];
02738         area->AXS2 = in[18];
02739         area->AXS3 = in[19];
02740         area->AXS1 |= (in[20] & 0x3) << 8;
02741         area->AXS2 |= (in[20] & 0xC) << 6;
02742         area->AXS3 |= (in[20] & 0x30) << 4;
02743         // 21
02744         area->AVS1 = in[22];
02745         area->AVS2 = in[23];
02746         area->AVS3 = in[24];
02747         area->AVS1 |= (in[25] & 0x3) << 8;
02748         area->AVS2 |= (in[25] & 0xC) << 6;
02749         area->AVS3 |= (in[25] & 0x30) << 4;
02750         // 26...42
02751         if (hFt->type == FT_INTELLIGENT_IF) {
02752             if (i % hFt->analogcycle) { // EX
02753                 area->AX = in[1] & (8<<in[2]);
02754             } else if (i % (2*hFt->analogcycle)) { // EY
02755                 area->AY = in[1] & (8<<in[2]);
02756             }
02757         } else if (hFt->type == FT_INTELLIGENT_IF_SLAVE) {
02758             if (i % hFt->analogcycle) { // EX
02759                 area->AX = in[1] & (8<<in[2]);
02760             } else if (i % (2*hFt->analogcycle)) { // EY
02761                 area->AY = in[1] & (8<<in[2]);
02762             }
02763         }
02764 #ifdef MBED
02765         increment(hFt->lock);
02766         hFt->interface_connected = 1;
02767 #else
02768         sem_post(&hFt->lock);
02769 
02770         hFt->interface_connected = 1;
02771 
02772         usleep(hFt->query_time);
02773 #endif
02774     }//end of the while loop (end of task)
02775 #ifdef USE_USB
02776     if (hFt->type == FT_ROBO_IF_OVER_RF || hFt->type == FT_ROBO_RF_DATA_LINK) {
02777         ret = usb_control_msg(hFt->device, 0xc0, 0x21, hFt->transfer_area.RfModulNr << 8, 0, in, 1, FT_USB_TIMEOUT);
02778         if (ret != 1 || in[0] != 0xd7) {
02779             fprintf(stderr, "Error uninitiating RF Module!\n");
02780         }
02781     }
02782 #endif
02783 #ifdef MBED
02784     return 0;
02785 #else
02786     hFt->transfer_area.TransferAktiv = 0;
02787     pthread_exit((void *) 0);
02788 #endif
02789 }
02790 
02791 void ft_handle_devices::FtThread() {
02792     ::FtThread(this);
02793 //    printf("%02X\r", transfer_area.E_Main);
02794 //    viaUsb.putc('.');
02795 }
02796 /** \endcond doxygen ignore end */
02797 
02798 #endif
02799 
02800 /** \endcond doxygen ignore end */
02801