diff options
Diffstat (limited to 'gr-fcd/lib/fcd/fcd.c')
-rw-r--r-- | gr-fcd/lib/fcd/fcd.c | 904 |
1 files changed, 904 insertions, 0 deletions
diff --git a/gr-fcd/lib/fcd/fcd.c b/gr-fcd/lib/fcd/fcd.c new file mode 100644 index 000000000..ca9050231 --- /dev/null +++ b/gr-fcd/lib/fcd/fcd.c @@ -0,0 +1,904 @@ +/*************************************************************************** + * This file is part of Qthid. + * + * Copyright (C) 2010 Howard Long, G6LVB + * CopyRight (C) 2011 Alexandru Csete, OZ9AEC + * Mario Lorenz, DL5MLO + * + * Qthid is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Qthid is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Qthid. If not, see <http://www.gnu.org/licenses/>. + * + ***************************************************************************/ + +#define FCD +#include <string.h> +#ifdef WIN32 + #include <malloc.h> +#else + #include <stdlib.h> +#endif +#include "hidapi.h" +#include "fcd.h" +#include "fcdhidcmd.h" +#include <stdio.h> + + +#define FALSE 0 +#define TRUE 1 +typedef int BOOL; + + +const unsigned short _usVID=0x04D8; /*!< USB vendor ID. */ +const unsigned short _usPID=0xFB56; /*!< USB product ID. */ + + + +/** \brief Open FCD device. + * \return Pointer to the FCD HID device or NULL if none found + * + * This function looks for FCD devices connected to the computer and + * opens the first one found. + */ +static hid_device *fcdOpen(void) +{ + struct hid_device_info *phdi=NULL; + hid_device *phd=NULL; + char *pszPath=NULL; + + phdi=hid_enumerate(_usVID,_usPID); + if (phdi==NULL) + { + return NULL; // No FCD device found + } + + pszPath=strdup(phdi->path); + if (pszPath==NULL) + { + return NULL; + } + + hid_free_enumeration(phdi); + phdi=NULL; + + if ((phd=hid_open_path(pszPath)) == NULL) + { + free(pszPath); + pszPath=NULL; + + return NULL; + } + + free(pszPath); + pszPath=NULL; + + return phd; +} + + +/** \brief Close FCD HID device. */ +static void fcdClose(hid_device *phd) +{ + hid_close(phd); +} + + +/** \brief Get FCD mode. + * \return The current FCD mode. + * \sa FCD_MODE_ENUM + */ +EXTERN FCD_MODE_ENUM fcdGetMode(void) +{ + hid_device *phd=NULL; + unsigned char aucBufIn[65]; + unsigned char aucBufOut[65]; + FCD_MODE_ENUM fcd_mode = FCD_MODE_NONE; + + + phd = fcdOpen(); + + if (phd == NULL) + { + return FCD_MODE_NONE; + } + + /* Send a BL Query Command */ + aucBufOut[0] = 0; // Report ID, ignored + aucBufOut[1] = FCD_CMD_BL_QUERY; + hid_write(phd, aucBufOut, 65); + memset(aucBufIn, 0xCC, 65); // Clear out the response buffer + hid_read(phd, aucBufIn, 65); + + fcdClose(phd); + phd = NULL; + + /* first check status bytes then check which mode */ + if (aucBufIn[0]==FCD_CMD_BL_QUERY && aucBufIn[1]==1) { + + /* In bootloader mode we have the string "FCDBL" starting at acBufIn[2] **/ + if (strncmp((char *)(aucBufIn+2), "FCDBL", 5) == 0) { + fcd_mode = FCD_MODE_BL; + } + /* In application mode we have "FCDAPP_18.06" where the number is the FW version */ + else if (strncmp((char *)(aucBufIn+2), "FCDAPP", 6) == 0) { + fcd_mode = FCD_MODE_APP; + } + /* either no FCD or firmware less than 18f */ + else { + fcd_mode = FCD_MODE_NONE; + } + } + + return fcd_mode; +} + + +/** \brief Get FCD firmware version as string. + * \param str The returned vesion number as a 0 terminated string (must be pre-allocated) + * \return The current FCD mode. + * \sa FCD_MODE_ENUM + */ +EXTERN FCD_MODE_ENUM fcdGetFwVerStr(char *str) +{ + hid_device *phd=NULL; + unsigned char aucBufIn[65]; + unsigned char aucBufOut[65]; + FCD_MODE_ENUM fcd_mode = FCD_MODE_NONE; + + + phd = fcdOpen(); + + if (phd == NULL) + { + return FCD_MODE_NONE; + } + + /* Send a BL Query Command */ + aucBufOut[0] = 0; // Report ID, ignored + aucBufOut[1] = FCD_CMD_BL_QUERY; + hid_write(phd, aucBufOut, 65); + memset(aucBufIn, 0xCC, 65); // Clear out the response buffer + hid_read(phd, aucBufIn, 65); + + fcdClose(phd); + phd = NULL; + + /* first check status bytes then check which mode */ + if (aucBufIn[0]==FCD_CMD_BL_QUERY && aucBufIn[1]==1) { + + /* In bootloader mode we have the string "FCDBL" starting at acBufIn[2] **/ + if (strncmp((char *)(aucBufIn+2), "FCDBL", 5) == 0) { + fcd_mode = FCD_MODE_BL; + } + /* In application mode we have "FCDAPP_18.06" where the number is the FW version */ + else if (strncmp((char *)(aucBufIn+2), "FCDAPP", 6) == 0) { + strncpy(str, (char *)(aucBufIn+9), 5); + str[5] = 0; + fcd_mode = FCD_MODE_APP; + } + /* either no FCD or firmware less than 18f */ + else { + fcd_mode = FCD_MODE_NONE; + } + } + + return fcd_mode; +} + + +/** \brief Get hardware and firmware dependent FCD capabilities. + * \param fcd_caps Pointer to an FCD_CAPS_STRUCT + * \return The current FCD mode. + * + * This function queries the FCD and extracts the hardware and firmware dependent + * capabilities. Currently these capabilities are: + * - Bias T (available since S/N TBD) + * - Cellular block (the certified version of the FCD) + * When the FCD is in application mode, the string returned by the query command is + * (starting at index 2): + * FCDAPP 18.08 Brd 1.0 No blk + * 1.0 means no bias tee, 1.1 means there is a bias tee + * 'No blk' means it is not cellular blocked. + * + * Ref: http://uk.groups.yahoo.com/group/FCDevelopment/message/303 + */ +EXTERN FCD_MODE_ENUM fcdGetCaps(FCD_CAPS_STRUCT *fcd_caps) +{ + hid_device *phd=NULL; + unsigned char aucBufIn[65]; + unsigned char aucBufOut[65]; + FCD_MODE_ENUM fcd_mode = FCD_MODE_NONE; + + /* clear output buffer */ + fcd_caps->hasBiasT = 0; + fcd_caps->hasCellBlock = 0; + + phd = fcdOpen(); + + if (phd == NULL) + { + return FCD_MODE_NONE; + } + + /* Send a BL Query Command */ + aucBufOut[0] = 0; // Report ID, ignored + aucBufOut[1] = FCD_CMD_BL_QUERY; + hid_write(phd, aucBufOut, 65); + memset(aucBufIn, 0xCC, 65); // Clear out the response buffer + hid_read(phd, aucBufIn, 65); + + fcdClose(phd); + phd = NULL; + + /* first check status bytes then check which mode */ + if (aucBufIn[0]==FCD_CMD_BL_QUERY && aucBufIn[1]==1) { + + /* In bootloader mode we have the string "FCDBL" starting at acBufIn[2] **/ + if (strncmp((char *)(aucBufIn+2), "FCDBL", 5) == 0) { + fcd_mode = FCD_MODE_BL; + } + /* In application mode we have "FCDAPP 18.08 Brd 1.0 No blk" (see API doc) */ + else if (strncmp((char *)(aucBufIn+2), "FCDAPP", 6) == 0) { + + /* Bias T */ + fcd_caps->hasBiasT = (aucBufIn[21] == '1') ? 1 : 0; + + /* cellular block */ + if (strncmp((char *)(aucBufIn+23), "No blk", 6) == 0) { + fcd_caps->hasCellBlock = 0; + } else { + fcd_caps->hasCellBlock = 1; + } + + fcd_mode = FCD_MODE_APP; + } + /* either no FCD or firmware less than 18f */ + else { + fcd_mode = FCD_MODE_NONE; + } + } + + return fcd_mode; +} + + +/** \brief Get hardware and firmware dependent FCD capabilities as string. + * \param caps_str Pointer to a pre-allocated string buffer where the info will be copied. + * \return The current FCD mode. + * + * This function queries the FCD and copies the returned string into the caps_str parameter. + * THe return buffer must be at least 28 characters. + * When the FCD is in application mode, the string returned by the query command is + * (starting at index 2): + * FCDAPP 18.08 Brd 1.0 No blk + * 1.0 means no bias tee, 1.1 means there is a bias tee + * 'No blk' means it is not cellular blocked. + * + * Ref: http://uk.groups.yahoo.com/group/FCDevelopment/message/303 + */ +EXTERN FCD_MODE_ENUM fcdGetCapsStr(char *caps_str) +{ + hid_device *phd=NULL; + unsigned char aucBufIn[65]; + unsigned char aucBufOut[65]; + FCD_MODE_ENUM fcd_mode = FCD_MODE_NONE; + + + phd = fcdOpen(); + + if (phd == NULL) + { + return FCD_MODE_NONE; + } + + /* Send a BL Query Command */ + aucBufOut[0] = 0; // Report ID, ignored + aucBufOut[1] = FCD_CMD_BL_QUERY; + hid_write(phd, aucBufOut, 65); + memset(aucBufIn, 0xCC, 65); // Clear out the response buffer + hid_read(phd, aucBufIn, 65); + + fcdClose(phd); + phd = NULL; + + /* first check status bytes then check which mode */ + if (aucBufIn[0]==FCD_CMD_BL_QUERY && aucBufIn[1]==1) { + + /* In bootloader mode we have the string "FCDBL" starting at acBufIn[2] **/ + if (strncmp((char *)(aucBufIn+2), "FCDBL", 5) == 0) { + fcd_mode = FCD_MODE_BL; + } + /* In application mode we have "FCDAPP 18.08 Brd 1.0 No blk" (see API doc) */ + else if (strncmp((char *)(aucBufIn+2), "FCDAPP", 6) == 0) { + + strncpy(caps_str, (char *)(aucBufIn+2), 27); + caps_str[27] = 0; + + fcd_mode = FCD_MODE_APP; + } + /* either no FCD or firmware less than 18f */ + else { + fcd_mode = FCD_MODE_NONE; + } + } + + return fcd_mode; +} + + + +/** \brief Reset FCD to bootloader mode. + * \return FCD_MODE_NONE + * + * This function is used to switch the FCD into bootloader mode in which + * various firmware operations can be performed. + */ +EXTERN FCD_MODE_ENUM fcdAppReset(void) +{ + hid_device *phd=NULL; + //unsigned char aucBufIn[65]; + unsigned char aucBufOut[65]; + + phd = fcdOpen(); + + if (phd == NULL) + { + return FCD_MODE_NONE; + } + + // Send an App reset command + aucBufOut[0] = 0; // Report ID, ignored + aucBufOut[1] = FCD_CMD_APP_RESET; + hid_write(phd, aucBufOut, 65); + + /** FIXME: hid_read() will occasionally hang due to a pthread_cond_wait() never returning. + It seems that the read_callback() in hid-libusb.c will never receive any + data during the reconfiguration. Since the same logic works in the native + windows application, it could be a libusb thing. Anyhow, since the value + returned by this function is not used, we may as well just skip the hid_read() + and return FME_NONE. + Correct switch from APP to BL mode can be observed in /var/log/messages (linux) + (when in bootloader mode the device version includes 'BL') + */ + /* + memset(aucBufIn,0xCC,65); // Clear out the response buffer + hid_read(phd,aucBufIn,65); + + if (aucBufIn[0]==FCDCMDAPPRESET && aucBufIn[1]==1) + { + FCDClose(phd); + phd=NULL; + return FME_APP; + } + FCDClose(phd); + phd=NULL; + return FME_BL; + */ + + fcdClose(phd); + phd = NULL; + + return FCD_MODE_NONE; + +} + + +/** \brief Set FCD frequency with kHz resolution. + * \param nFreq The new frequency in kHz. + * \return The FCD mode. + * + * This function sets the frequency of the FCD with 1 kHz resolution. The parameter + * nFreq must already contain any necessary frequency correction. + * + * \sa fcdAppSetFreq + */ +EXTERN FCD_MODE_ENUM fcdAppSetFreqkHz(int nFreq) +{ + hid_device *phd=NULL; + unsigned char aucBufIn[65]; + unsigned char aucBufOut[65]; + + phd = fcdOpen(); + + if (phd == NULL) + { + return FCD_MODE_NONE; + } + + // Send an App reset command + aucBufOut[0] = 0; // Report ID, ignored + aucBufOut[1] = FCD_CMD_APP_SET_FREQ_KHZ; + aucBufOut[2] = (unsigned char)nFreq; + aucBufOut[3] = (unsigned char)(nFreq>>8); + aucBufOut[4] = (unsigned char)(nFreq>>16); + hid_write(phd, aucBufOut, 65); + memset(aucBufIn, 0xCC, 65); // Clear out the response buffer + hid_read(phd, aucBufIn, 65); + + if (aucBufIn[0]==FCD_CMD_APP_SET_FREQ_KHZ && aucBufIn[1]==1) + { + fcdClose(phd); + phd = NULL; + + return FCD_MODE_APP; + } + + fcdClose(phd); + phd = NULL; + + return FCD_MODE_BL; +} + + +/** \brief Set FCD frequency with Hz resolution. + * \param nFreq The new frequency in Hz. + * \return The FCD mode. + * + * This function sets the frequency of the FCD with 1 Hz resolution. The parameter + * nFreq must already contain any necessary frequency correction. + * + * \sa fcdAppSetFreq + */ +EXTERN FCD_MODE_ENUM fcdAppSetFreq(int nFreq) +{ + hid_device *phd=NULL; + unsigned char aucBufIn[65]; + unsigned char aucBufOut[65]; + + phd = fcdOpen(); + + if (phd == NULL) + { + return FCD_MODE_NONE; + } + + // Send an App reset command + aucBufOut[0] = 0; // Report ID, ignored + aucBufOut[1] = FCD_CMD_APP_SET_FREQ_HZ; + aucBufOut[2] = (unsigned char)nFreq; + aucBufOut[3] = (unsigned char)(nFreq>>8); + aucBufOut[4] = (unsigned char)(nFreq>>16); + aucBufOut[5] = (unsigned char)(nFreq>>24); + hid_write(phd, aucBufOut, 65); + memset(aucBufIn, 0xCC, 65); // Clear out the response buffer + hid_read(phd, aucBufIn, 65); + + if (aucBufIn[0]==FCD_CMD_APP_SET_FREQ_HZ && aucBufIn[1]==1) + { + fcdClose(phd); + phd = NULL; + + return FCD_MODE_APP; + } + + fcdClose(phd); + phd = NULL; + + return FCD_MODE_BL; +} + + + +/** \brief Reset FCD to application mode. + * \return FCD_MODE_NONE + * + * This function is used to switch the FCD from bootloader mode + * into application mode. + */ +EXTERN FCD_MODE_ENUM fcdBlReset(void) +{ + hid_device *phd=NULL; +// unsigned char aucBufIn[65]; + unsigned char aucBufOut[65]; + + phd = fcdOpen(); + + if (phd == NULL) + { + return FCD_MODE_NONE; + } + + // Send an BL reset command + aucBufOut[0] = 0; // Report ID, ignored + aucBufOut[1] = FCD_CMD_BL_RESET; + hid_write(phd, aucBufOut, 65); + + /** FIXME: hid_read() will hang due to a pthread_cond_wait() never returning. + It seems that the read_callback() in hid-libusb.c will never receive any + data during the reconfiguration. Since the same logic works in the native + windows application, it could be a libusb thing. Anyhow, since the value + returned by this function is not used, we may as well jsut skip the hid_read() + and return FME_NONE. + Correct switch from BL to APP mode can be observed in /var/log/messages (linux) + (when in bootloader mode the device version includes 'BL') + */ + /* + memset(aucBufIn,0xCC,65); // Clear out the response buffer + hid_read(phd,aucBufIn,65); + + if (aucBufIn[0]==FCDCMDBLRESET && aucBufIn[1]==1) + { + FCDClose(phd); + phd=NULL; + return FME_BL; + } + FCDClose(phd); + phd=NULL; + return FME_APP; + */ + + fcdClose(phd); + phd = NULL; + + return FCD_MODE_NONE; + +} + + +/** \brief Erase firmware from FCD. + * \return The FCD mode + * + * This function deletes the firmware from the FCD. This is required + * before writing new firmware into the FCD. + * + * \sa fcdBlWriteFirmware + */ +EXTERN FCD_MODE_ENUM fcdBlErase(void) +{ + hid_device *phd=NULL; + unsigned char aucBufIn[65]; + unsigned char aucBufOut[65]; + + phd = fcdOpen(); + + if (phd == NULL) + { + return FCD_MODE_NONE; + } + + // Send an App reset command + aucBufOut[0] = 0; // Report ID, ignored + aucBufOut[1] = FCD_CMD_BL_ERASE; + hid_write(phd, aucBufOut, 65); + memset(aucBufIn, 0xCC, 65); // Clear out the response buffer + hid_read(phd, aucBufIn, 65); + + if (aucBufIn[0]==FCD_CMD_BL_ERASE && aucBufIn[1]==1) + { + fcdClose(phd); + phd = NULL; + + return FCD_MODE_BL; + } + + fcdClose(phd); + phd = NULL; + + return FCD_MODE_APP; +} + + +/** \brief Write new firmware into the FCD. + * \param pc Pointer to the new firmware data + * \param n64size The number of bytes in the data + * \return The FCD mode + * + * This function is used to upload new firmware into the FCD flash. + * + * \sa fcdBlErase + */ +EXTERN FCD_MODE_ENUM fcdBlWriteFirmware(char *pc, int64_t n64Size) +{ + hid_device *phd=NULL; + unsigned char aucBufIn[65]; + unsigned char aucBufOut[65]; + uint32_t u32AddrStart; + uint32_t u32AddrEnd; + uint32_t u32Addr; + BOOL bFinished=FALSE; + + phd = fcdOpen(); + + if (phd==NULL) + { + return FCD_MODE_NONE; + } + + // Get the valid flash address range + aucBufOut[0] = 0; // Report ID, ignored + aucBufOut[1] = FCD_CMD_BL_GET_BYTE_ADDR_RANGE; + hid_write(phd, aucBufOut, 65); + memset(aucBufIn, 0xCC, 65); // Clear out the response buffer + hid_read(phd, aucBufIn, 65); + + if (aucBufIn[0]!=FCD_CMD_BL_GET_BYTE_ADDR_RANGE || aucBufIn[1]!=1) + { + fcdClose(phd); + phd = NULL; + + return FCD_MODE_APP; + } + + u32AddrStart= + aucBufIn[2]+ + (((uint32_t)aucBufIn[3])<<8)+ + (((uint32_t)aucBufIn[4])<<16)+ + (((uint32_t)aucBufIn[5])<<24); + u32AddrEnd= + aucBufIn[6]+ + (((uint32_t)aucBufIn[7])<<8)+ + (((uint32_t)aucBufIn[8])<<16)+ + (((uint32_t)aucBufIn[9])<<24); + + // Set start address for flash + aucBufOut[0] = 0; // Report ID, ignored + aucBufOut[1] = FCD_CMD_BL_SET_BYTE_ADDR; + aucBufOut[2] = ((unsigned char)u32AddrStart); + aucBufOut[3] = ((unsigned char)(u32AddrStart>>8)); + aucBufOut[4] = ((unsigned char)(u32AddrStart>>16)); + aucBufOut[5] = ((unsigned char)(u32AddrStart>>24)); + hid_write(phd, aucBufOut, 65); + memset(aucBufIn, 0xCC, 65); // Clear out the response buffer + hid_read(phd, aucBufIn, 65); + + if (aucBufIn[0]!=FCD_CMD_BL_SET_BYTE_ADDR || aucBufIn[1]!=1) + { + fcdClose(phd); + phd = NULL; + + return FCD_MODE_APP; + } + + // Write blocks + aucBufOut[0] = 0; // Report ID, ignored + aucBufOut[1] = FCD_CMD_BL_WRITE_FLASH_BLOCK; + for (u32Addr=u32AddrStart; u32Addr+47<u32AddrEnd && u32Addr+47<n64Size && !bFinished; u32Addr+=48) + { + memcpy(&aucBufOut[3], &pc[u32Addr], 48); + + hid_write(phd, aucBufOut, 65); + memset(aucBufIn, 0xCC, 65); // Clear out the response buffer + hid_read(phd, aucBufIn, 65); + + if (aucBufIn[0]!=FCD_CMD_BL_WRITE_FLASH_BLOCK || aucBufIn[1]!=1) + { + bFinished = TRUE; + fcdClose(phd); + phd = NULL; + + return FCD_MODE_APP; + } + } + + fcdClose(phd); + phd = NULL; + + return FCD_MODE_BL; +} + + +/** \brief Verify firmware in FCd flash. + * \param pc Pointer to firmware data to verify against. + * \param n64Size Size of the data in pc. + * \return The FCD_MODE_BL if verification was succesful. + * + * This function verifies the firmware currently in the FCd flash against the firmware + * image pointed to by pc. The function return FCD_MODE_BL if the verification is OK and + * FCD_MODE_APP otherwise. + */ +EXTERN FCD_MODE_ENUM fcdBlVerifyFirmware(char *pc, int64_t n64Size) +{ + hid_device *phd=NULL; + unsigned char aucBufIn[65]; + unsigned char aucBufOut[65]; + uint32_t u32AddrStart; + uint32_t u32AddrEnd; + uint32_t u32Addr; + BOOL bFinished=FALSE; + + phd = fcdOpen(); + + if (phd==NULL) + { + return FCD_MODE_NONE; + } + + // Get the valid flash address range + aucBufOut[0] = 0; // Report ID, ignored + aucBufOut[1] = FCD_CMD_BL_GET_BYTE_ADDR_RANGE; + hid_write(phd, aucBufOut, 65); + memset(aucBufIn, 0xCC, 65); // Clear out the response buffer + hid_read(phd, aucBufIn, 65); + + if (aucBufIn[0]!=FCD_CMD_BL_GET_BYTE_ADDR_RANGE || aucBufIn[1]!=1) + { + fcdClose(phd); + phd = NULL; + + return FCD_MODE_APP; + } + + u32AddrStart= + aucBufIn[2]+ + (((uint32_t)aucBufIn[3])<<8)+ + (((uint32_t)aucBufIn[4])<<16)+ + (((uint32_t)aucBufIn[5])<<24); + + u32AddrEnd= + aucBufIn[6]+ + (((uint32_t)aucBufIn[7])<<8)+ + (((uint32_t)aucBufIn[8])<<16)+ + (((uint32_t)aucBufIn[9])<<24); + + // Set start address for flash + aucBufOut[0] = 0; // Report ID, ignored + aucBufOut[1] = FCD_CMD_BL_SET_BYTE_ADDR; + aucBufOut[2] = ((unsigned char)u32AddrStart); + aucBufOut[3] = ((unsigned char)(u32AddrStart>>8)); + aucBufOut[4] = ((unsigned char)(u32AddrStart>>16)); + aucBufOut[5] = ((unsigned char)(u32AddrStart>>24)); + hid_write(phd, aucBufOut, 65); + memset(aucBufIn, 0xCC, 65); // Clear out the response buffer + hid_read(phd, aucBufIn, 65); + + if (aucBufIn[0]!=FCD_CMD_BL_SET_BYTE_ADDR || aucBufIn[1]!=1) + { + fcdClose(phd); + phd = NULL; + + return FCD_MODE_APP; + } + + // Read blocks + aucBufOut[0] = 0; // Report ID, ignored + aucBufOut[1] = FCD_CMD_BL_READ_FLASH_BLOCK; + for (u32Addr=u32AddrStart; u32Addr+47<u32AddrEnd && u32Addr+47<n64Size && !bFinished; u32Addr+=48) + { + hid_write(phd, aucBufOut, 65); + memset(aucBufIn, 0xCC, 65); // Clear out the response buffer + hid_read(phd, aucBufIn, 65); + + if (aucBufIn[0]!=FCD_CMD_BL_READ_FLASH_BLOCK || aucBufIn[1]!=1) + { + bFinished = TRUE; + fcdClose(phd); + phd = NULL; + + return FCD_MODE_APP; + } + + if (memcmp(&aucBufIn[2],&pc[u32Addr],48)!=0) + { + bFinished = TRUE; + fcdClose(phd); + phd = NULL; + + return FCD_MODE_APP; + } + } + + fcdClose(phd); + phd = NULL; + + return FCD_MODE_BL; +} + + + +/** \brief Write FCD parameter (e.g. gain or filter) + * \param u8Cmd The command byte / parameter ID, see FCD_CMD_APP_SET_* + * \param pu8Data The parameter value to be written + * \param u8len Length of pu8Data in bytes + * \return One of FCD_MODE_NONE, FCD_MODE_APP or FCD_MODE_BL (see description) + * + * This function can be used to set the value of a parameter in the FCD for which there is no + * high level API call. It gives access to the low level API of the FCD and the caller is expected + * to be aware of the various FCD commands, since they are required to be supplied as parameter + * to this function. + * + * The return value can be used to determine the success or failure of the command execution: + * - FCD_MODE_APP : Reply from FCD was as expected (nominal case). + * - FCD_MODE_BL : Reply from FCD was not as expected. + * - FCD_MODE_NONE : No FCD was found + */ +EXTERN FCD_MODE_ENUM fcdAppSetParam(uint8_t u8Cmd, uint8_t *pu8Data, uint8_t u8len) +{ + hid_device *phd=NULL; + unsigned char aucBufOut[65]; + unsigned char aucBufIn[65]; + + + phd = fcdOpen(); + + if (phd == NULL) + { + return FCD_MODE_NONE; + } + + aucBufOut[0]=0; // Report ID, ignored + aucBufOut[1]=u8Cmd; + memcpy(aucBufOut+2, pu8Data,u8len); + hid_write(phd,aucBufOut,65); + + /* we must read after each write in order to empty FCD/HID buffer */ + memset(aucBufIn,0xCC,65); // Clear out the response buffer + hid_read(phd,aucBufIn,65); + + /* Check the response, if OK return FCD_MODE_APP */ + if (aucBufIn[0]==u8Cmd && aucBufIn[1]==1) { + fcdClose(phd); + phd = NULL; + + return FCD_MODE_APP; + } + + /* Response did not contain the expected bytes */ + fcdClose(phd); + phd = NULL; + + return FCD_MODE_BL; + +} + + +/** \brief Read FCD parameter (e.g. gain or filter) + * \param u8Cmd The command byte / parameter ID, see FCD_CMD_APP_GET_* + * \param pu8Data TPointer to buffer where the parameter value(s) will be written + * \param u8len Length of pu8Data in bytes + * \return One of FCD_MODE_NONE, FCD_MODE_APP or FCD_MODE_BL (see description) + * + * This function can be used to read the value of a parameter in the FCD for which there is no + * high level API call. It gives access to the low level API of the FCD and the caller is expected + * to be aware of the various FCD commands, since they are required to be supplied as parameter + * to this function. + * + * The return value can be used to determine the success or failure of the command execution: + * - FCD_MODE_APP : Reply from FCD was as expected (nominal case). + * - FCD_MODE_BL : Reply from FCD was not as expected. + * - FCD_MODE_NONE : No FCD was found + */ +EXTERN FCD_MODE_ENUM fcdAppGetParam(uint8_t u8Cmd, uint8_t *pu8Data, uint8_t u8len) +{ + hid_device *phd=NULL; + unsigned char aucBufOut[65]; + unsigned char aucBufIn[65]; + + phd = fcdOpen(); + if (phd == NULL) + { + return FCD_MODE_NONE; + } + + aucBufOut[0]=0; // Report ID, ignored + aucBufOut[1]=u8Cmd; + hid_write(phd,aucBufOut,65); + + memset(aucBufIn,0xCC,65); // Clear out the response buffer + hid_read(phd,aucBufIn,65); + /* Copy return data to output buffer (even if cmd exec failed) */ + memcpy(pu8Data,aucBufIn+2,u8len); + + /* Check status bytes in returned data */ + if (aucBufIn[0]==u8Cmd && aucBufIn[1]==1) { + fcdClose(phd); + phd = NULL; + + return FCD_MODE_APP; + } + + /* Response did not contain the expected bytes */ + fcdClose(phd); + phd = NULL; + + return FCD_MODE_BL; +} + |