From c1847bdd4facbd48359690d584accc65fbc13ab8 Mon Sep 17 00:00:00 2001 From: Sophia Papagiannaki Date: Tue, 12 May 2020 11:09:42 +0200 Subject: added firmware upgrade function --- o3000.c | 27 +++++++++++++++++++++++++++ o3000.h | 1 + 2 files changed, 28 insertions(+) diff --git a/o3000.c b/o3000.c index dd99f97..c68baf7 100644 --- a/o3000.c +++ b/o3000.c @@ -868,6 +868,33 @@ int __stdcall o3000_send_xml(int id, const char *msg, int msg_len) { } +/** + * Do firmware update of the device + * + * @param data pointer to firmware update data + * @param data_len update package lenght in bytes + * @return 0 on success, -1 on failure + */ +int __stdcall o3000_firmware_update(unsigned char *data, int data_len) { + + int ret; + + // paranoia checks + if(data == NULL) { + return -1; + } + + + if(data_len <= 0) { + return -1; + } + + // checking whether all connection are closed + ret = firmware_update(data, data_len); + return ret; +} + + /** * Disconnect a currently claimed USB connection. * Use this function if the driver is connected to an USB device. The o3000_connect() function-call is blocking now. diff --git a/o3000.h b/o3000.h index 51c8c3b..2ec4d07 100644 --- a/o3000.h +++ b/o3000.h @@ -88,6 +88,7 @@ int __stdcall o3000_disconnect(int id); int __stdcall o3000_send_xml(int id, const char *msg, int msg_len); +int __stdcall o3000_firmware_update(unsigned char *data, int data_len); #if defined(__cplusplus) || defined(c_plusplus) } // extern "C" -- cgit v1.2.1 From bf0831b3e877ec53f223b73c1de5f6028f24a885 Mon Sep 17 00:00:00 2001 From: Sophia Papagiannaki Date: Tue, 19 May 2020 18:30:53 +0200 Subject: Version 2.1.0 Implemented firmware update. --- CMakeLists.txt | 7 +- ChangeLog | 4 + md5.c | 276 +++++++++++++++++++++++++++++++ md5.h | 65 ++++++++ md5_helper.c | 54 ++++++ md5_helper.h | 33 ++++ o3000.c | 46 +++++- o3000.h | 4 + o3000_upgrade.c | 498 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ o3000_upgrade.h | 33 ++++ 10 files changed, 1009 insertions(+), 11 deletions(-) create mode 100644 md5.c create mode 100644 md5.h create mode 100644 md5_helper.c create mode 100644 md5_helper.h create mode 100644 o3000_upgrade.c create mode 100644 o3000_upgrade.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f61faa9..e25cc1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,8 +16,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake) # library version definition set(VERSION_MAJOR "2") -set(VERSION_MINOR "0") -set(VERSION_RELEASE "3") +set(VERSION_MINOR "1") +set(VERSION_RELEASE "0") set(VERSION_STR "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_RELEASE}") # pass macros to preprocessor @@ -37,6 +37,9 @@ add_library( ${LIB_NAME} SHARED o3000_private.h o3000_xfer_handler.c o3000_xfer_handler.h + o3000_upgrade.c + md5_helper.c + md5.c ) set_target_properties ( ${LIB_NAME} PROPERTIES diff --git a/ChangeLog b/ChangeLog index 0884cb0..4831862 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,10 @@ - ChangeLog O-3000 Host Driver ------------------------------------------------------------------------------- +Version 2.1.0 SP + 2020-05-19 + * Added firmware update function. + Version 2.0.3 2019-09-25 SP * Added "paranoia check" for wraparound_chunk_size check in handle_transfer(). diff --git a/md5.c b/md5.c new file mode 100644 index 0000000..8cef19e --- /dev/null +++ b/md5.c @@ -0,0 +1,276 @@ +/* + ********************************************************************** + ** md5.c ** + ** RSA Data Security, Inc. MD5 Message Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version ** + ********************************************************************** + */ + +/* + ********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD5 Message ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD5 Message Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + ********************************************************************** + */ + +/* -- include the following line if the md5.h header file is separate -- */ +#include "md5.h" + +/* forward declaration */ +static void Transform (); + +static unsigned char PADDING[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* F, G and H are basic MD5 functions: selection, majority, parity */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ +/* Rotation is separate from addition to prevent recomputation */ +#define FF(a, b, c, d, x, s, ac) \ + {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) \ + {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) \ + {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) \ + {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +void MD5Init (mdContext) +MD5_CTX *mdContext; +{ + mdContext->i[0] = mdContext->i[1] = (UINT4)0; + + /* Load magic initialization constants. + */ + mdContext->buf[0] = (UINT4)0x67452301; + mdContext->buf[1] = (UINT4)0xefcdab89; + mdContext->buf[2] = (UINT4)0x98badcfe; + mdContext->buf[3] = (UINT4)0x10325476; +} + +void MD5Update (mdContext, inBuf, inLen) +MD5_CTX *mdContext; +unsigned char *inBuf; +unsigned int inLen; +{ + UINT4 in[16]; + int mdi; + unsigned int i, ii; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* update number of bits */ + if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0]) + mdContext->i[1]++; + mdContext->i[0] += ((UINT4)inLen << 3); + mdContext->i[1] += ((UINT4)inLen >> 29); + + while (inLen--) { + /* add new character to buffer, increment mdi */ + mdContext->in[mdi++] = *inBuf++; + + /* transform if necessary */ + if (mdi == 0x40) { + for (i = 0, ii = 0; i < 16; i++, ii += 4) + in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | + (((UINT4)mdContext->in[ii+2]) << 16) | + (((UINT4)mdContext->in[ii+1]) << 8) | + ((UINT4)mdContext->in[ii]); + Transform (mdContext->buf, in); + mdi = 0; + } + } +} + +void MD5Final (mdContext) +MD5_CTX *mdContext; +{ + UINT4 in[16]; + int mdi; + unsigned int i, ii; + unsigned int padLen; + + /* save number of bits */ + in[14] = mdContext->i[0]; + in[15] = mdContext->i[1]; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* pad out to 56 mod 64 */ + padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); + MD5Update (mdContext, PADDING, padLen); + + /* append length in bits and transform */ + for (i = 0, ii = 0; i < 14; i++, ii += 4) + in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | + (((UINT4)mdContext->in[ii+2]) << 16) | + (((UINT4)mdContext->in[ii+1]) << 8) | + ((UINT4)mdContext->in[ii]); + Transform (mdContext->buf, in); + + /* store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) { + mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF); + mdContext->digest[ii+1] = + (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); + mdContext->digest[ii+2] = + (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); + mdContext->digest[ii+3] = + (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); + } +} + +/* Basic MD5 step. Transform buf based on in. + */ +static void Transform (buf, in) +UINT4 *buf; +UINT4 *in; +{ + UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + /* Round 1 */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 + FF ( a, b, c, d, in[ 0], S11, 3614090360U); /* 1 */ + FF ( d, a, b, c, in[ 1], S12, 3905402710U); /* 2 */ + FF ( c, d, a, b, in[ 2], S13, 606105819U); /* 3 */ + FF ( b, c, d, a, in[ 3], S14, 3250441966U); /* 4 */ + FF ( a, b, c, d, in[ 4], S11, 4118548399U); /* 5 */ + FF ( d, a, b, c, in[ 5], S12, 1200080426U); /* 6 */ + FF ( c, d, a, b, in[ 6], S13, 2821735955U); /* 7 */ + FF ( b, c, d, a, in[ 7], S14, 4249261313U); /* 8 */ + FF ( a, b, c, d, in[ 8], S11, 1770035416U); /* 9 */ + FF ( d, a, b, c, in[ 9], S12, 2336552879U); /* 10 */ + FF ( c, d, a, b, in[10], S13, 4294925233U); /* 11 */ + FF ( b, c, d, a, in[11], S14, 2304563134U); /* 12 */ + FF ( a, b, c, d, in[12], S11, 1804603682U); /* 13 */ + FF ( d, a, b, c, in[13], S12, 4254626195U); /* 14 */ + FF ( c, d, a, b, in[14], S13, 2792965006U); /* 15 */ + FF ( b, c, d, a, in[15], S14, 1236535329U); /* 16 */ + + /* Round 2 */ +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 + GG ( a, b, c, d, in[ 1], S21, 4129170786U); /* 17 */ + GG ( d, a, b, c, in[ 6], S22, 3225465664U); /* 18 */ + GG ( c, d, a, b, in[11], S23, 643717713U); /* 19 */ + GG ( b, c, d, a, in[ 0], S24, 3921069994U); /* 20 */ + GG ( a, b, c, d, in[ 5], S21, 3593408605U); /* 21 */ + GG ( d, a, b, c, in[10], S22, 38016083U); /* 22 */ + GG ( c, d, a, b, in[15], S23, 3634488961U); /* 23 */ + GG ( b, c, d, a, in[ 4], S24, 3889429448U); /* 24 */ + GG ( a, b, c, d, in[ 9], S21, 568446438U); /* 25 */ + GG ( d, a, b, c, in[14], S22, 3275163606U); /* 26 */ + GG ( c, d, a, b, in[ 3], S23, 4107603335U); /* 27 */ + GG ( b, c, d, a, in[ 8], S24, 1163531501U); /* 28 */ + GG ( a, b, c, d, in[13], S21, 2850285829U); /* 29 */ + GG ( d, a, b, c, in[ 2], S22, 4243563512U); /* 30 */ + GG ( c, d, a, b, in[ 7], S23, 1735328473U); /* 31 */ + GG ( b, c, d, a, in[12], S24, 2368359562U); /* 32 */ + + /* Round 3 */ +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 + HH ( a, b, c, d, in[ 5], S31, 4294588738U); /* 33 */ + HH ( d, a, b, c, in[ 8], S32, 2272392833U); /* 34 */ + HH ( c, d, a, b, in[11], S33, 1839030562U); /* 35 */ + HH ( b, c, d, a, in[14], S34, 4259657740U); /* 36 */ + HH ( a, b, c, d, in[ 1], S31, 2763975236U); /* 37 */ + HH ( d, a, b, c, in[ 4], S32, 1272893353U); /* 38 */ + HH ( c, d, a, b, in[ 7], S33, 4139469664U); /* 39 */ + HH ( b, c, d, a, in[10], S34, 3200236656U); /* 40 */ + HH ( a, b, c, d, in[13], S31, 681279174U); /* 41 */ + HH ( d, a, b, c, in[ 0], S32, 3936430074U); /* 42 */ + HH ( c, d, a, b, in[ 3], S33, 3572445317U); /* 43 */ + HH ( b, c, d, a, in[ 6], S34, 76029189U); /* 44 */ + HH ( a, b, c, d, in[ 9], S31, 3654602809U); /* 45 */ + HH ( d, a, b, c, in[12], S32, 3873151461U); /* 46 */ + HH ( c, d, a, b, in[15], S33, 530742520U); /* 47 */ + HH ( b, c, d, a, in[ 2], S34, 3299628645U); /* 48 */ + + /* Round 4 */ +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + II ( a, b, c, d, in[ 0], S41, 4096336452U); /* 49 */ + II ( d, a, b, c, in[ 7], S42, 1126891415U); /* 50 */ + II ( c, d, a, b, in[14], S43, 2878612391U); /* 51 */ + II ( b, c, d, a, in[ 5], S44, 4237533241U); /* 52 */ + II ( a, b, c, d, in[12], S41, 1700485571U); /* 53 */ + II ( d, a, b, c, in[ 3], S42, 2399980690U); /* 54 */ + II ( c, d, a, b, in[10], S43, 4293915773U); /* 55 */ + II ( b, c, d, a, in[ 1], S44, 2240044497U); /* 56 */ + II ( a, b, c, d, in[ 8], S41, 1873313359U); /* 57 */ + II ( d, a, b, c, in[15], S42, 4264355552U); /* 58 */ + II ( c, d, a, b, in[ 6], S43, 2734768916U); /* 59 */ + II ( b, c, d, a, in[13], S44, 1309151649U); /* 60 */ + II ( a, b, c, d, in[ 4], S41, 4149444226U); /* 61 */ + II ( d, a, b, c, in[11], S42, 3174756917U); /* 62 */ + II ( c, d, a, b, in[ 2], S43, 718787259U); /* 63 */ + II ( b, c, d, a, in[ 9], S44, 3951481745U); /* 64 */ + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +/* + ********************************************************************** + ** End of md5.c ** + ******************************* (cut) ******************************** + */ diff --git a/md5.h b/md5.h new file mode 100644 index 0000000..1a642c1 --- /dev/null +++ b/md5.h @@ -0,0 +1,65 @@ +/* + ********************************************************************** + ** md5.h -- Header file for implementation of MD5 ** + ** RSA Data Security, Inc. MD5 Message Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** + ** Revised (for MD5): RLR 4/27/91 ** + ** -- G modified to have y&~z instead of y&z ** + ** -- FF, GG, HH modified to add in last register done ** + ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 ** + ** -- distinct additive constant for each step ** + ** -- round 4 added, working mod 7 ** + ********************************************************************** + */ + +/* + ********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD5 Message ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD5 Message Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + ********************************************************************** + */ + +#ifndef __MD5_H__ +#define __MD5_H__ + +/* typedef a 32 bit type */ +// typedef unsigned long int UINT4; +typedef unsigned int UINT4; + +/* Data structure for MD5 (Message Digest) computation */ +typedef struct { + UINT4 i[2]; /* number of _bits_ handled mod 2^64 */ + UINT4 buf[4]; /* scratch buffer */ + unsigned char in[64]; /* input buffer */ + unsigned char digest[16]; /* actual digest after MD5Final call */ +} MD5_CTX; + +void MD5Init (); +void MD5Update (); +void MD5Final (); + +/* + ********************************************************************** + ** End of md5.h ** + ******************************* (cut) ******************************** + */ + +#endif // __MD5_H__ diff --git a/md5_helper.c b/md5_helper.c new file mode 100644 index 0000000..895ea3c --- /dev/null +++ b/md5_helper.c @@ -0,0 +1,54 @@ +/** +* @file md5_helper.c +* @brief MD5 checksum generation. +* @author Patrick Roth - roth@stettbacher.ch +* @date 2010-04-30 +* @copyright 2010 Stettbacher Signal Processing AG +* +* @remarks +* +*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+* 
+* +*/ + +#include + +#include "md5.h" + + +/** + * Generate the MD5 checksum. + * + * @param addr: A pointer to the start address. + * @param size: The size to compare. + * @param buf: Destination buffer; must provide room for 32+1 chars! + * @return A pointer to the first digit of the generated MD5 checksum. The + * checksum's length is always 16 bytes. + */ +void getMd5ChecksumString(void *addr, ssize_t size, char *buf) +{ + MD5_CTX md5; + + MD5Init(&md5); + MD5Update(&md5, (unsigned char*)(addr), (unsigned int)size); + MD5Final(&md5); + + for(int i = 0; i < 16; i++) { + sprintf(buf+i*2, "%02x", md5.digest[i]); + } + *(buf+32) = '\0'; +} diff --git a/md5_helper.h b/md5_helper.h new file mode 100644 index 0000000..fa7c292 --- /dev/null +++ b/md5_helper.h @@ -0,0 +1,33 @@ +/** +* @file md5_helper.h +* @brief MD5 checksum generation. +* @author Patrick Roth - roth@stettbacher.ch +* @date 2010-04-30 +* @copyright 2010 Stettbacher Signal Processing AG +* +* @remarks +* +*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+* 
+* +*/ + +#ifndef __MD5_HELPER_H +#define __MD5_HELPER_H + +void getMd5ChecksumString(void *addr, ssize_t size, char *buf); + +#endif /* __MD5_HELPER_H */ diff --git a/o3000.c b/o3000.c index c68baf7..1ea9f77 100644 --- a/o3000.c +++ b/o3000.c @@ -240,6 +240,7 @@ or a transfer may contain several frames. #include "o3000_private.h" #include "o3000.h" #include "o3000_xfer_handler.h" +#include "o3000_upgrade.h" #define CAM_IN_EP (1 | LIBUSB_ENDPOINT_IN) ///< endpoint for video data @@ -867,30 +868,57 @@ int __stdcall o3000_send_xml(int id, const char *msg, int msg_len) { return (send_xml(session, msg, msg_len)); } +/** + * Check whether all connections are closed. + * + * @return 0 if all sessions are closed, error code otherwise defined at @ref o3000.h. + */ +static int check_sessions(void) { + int i; + + for(i = 0; i < MAX_NUM_SESSION; i++) { + if(session_table[i] != NULL) { + break; + } + } + if (i < MAX_NUM_SESSION) { + printf("%s: Session %d is still open\n", __func__, i); + return O3000_ERROR_SESSION_STILL_OPEN; + } + return 0; +} /** * Do firmware update of the device * * @param data pointer to firmware update data - * @param data_len update package lenght in bytes - * @return 0 on success, -1 on failure + * @param data_len firmware update data lenght in bytes + * @return 0 on success, error code on failure defined at @ref o3000.h. */ int __stdcall o3000_firmware_update(unsigned char *data, int data_len) { - - int ret; + + int ret = 0; // paranoia checks if(data == NULL) { - return -1; + ret = O3000_ERROR_NOT_VALID_ARGUMENT; + printf("%s: Data pointer is NULL. error: %d\n", __func__, ret); + return ret; } - - if(data_len <= 0) { - return -1; + ret = O3000_ERROR_NOT_VALID_ARGUMENT; + printf("%s: Length of data is negative. error: %d\n", __func__, ret); + return ret; } - // checking whether all connection are closed + // checking whether all connections are closed + if ((ret = check_sessions())) { + printf("%s: Cannot proceed to firmware update: error %d\n", __func__, ret); + return ret; + } + ret = firmware_update(data, data_len); + return ret; } diff --git a/o3000.h b/o3000.h index 2ec4d07..ac2127e 100644 --- a/o3000.h +++ b/o3000.h @@ -53,6 +53,10 @@ #define O3000_ERROR_USB_TRANSFER_TIMEOUT -10 ///< USB transfer timeout #define O3000_ERROR_USB_EP_HALTED -11 ///< USB endpoint halted #define O3000_ERROR_LESS_DATA -12 ///< USB received less data than expected +#define O3000_ERROR_NOT_VALID_ARGUMENT -13 ///< at least one function argument is not valid +#define O3000_ERROR_SESSION_STILL_OPEN -14 ///< there is at least one session still open +#define O3000_ERROR_BOOTLOADER_TIMEOUT -15 ///< camera could not start in bootloader mode in given time +#define O3000_ERROR_USB_INIT_FAILURE -16 ///< failed to initialize the usb #define O3000_ERROR_OTHER -1000 ///< other (unspecified) error diff --git a/o3000_upgrade.c b/o3000_upgrade.c new file mode 100644 index 0000000..b05cf0f --- /dev/null +++ b/o3000_upgrade.c @@ -0,0 +1,498 @@ +/** +* @file o3000_upgrade.c +* @brief O-3000 firmware upgrade +* @author Sophia Papagiannaki - papagiannaki@stettbacher.ch +* @version 0.1 +* @date 2020-05-12 +* @copyright 2020 Stettbacher Signal Processing AG +* +* @remarks +* +*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+* 
+* +*/ + +#include +#include +#include +#include +#include +#include + +#include "o3000_upgrade.h" +#include "md5_helper.h" +#include "o3000.h" + +#define BUF_LEN 256 +#define TRANSFER_SIZE 512 +#define MAX_RETRIES 5 + +#define BL_OUT_EP (2) +#define XML_IN_EP (2 | LIBUSB_ENDPOINT_IN) +#define XML_OUT_EP (1) + +// table of valid bootloader ids +const char* bl_ids[] = { + "Streaming Camera Bootloader in HS mode", // version without proper product id + "Camera O-30xx (HS mode)", // version proper product id +}; + +// table of valid application ids +const char* app_ids[] = { + "Streaming Camera in HS mode", // version without proper product id (LEGACY) + "Camera O-3010 (HS mode)", // rolling shutter, mono version (LEGACY) + "Camera O-3020 (HS mode)", // rolling shutter, color version (LEGACY) + "Camera O-3010", // rolling shutter, mono version (without speed mode) + "Camera O-3020", // rolling shutter, color version (without speed mode) + "Camera O-3110", // global shutter, mono version + "Camera O-3120", // global shutter, color version +}; + +const uint16_t vid = 0x0483; +const uint16_t pid = 0xA098; + +static struct cam_usb_t { + struct libusb_context *ctx; // libusb context + struct libusb_device_handle *dev_handle; // the USB device handle + struct libusb_device *dev; // the USB device + struct libusb_device_descriptor desc; + uint32_t transfer_size; + struct libusb_transfer *transfer_data_out; ///< libusb specific transfer structure + struct libusb_transfer *transfer_xml_out; ///< libusb specific transfer structure + struct libusb_transfer *transfer_xml_in; ///< libusb specific transfer structure + int data_buf_size; ///< image data buffer size in bytes +} cam_usb; + +enum cam_mode_t { + CM_UNKNOWN = 0, + CM_BOOTLOADER, + CM_APPLICATION, +}; + + +volatile static bool xml_out_xfer_done; +volatile static bool data_out_xfer_done; + +/** + * @brief Transfer done callback for XML out + * + * Note: Transfer done only means submitted, not actually completed! + * @param transfer Pointer to XML transfer which has been submitted + */ +static void LIBUSB_CALL cb_xml_out_xfer_done(struct libusb_transfer *transfer) +{ + if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { + printf("%s: XML out transfer failed with status %d\n",__func__, transfer->status); + } + xml_out_xfer_done = true; +} + +/** + * @brief Transfer done callback for data out + * + * Note: Transfer done only means submitted, not actually completed! + * @param transfer Pointer to XML transfer which has been submitted + */ +static void LIBUSB_CALL cb_data_out_xfer_done(struct libusb_transfer *transfer) +{ + if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { + printf("%s: Data out transfer failed with status %d\n",__func__, transfer->status); + } + data_out_xfer_done = true; +} + +/** + Wait until XML transfer has finished. +*/ +static void wait_for_xml_xfer_done(void) +{ + while(!xml_out_xfer_done) { + libusb_handle_events(cam_usb.ctx); + }; +} + +/** + Wait until data transfer has finished. +*/ +static void wait_for_data_xfer_done(void) +{ + while(!data_out_xfer_done) { + libusb_handle_events(cam_usb.ctx); + }; +} + +/** + * @brief Send XML packet. + * + * Note: this function accesses the global structure cam_usb! + * @param msg Message content + * @param msg_len Message content length + * @retval 0: success, otherwise: error + */ +static int send_xml(char *msg, int msg_len) +{ + int retval; + + cam_usb.transfer_xml_out = libusb_alloc_transfer(0); + if (!cam_usb.transfer_xml_out) + return -1; + + // throw away transfer after use + cam_usb.transfer_xml_out->flags = LIBUSB_TRANSFER_FREE_TRANSFER; + + libusb_fill_bulk_transfer(cam_usb.transfer_xml_out, cam_usb.dev_handle, XML_OUT_EP, (unsigned char*)msg, + msg_len, cb_xml_out_xfer_done, (unsigned char*)msg, 0); + + retval = libusb_submit_transfer(cam_usb.transfer_xml_out); + if(retval) { + printf("error in %s",__func__); + return -1; + } + return 0; +} + +/** + * @brief Send binary packet. + * + * Note: this function accesses the global structure cam_usb! + * @param data_buf data buffer + * @param data_len data length + * @retval 0: success, otherwise: error + */ +static int send_data(unsigned char *data_buf, int data_len) +{ + int retval; + + cam_usb.transfer_data_out = libusb_alloc_transfer(0); + if (!cam_usb.transfer_data_out) + return -1; + + // throw away transfer after use + cam_usb.transfer_data_out->flags = LIBUSB_TRANSFER_FREE_TRANSFER; + + libusb_fill_bulk_transfer(cam_usb.transfer_data_out, cam_usb.dev_handle, BL_OUT_EP, (unsigned char*)data_buf, + data_len, cb_data_out_xfer_done, (unsigned char*)data_buf, 0); + + retval = libusb_submit_transfer(cam_usb.transfer_data_out); + if(retval) { + printf("error in %s",__func__); + return -1; + } + return 0; +} + + +/** + + Open libusb. + + Note: this function accesses the global structure cam_usb! + @retval Camera mode (see @ref cam_mode_t) + +*/ +static enum cam_mode_t usb_open(void) +{ + int r,i; + unsigned char buf[BUF_LEN]; + enum cam_mode_t mode = CM_UNKNOWN; + int retries = MAX_RETRIES; + int num_bl_ids; + int num_app_ids; + + if (libusb_init(&cam_usb.ctx) < 0) { + printf("Error: failed to initialise libusb\n"); + return mode; + } + + // setting up USB logging. That's tricky, as LOG_LEVEL_INFO prints (almost) no log messages, + // whereas the next more verbose level LOG_LEVEL_DEBUG will flood the terminal + libusb_set_debug(cam_usb.ctx, LIBUSB_LOG_LEVEL_INFO); + + // If the camera has just performed a reset, it might not be ready yet. + // We try MAX_RETRIES times, before we give up. + while(retries > 0) { + if((cam_usb.dev_handle = libusb_open_device_with_vid_pid(cam_usb.ctx, vid, pid)) == NULL) { + printf("retry: %d\n",retries); + retries--; + sleep(1); + } else { + break; + } + } + + if(retries <= 0) { + printf("Error: Could not find/open device after %d retries\nAre you root?\n",MAX_RETRIES); + libusb_exit(cam_usb.ctx); + return mode; + } + + if((r = libusb_claim_interface(cam_usb.dev_handle, 0)) < 0) { + printf("Error: usb_claim_interface error %d\n", r); + libusb_close(cam_usb.dev_handle); + libusb_exit(cam_usb.ctx); + return mode; + } + + cam_usb.dev = libusb_get_device(cam_usb.dev_handle); + + r = libusb_get_device_descriptor (cam_usb.dev, &cam_usb.desc); + if(r) { + printf("Error: libusb_get_device_descriptor error %d\n", r); + } + + // determine camera mode + r = libusb_get_string_descriptor_ascii(cam_usb.dev_handle, cam_usb.desc.iProduct, buf, BUF_LEN); + if(r > 0) { + + // get number of app/bootloader ids + num_app_ids = sizeof(app_ids)/sizeof(app_ids[0]); + num_bl_ids = sizeof(bl_ids)/sizeof(bl_ids[0]); + + // look for bootloader ids + for(i=0; i" \ + " %s " \ + "", + "application"); + + xml_out_xfer_done = false; + send_xml(msg, strlen(msg)); + wait_for_xml_xfer_done(); + + usb_close(); + cam_mode = usb_open(); + + return cam_mode; +} + +/** + * Create and send the firmware update package information. + * + * @param data pointer to firmware update data + * @param data_len firmware update data lenght in bytes + */ +static void create_and_send_update_info(unsigned char *data, int data_len) { + + char msg[BUF_LEN]; + char md5[33]; + + // compute MD5 digest + getMd5ChecksumString(data, data_len, md5); + + snprintf(msg, BUF_LEN, + "" \ + "" \ + "
%s
" \ + "%d" \ + "%s" \ + "
" \ + "
", + "application", data_len, md5); + + xml_out_xfer_done = false; + send_xml(msg, strlen(msg)); + wait_for_xml_xfer_done(); +} + +/** + * Send the firmware update package data, close and + * open again usb connection. + * + * @param data pointer to firmware update data + * @param data_len firmware update data lenght in bytes + * @return camera mode (see @ref cam_mode_t) + */ +static enum cam_mode_t send_update_data(unsigned char *data, int data_len) { + + int num_chunks; + int last_chunk_size; + enum cam_mode_t cam_mode = CM_UNKNOWN; + + // calculate number of chunks to be sent and size of last chunk + num_chunks = data_len / TRANSFER_SIZE; + last_chunk_size = data_len - (num_chunks * TRANSFER_SIZE); + + // send complete chunks + for(int i = 0; i < num_chunks; i++) { + data_out_xfer_done = false; + send_data(data + i*TRANSFER_SIZE, TRANSFER_SIZE); + wait_for_data_xfer_done(); + } + + // send incomplete chunk (if available) + if(last_chunk_size > 0) { + data_out_xfer_done = false; + send_data(data + num_chunks*TRANSFER_SIZE, last_chunk_size); + wait_for_data_xfer_done(); + } + + usb_close(); + cam_mode = usb_open(); + + return cam_mode; +} + +/** + * Try MAX_RETRIES to open camera and check if + * it started in bootloader mode. + * + * @return camera mode (see @ref cam_mode_t) + */ +static enum cam_mode_t wait_for_bootloader_mode() { + + int i; + enum cam_mode_t cam_mode = CM_UNKNOWN; + + for (i = 0; i > MAX_RETRIES; i++){ + + usb_close(); + + cam_mode = usb_open(); + + if(cam_mode != CM_BOOTLOADER) { + continue; // try again + } + break; // started in bootloader mode so exit loop and return + } + + return cam_mode; +} + +/** + * Do firmware update of the device. + * + * Note: Parameters are already checked in o3000_firmware_update. + * + * @param data pointer to firmware update data + * @param data_len firmware update data lenght in bytes + * @return 0 on success, error code on failure + */ +int firmware_update(unsigned char *data, int data_len) { + + enum cam_mode_t cam_mode = CM_UNKNOWN; + + cam_mode = usb_open(); + + if(cam_mode == CM_UNKNOWN) { + printf("Error: failed to initialise usb\n"); + return O3000_ERROR_USB_INIT_FAILURE; + } + + /** + * If camera started in application mode, + * it has to be forced into upgrade mode. + */ + if (cam_mode == CM_APPLICATION) { + cam_mode = force_into_upgrade_mode(); + } + + /** + * Now camera should start in bootloader mode. + * If not, try MAX_RETRIES times. If still + * not in bootloader mode, return error code. + */ + if (cam_mode != CM_BOOTLOADER) { + + cam_mode = wait_for_bootloader_mode(); + + if (cam_mode != CM_BOOTLOADER) { + printf("Error: Timeout! Camera won't start in bootloader mode\n"); + usb_close(); + return O3000_ERROR_BOOTLOADER_TIMEOUT; + } + } + + /** + * Camera is finally in bootloader mode, ready + * for the upgrade. So, send xml package first + * and then binary data. + */ + create_and_send_update_info(data, data_len); + + cam_mode = send_update_data(data, data_len); + + usb_close(); + + if(cam_mode == CM_APPLICATION) { + printf("Camera upgrade successful\n"); + } + else if (cam_mode == CM_BOOTLOADER) { + printf("Error: Camera is still in bootloader mode\n"); + return O3000_ERROR_OTHER; + } + else if (cam_mode == CM_UNKNOWN) { + printf("Error: failed to initialise usb\n"); + return O3000_ERROR_USB_INIT_FAILURE; + } + + return 0; + +} diff --git a/o3000_upgrade.h b/o3000_upgrade.h new file mode 100644 index 0000000..aa898fa --- /dev/null +++ b/o3000_upgrade.h @@ -0,0 +1,33 @@ +/** +* @file o3000_upgrade.c +* @brief O-3000 firmware upgrade +* @author Sophia Papagiannaki - papagiannaki@stettbacher.ch +* @version 0.1 +* @date 2020-05-12 +* @copyright 2020 Stettbacher Signal Processing AG +* +* @remarks +* +*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+* 
+* +*/ +#ifndef __O3000_UPGRADE_H +#define __O3000_UPGRADE_H + +int firmware_update(unsigned char *data, int data_len); + +#endif -- cgit v1.2.1 From 8da9dcf4f2387aa7f9c0aad28a87a04de98f3000 Mon Sep 17 00:00:00 2001 From: Sophia Papagiannaki Date: Mon, 15 Jun 2020 15:37:35 +0200 Subject: Modified some debug/error messages. --- o3000.c | 8 ++++---- o3000_upgrade.c | 32 ++++++++++++++++---------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/o3000.c b/o3000.c index 1ea9f77..37c0ab7 100644 --- a/o3000.c +++ b/o3000.c @@ -882,7 +882,7 @@ static int check_sessions(void) { } } if (i < MAX_NUM_SESSION) { - printf("%s: Session %d is still open\n", __func__, i); + printf("%s: Session %d is still open.\n", __func__, i); return O3000_ERROR_SESSION_STILL_OPEN; } return 0; @@ -902,18 +902,18 @@ int __stdcall o3000_firmware_update(unsigned char *data, int data_len) { // paranoia checks if(data == NULL) { ret = O3000_ERROR_NOT_VALID_ARGUMENT; - printf("%s: Data pointer is NULL. error: %d\n", __func__, ret); + printf("%s: Data pointer is NULL. error code: %d.\n", __func__, ret); return ret; } if(data_len <= 0) { ret = O3000_ERROR_NOT_VALID_ARGUMENT; - printf("%s: Length of data is negative. error: %d\n", __func__, ret); + printf("%s: Length of data is negative. error code: %d.\n", __func__, ret); return ret; } // checking whether all connections are closed if ((ret = check_sessions())) { - printf("%s: Cannot proceed to firmware update: error %d\n", __func__, ret); + printf("%s: Cannot proceed to firmware update: error code: %d.\n", __func__, ret); return ret; } diff --git a/o3000_upgrade.c b/o3000_upgrade.c index b05cf0f..264afc1 100644 --- a/o3000_upgrade.c +++ b/o3000_upgrade.c @@ -96,7 +96,7 @@ volatile static bool data_out_xfer_done; static void LIBUSB_CALL cb_xml_out_xfer_done(struct libusb_transfer *transfer) { if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - printf("%s: XML out transfer failed with status %d\n",__func__, transfer->status); + printf("Error: %s: XML out transfer failed with status %d.\n",__func__, transfer->status); } xml_out_xfer_done = true; } @@ -110,7 +110,7 @@ static void LIBUSB_CALL cb_xml_out_xfer_done(struct libusb_transfer *transfer) static void LIBUSB_CALL cb_data_out_xfer_done(struct libusb_transfer *transfer) { if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - printf("%s: Data out transfer failed with status %d\n",__func__, transfer->status); + printf("Error: %s: Data out transfer failed with status %d.\n",__func__, transfer->status); } data_out_xfer_done = true; } @@ -159,7 +159,7 @@ static int send_xml(char *msg, int msg_len) retval = libusb_submit_transfer(cam_usb.transfer_xml_out); if(retval) { - printf("error in %s",__func__); + printf("Error: %s: Failed to send XML packet.\n", __func__); return -1; } return 0; @@ -189,7 +189,7 @@ static int send_data(unsigned char *data_buf, int data_len) retval = libusb_submit_transfer(cam_usb.transfer_data_out); if(retval) { - printf("error in %s",__func__); + printf("Error: %s: Failed to send binary data packet.\n", __func__); return -1; } return 0; @@ -214,7 +214,7 @@ static enum cam_mode_t usb_open(void) int num_app_ids; if (libusb_init(&cam_usb.ctx) < 0) { - printf("Error: failed to initialise libusb\n"); + printf("Error: %s: Failed to initialise libusb.\n", __func__); return mode; } @@ -235,13 +235,13 @@ static enum cam_mode_t usb_open(void) } if(retries <= 0) { - printf("Error: Could not find/open device after %d retries\nAre you root?\n",MAX_RETRIES); + printf("Error: %s: Could not find/open device after %d retries\nAre you root?\n", __func__, MAX_RETRIES); libusb_exit(cam_usb.ctx); return mode; } if((r = libusb_claim_interface(cam_usb.dev_handle, 0)) < 0) { - printf("Error: usb_claim_interface error %d\n", r); + printf("Error: %s: usb_claim_interface error %d.\n", __func__, r); libusb_close(cam_usb.dev_handle); libusb_exit(cam_usb.ctx); return mode; @@ -251,7 +251,7 @@ static enum cam_mode_t usb_open(void) r = libusb_get_device_descriptor (cam_usb.dev, &cam_usb.desc); if(r) { - printf("Error: libusb_get_device_descriptor error %d\n", r); + printf("Error: %s: libusb_get_device_descriptor error %d.\n", __func__, r); } // determine camera mode @@ -281,11 +281,11 @@ static enum cam_mode_t usb_open(void) } if(mode == CM_UNKNOWN) { - printf("Error: could not make sense out of product %s\n", buf); + printf("Error: %s: Could not make sense out of product %s.\n", __func__, buf); } } else { - printf("Error: libusb_get_string_descriptor_ascii error %d\n", r); + printf("Error: %s: libusb_get_string_descriptor_ascii error %d.\n", __func__, r); } return mode; @@ -411,7 +411,7 @@ static enum cam_mode_t wait_for_bootloader_mode() { int i; enum cam_mode_t cam_mode = CM_UNKNOWN; - for (i = 0; i > MAX_RETRIES; i++){ + for (i = 0; i < MAX_RETRIES; i++){ usb_close(); @@ -442,7 +442,7 @@ int firmware_update(unsigned char *data, int data_len) { cam_mode = usb_open(); if(cam_mode == CM_UNKNOWN) { - printf("Error: failed to initialise usb\n"); + printf("Error: %s: Failed to initialise usb.\n", __func__); return O3000_ERROR_USB_INIT_FAILURE; } @@ -476,20 +476,20 @@ int firmware_update(unsigned char *data, int data_len) { * and then binary data. */ create_and_send_update_info(data, data_len); - + cam_mode = send_update_data(data, data_len); usb_close(); if(cam_mode == CM_APPLICATION) { - printf("Camera upgrade successful\n"); + printf("Camera upgrade successful.\n"); } else if (cam_mode == CM_BOOTLOADER) { - printf("Error: Camera is still in bootloader mode\n"); + printf("Error: %s: Camera is still in bootloader mode.\n", __func__); return O3000_ERROR_OTHER; } else if (cam_mode == CM_UNKNOWN) { - printf("Error: failed to initialise usb\n"); + printf("Error: %s: Failed to initialise usb.\n", __func__); return O3000_ERROR_USB_INIT_FAILURE; } -- cgit v1.2.1 From 8ad61ce3a1ac60f62d792c26831a7413ab573d79 Mon Sep 17 00:00:00 2001 From: "sophia.papagiannaki" Date: Tue, 28 Jul 2020 15:12:47 +0200 Subject: Working copy for testing on Windows. --- o3000.c | 28 ++++++++++++++++------------ o3000_upgrade.c | 7 +++---- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/o3000.c b/o3000.c index 37c0ab7..12c5ff1 100644 --- a/o3000.c +++ b/o3000.c @@ -869,23 +869,25 @@ int __stdcall o3000_send_xml(int id, const char *msg, int msg_len) { } /** - * Check whether all connections are closed. + * Get the number of open sessions. * - * @return 0 if all sessions are closed, error code otherwise defined at @ref o3000.h. + * @return number of open sessions */ -static int check_sessions(void) { - int i; +static int get_num_open_sessions(void) { + int i, num_sessions = 0; for(i = 0; i < MAX_NUM_SESSION; i++) { if(session_table[i] != NULL) { - break; + num_sessions ++; } } - if (i < MAX_NUM_SESSION) { - printf("%s: Session %d is still open.\n", __func__, i); - return O3000_ERROR_SESSION_STILL_OPEN; - } - return 0; + return num_sessions; + +// if (i < MAX_NUM_SESSION) { +// printf("%s: Session %d is still open.\n", __func__, i); +// return O3000_ERROR_SESSION_STILL_OPEN; +// } +// return 0; } /** @@ -897,7 +899,7 @@ static int check_sessions(void) { */ int __stdcall o3000_firmware_update(unsigned char *data, int data_len) { - int ret = 0; + int ret = 0, num_sessions; // paranoia checks if(data == NULL) { @@ -912,7 +914,9 @@ int __stdcall o3000_firmware_update(unsigned char *data, int data_len) { } // checking whether all connections are closed - if ((ret = check_sessions())) { + num_sessions = get_num_open_sessions(); + if (num_sessions > 0) { + ret = O3000_ERROR_SESSION_STILL_OPEN; printf("%s: Cannot proceed to firmware update: error code: %d.\n", __func__, ret); return ret; } diff --git a/o3000_upgrade.c b/o3000_upgrade.c index 264afc1..700a280 100644 --- a/o3000_upgrade.c +++ b/o3000_upgrade.c @@ -1,6 +1,8 @@ /** * @file o3000_upgrade.c * @brief O-3000 firmware upgrade +* @author Patrick Roth - roth@stettbacher.ch +* @author Patrick Brunner - brunner@stettbacher.ch * @author Sophia Papagiannaki - papagiannaki@stettbacher.ch * @version 0.1 * @date 2020-05-12 @@ -62,9 +64,6 @@ const char* app_ids[] = { "Camera O-3120", // global shutter, color version }; -const uint16_t vid = 0x0483; -const uint16_t pid = 0xA098; - static struct cam_usb_t { struct libusb_context *ctx; // libusb context struct libusb_device_handle *dev_handle; // the USB device handle @@ -225,7 +224,7 @@ static enum cam_mode_t usb_open(void) // If the camera has just performed a reset, it might not be ready yet. // We try MAX_RETRIES times, before we give up. while(retries > 0) { - if((cam_usb.dev_handle = libusb_open_device_with_vid_pid(cam_usb.ctx, vid, pid)) == NULL) { + if((cam_usb.dev_handle = libusb_open_device_with_vid_pid(cam_usb.ctx, O3000_VID, O3000_PID)) == NULL) { printf("retry: %d\n",retries); retries--; sleep(1); -- cgit v1.2.1 From e153b88661ef63f2ffc2d71beb10dbcf2c54211e Mon Sep 17 00:00:00 2001 From: "sophia.papagiannaki" Date: Wed, 29 Jul 2020 14:05:38 +0200 Subject: Modified log messages in o3000_upgrade.c --- o3000_upgrade.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/o3000_upgrade.c b/o3000_upgrade.c index 700a280..176be03 100644 --- a/o3000_upgrade.c +++ b/o3000_upgrade.c @@ -115,8 +115,8 @@ static void LIBUSB_CALL cb_data_out_xfer_done(struct libusb_transfer *transfer) } /** - Wait until XML transfer has finished. -*/ + * Wait until XML transfer has finished. + */ static void wait_for_xml_xfer_done(void) { while(!xml_out_xfer_done) { @@ -125,8 +125,8 @@ static void wait_for_xml_xfer_done(void) } /** - Wait until data transfer has finished. -*/ + * Wait until data transfer has finished. + */ static void wait_for_data_xfer_done(void) { while(!data_out_xfer_done) { @@ -196,13 +196,13 @@ static int send_data(unsigned char *data_buf, int data_len) /** - - Open libusb. - - Note: this function accesses the global structure cam_usb! - @retval Camera mode (see @ref cam_mode_t) - -*/ + * + * Open libusb. + * + * Note: this function accesses the global structure cam_usb! + * @retval Camera mode (see @ref cam_mode_t) + * + */ static enum cam_mode_t usb_open(void) { int r,i; -- cgit v1.2.1 From cd386dac7875843caa54be2190cf6dd4923db50a Mon Sep 17 00:00:00 2001 From: "sophia.papagiannaki" Date: Wed, 29 Jul 2020 14:08:26 +0200 Subject: Deleted comment lines. --- o3000.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/o3000.c b/o3000.c index 12c5ff1..cd4a928 100644 --- a/o3000.c +++ b/o3000.c @@ -882,12 +882,6 @@ static int get_num_open_sessions(void) { } } return num_sessions; - -// if (i < MAX_NUM_SESSION) { -// printf("%s: Session %d is still open.\n", __func__, i); -// return O3000_ERROR_SESSION_STILL_OPEN; -// } -// return 0; } /** @@ -951,7 +945,7 @@ int __stdcall o3000_disconnect(int id) { o3000_log(session, O3000_LOG_WARNING, "%s: driver is not connected!\n", __func__); return O3000_ERROR_DRV_NOT_CONNECTED; } - + o3000_log(session, O3000_LOG_DEBUG, "%s: disconnect USB device (release interface)\n", __func__); session->cleanup_transfers = TRUE; session->disconnect_dev = TRUE; @@ -965,6 +959,7 @@ int __stdcall o3000_disconnect(int id) { else if(retval != 0) { o3000_log(session, O3000_LOG_ERROR, "%s: releasing interface failed (code %d)\n", __func__, retval); } + return retval; } @@ -1092,7 +1087,7 @@ int __stdcall o3000_connect(int id, int device_nr, char *config_msg, int config_ o3000_log(session, O3000_LOG_ERROR, "%s: sending configuration string failed (code %d)\n", __func__, ret); } } - + /* * Finally enter main-loop */ -- cgit v1.2.1 From 6e04d6e2cc094aae7122627a96b35fb76038a17e Mon Sep 17 00:00:00 2001 From: Patrick Roth Date: Fri, 9 Oct 2020 13:24:58 +0200 Subject: update --> upgrade , more checks added Use firmware upgrade instead of update. The firmware update function does more sanity checks. --- o3000.c | 51 ++++++++++++++++++++++++++++++++++++--------------- o3000.h | 2 +- o3000_upgrade.c | 10 ++++------ o3000_upgrade.h | 2 +- 4 files changed, 42 insertions(+), 23 deletions(-) diff --git a/o3000.c b/o3000.c index cd4a928..f53bce2 100644 --- a/o3000.c +++ b/o3000.c @@ -885,38 +885,59 @@ static int get_num_open_sessions(void) { } /** - * Do firmware update of the device + * Do firmware upgrade of connected camera device. * - * @param data pointer to firmware update data + * Make sure, that all O-3000 sessions are closed before calling this + * function. Further, only one camera must be connected to the host system. + * Otherwise the update process will fail. + * + * @param data pointer to firmware update data binary * @param data_len firmware update data lenght in bytes * @return 0 on success, error code on failure defined at @ref o3000.h. */ -int __stdcall o3000_firmware_update(unsigned char *data, int data_len) { +int __stdcall o3000_firmware_upgrade(unsigned char *data, int data_len) { - int ret = 0, num_sessions; + int ret , num_sessions, num_cam; // paranoia checks if(data == NULL) { - ret = O3000_ERROR_NOT_VALID_ARGUMENT; - printf("%s: Data pointer is NULL. error code: %d.\n", __func__, ret); - return ret; + printf("%s: Firmware binary not defined!\n", __func__); + return O3000_ERROR_NOT_VALID_ARGUMENT; } if(data_len <= 0) { - ret = O3000_ERROR_NOT_VALID_ARGUMENT; - printf("%s: Length of data is negative. error code: %d.\n", __func__, ret); - return ret; + printf("%s: Invalid firmware binary length of %d bytes!\n", __func__, data_len); + return O3000_ERROR_NOT_VALID_ARGUMENT; } - // checking whether all connections are closed + // checking whether all camera sessions are closed num_sessions = get_num_open_sessions(); if (num_sessions > 0) { - ret = O3000_ERROR_SESSION_STILL_OPEN; - printf("%s: Cannot proceed to firmware update: error code: %d.\n", __func__, ret); - return ret; + printf("%s: There're still %d camera session(s) opened. Close all session to perform firmware upgrade.\n", __func__, num_sessions); + return O3000_ERROR_SESSION_STILL_OPEN; } - ret = firmware_update(data, data_len); + // checking whether only one camera is connected to the system + num_cam = o3000_get_num_cam(); + if(num_cam < 0) { + // forward error + printf("%s: Getting number of connected cameras failed with error code %d\n", __func__, num_cam); + return num_cam; + } + if(num_cam == 0) { + // no camera connected to the system + printf("%s: No camera connected to the host system.\n", __func__); + return O3000_ERROR_NODEV; + } + if(num_cam > 1) { + printf("%s: %d cameras connected to the host system. Make sure only one camera is connected.\n", __func__, num_cam); + return O3000_ERROR_OTHER; + } + // At this point only one camera is connected and all sessions are closed. Perform upgrade now. + ret = firmware_upgrade(data, data_len); + if(ret != 0) { + printf("%s: Firmware upgrade failed with error code %d.\n", __func__, ret); + } return ret; } diff --git a/o3000.h b/o3000.h index ac2127e..17aa6a5 100644 --- a/o3000.h +++ b/o3000.h @@ -92,7 +92,7 @@ int __stdcall o3000_disconnect(int id); int __stdcall o3000_send_xml(int id, const char *msg, int msg_len); -int __stdcall o3000_firmware_update(unsigned char *data, int data_len); +int __stdcall o3000_firmware_upgrade(unsigned char *data, int data_len); #if defined(__cplusplus) || defined(c_plusplus) } // extern "C" diff --git a/o3000_upgrade.c b/o3000_upgrade.c index 176be03..9e461e8 100644 --- a/o3000_upgrade.c +++ b/o3000_upgrade.c @@ -426,15 +426,13 @@ static enum cam_mode_t wait_for_bootloader_mode() { } /** - * Do firmware update of the device. - * - * Note: Parameters are already checked in o3000_firmware_update. - * - * @param data pointer to firmware update data + * Do firmware upgrade of the device. + * + * @param data pointer to firmware update data binary * @param data_len firmware update data lenght in bytes * @return 0 on success, error code on failure */ -int firmware_update(unsigned char *data, int data_len) { +int firmware_upgrade(unsigned char *data, int data_len) { enum cam_mode_t cam_mode = CM_UNKNOWN; diff --git a/o3000_upgrade.h b/o3000_upgrade.h index aa898fa..b88d38c 100644 --- a/o3000_upgrade.h +++ b/o3000_upgrade.h @@ -28,6 +28,6 @@ #ifndef __O3000_UPGRADE_H #define __O3000_UPGRADE_H -int firmware_update(unsigned char *data, int data_len); +int firmware_upgrade(unsigned char *data, int data_len); #endif -- cgit v1.2.1