AgeCommit message (Collapse)AuthorFilesLines
2017-12-14fix buildfairwaves/libxtrxSergey.Kostanbaev2-1/+1
2017-12-14initial libxtrx supportSergey.Kostanbaev11-33/+948
2017-12-04UHDDevice.cpp: add USRP B205mini supportPiotr Krysik1-0/+1
The B205mini is similar to the B200mini and runs OsmoTRX just fine, so let's make OsmoTRX recogonize and support it too. Change-Id: Iee575121248ea541f7abc49055e49ec2d30904c0
2017-11-07SocketsTest: Fix printing of non-nul-terminated stringHarald Welte1-1/+2
Change-Id: I33d0ddf851d84b81ab5252e3755422170cee54ee Fixes: Coverity CID#149363
2017-10-31jenkins: use osmo-clean-workspace.sh before and after buildNeels Hofmeyr1-0/+5
See osmo-ci change I2409b2928b4d7ebbd6c005097d4ad7337307dd93 for rationale. Depends: I2409b2928b4d7ebbd6c005097d4ad7337307dd93 Change-Id: I609f7c7c88b49f26e2e48e1f1cffed76d9e6fb5e
2017-10-28Tag/Release Welte1-0/+167
This is the first real tagged Osmocom release of OsmoTRX. [ Alexander Chemeris ] * EDGE: Add support for UmTRX. * Common: Get rid of a compilation warning. * Common: Make sure gLogEarly() log to the same facilities as the normal log. * transceiver: Properly handle MAXDLY. * transceiver: Add an option to generate random Access Bursts. * osmo-trx: Output Rx SPS as a part of configuration output. * transceiver: Do not pass transceiver state struct to function where it's not used. * makefile: Fix build from an external path. * radioDevice: GSMRATE macro must have parentheses around its definition. * uhd: Fix comment. * radioInterface: Initialize power scale with a meaningful default. * transceiver: Log channel number in DEBUG output of demoded bursts. * transceiver: Add an option to emulate a RACH delay in random filler mode. * UHD: Initial LimeSDR support. * CommonLibs: Remove unused files. * sigProcLib: Typo sybols -> symbols * radioBuffer: Remove extra ; at the end of inline function definitions. * sigProcLib: Fix documentation, sync argument names in .cpp and .h files. * sigProcLib: make energyDetect() simpler by returning actual energy. * sigProcLib: Rename demodulateBurst() to demodGmskBurst() for clarity. * sigProcLib: Slice SoftVector instead of signalVector for GMSK demod. * Call vectorSlicer() right before packing bits for transmission to osmo-bts. * CommonLibs: Print soft bits with less confidence to console when printing a soft vector. * BitVector: Remove convolutional codec - we don't use it in osmo-trx. * BitVector: Convert SoftVector from 0..1 to -1..+1 soft bits. * signalVector: Implement segment(). * vector: Introduce segmentMove() method to move data inside of a vector. * vector: Introduce shrink() function to shrink vector size without loosing data. * Move CorrType type from Transceiver to sigProcLib. * sigProcLib: rename signalError type to SignalError. * Move Transceiver::detectBurst() to sigProcLib to make it reusable. * Move BURST_THRESH from Transceiver.cpp to sigProcLib.h to make it reusable. * sigProcLib: Add operator<< to print CorrType to a string. * sigProcLib.h: Fix whitespaces. No non-whitespace changes. * Move Transceiver::demodulate() to sigProcLib to make it reusable. * sigProcLib: constify signalVector arguments for detectBurst() functions. * sigProcLib: Constify demodulation functions burst argument. * sigProcLib: Fix number of tail bits in random Normal Bursts and zero Stealing Bits. * Configuration: Variables allocated with 'new' must be freed with 'delete'. * BitVector: Remove Generator class. * PRBS: a Pseudo-random binary sequence (PRBS) generator class. [ Tom Tsou ] * EDGE: Fix USRP B210 device support * uhd: Correct timing alignment in 8-PSK and GMSK downlink bursts * EDGE: Fix demodulation slicer input * common: Restrict UDP binding to localhost only * common: Add mandatory length field to UDP receive calls * uhd: Update default E3XX settings * uhd: Set default Tx sampling to 4 sps * uhd: Make device offset check a private method * uhd: Set minimum UHD version requirement for E3XX * sigproc: Expand RACH, TSC, and EDGE correlation windows * transceiver: Do not report error on SETTSC when radio is on * transceiver: Add Rx samples-per-symbol option * radioInterface: Convert diversity argument to general type * iface: Add inner ring-buffer implementation * mcbts: Add multi-ARFCN channelizing filters * mcbts: Add multi-ARFCN radio support * sigproc: Adjust burst detection threshold criteria * egprs: Enable 8-PSK length vectors on the Tx interface * egprs: Enable 8-PSK burst detection when EDGE is enabled * transceiver: Remove HANDOVER warnings * mcbts: Allow out of order channel setup * radioInterface: Fix multi-channel buffer index bug * uhd: Add command line option for GPS reference * transceiver: Fix mixed GSMK / 8-PSK transmission * transceiver: Fix 4 SPS receive TOA value * sigproc: Fix missing 8-PSK tail symbols * uhd: Update USRP2/N200/N210 for 4 SPS Rx * sigproc: Match differential GMSK start/end bits to tail bits * uhd: Add missing B200 sample timing for 4 SPS receive * transceiver: Fix command build warning * uhd: Set minimum supported version to 3.9.0 * uhd: Add X300 sample timing for 4 SPS * Revert "uhd: Set minimum supported version to 3.9.0" * uhd: Add support for UHD-3.11 logging control * uhd: Increase MC-BTS FPGA clock rate to 51.2 MHz * Resampler: Fix initialization return checking * sigProcLib: Remove unreachable code and no-effect checks * sigProcLib: Check return status on downsampling * sigProcLib: Fix negative value check on unsigned value * Resampler: Fix non-array delete for filter taps * Transceiver: Remove unsigned negative compares * Configuration: Fix const and signedness compile warnings * config: Remove OpenBTS style sqlite configuration * radioInterface: Remove UmTRX 'diversity' option * build: Require and check for gcc C++11 support * uhd: Use map container for for device parameter access * sigProcLib: Remove unused functions from public interface * uhd: Add non-UmTRX channel swap support * uhd: Fix Tx-RX timing offset setting * uhd: Fix USRP2/N200/N210 device detection * transceiver: Fix POWEROFF crash on USRP2/N200/X300 devices * sigProcLib: Fix complex/real vector flag in Laurent modulator * sigProcLib: Remove heap based signal vector allocations * common: Declare explicit Vector move constructor * sigProcLib: Remove trigonometric tables * sigProcLib: Use explicit NaN check in sinc table generation * sigProcLib: Replace dynamically allocated resampling buffers * sigProcLib: Specify standard namespace for isnan() * uhd: Always specify samples-per-symbol for device lookup * LimeSDR: set approximate tx offset value to make GSM work [ Neels Hofmeyr ] * add basic .gitignore * configure.ac: check for boost/config.hpp header * The INSTALL file is being overwritten by autoreconf, but it is committed as empty file. As a result, the INSTALL file always shows as modified. Instead, remove INSTALL from git and ignore it. * add contrib/jenkins.sh, for gerrit build bot [ pierre.baudry ] * transceiver: Fix mismatched allocations and deallocations [ Holger Hans Peter Freyther ] * debian: Require fftw3 header files for osmo-trx [ Max ] * Add gerrit settings * Integrate Debian packaging changes * Remove embedded sqlite3 * Fix building against sqlite3 * Add autoconf-archive to dependencies * debian: remove obsolete dependency * deb: remove unused dependency * Remove redundant explicit dependency * Use release helper from libosmocore [ Ruben Undheim ] * Do not embed sqlite3 when building [ Philipp Maier ] * buildenv: Turn off native architecture builds * cosmetic: Make parameter lists uniform * Add test program to verify convolution implementation * ssedetect: Add runtime CPU detection * cosmetic: remove code duplication * buildenv: Make build CPU invariant * buildenv: Split up SSE3 and SSE4.1 code * cosmetic: Add info about SSE support [ Vadim Yanitskiy ] * buildenv: correct the ax_sse macro description * buildenv: actually strip unused cpuid functionality * buildenv: fix build on systems without SIMD support * buildenv: cosmetic changes * buildenv: check for __builtin_cpu_supports call support * ssedetect: call __builtin_cpu_supports() only if supported [ Pau Espin Pedrol ] * cosmetic: transciever: Remove trailing whitespaces * transceiver: Avoid sending clock indications when trx is not powered on * Add -j option to bind to specific address [ ignasj ] * LimeSDR: Change device detection to work with USB and PCIe versions * LimeSDR: change tx window type to TX_WINDOW_FIXED * LimeSDR: Fix sample value range [ Harald Welte ] * Add '-t' command line option to enable SCHED_RR * Import git-version-gen and update AC_INIT() Change-Id: Ibf3be6cc25e9b20d625b1f67972114b7f613f05c
2017-10-28Import git-version-gen and update AC_INIT()Harald Welte2-1/+154
In AC_INIT(), it still stated openbts. Let's clean this up and use the same method of version generation that we use in all other osmocom projects, too. Change-Id: Ie7ae0585955aebdc3950b1dd8bff0d1fff3be212
2017-08-28Use release helper from libosmocoreMax2-0/+5
See https://osmocom.org/projects/cellular-infrastructure/wiki/Make_a_new_release for details. Change-Id: Ieb843923d8f534654413be695f2b5f0c87b75520 Related: OS#1861
2017-08-16Add -j option to bind to specific addressPau Espin Pedrol6-28/+40
Before this patch, the binding of the listening sockets was hardcoded to a local IP. Change-Id: I9ba184a1251c823e413a9230943ed263e52142ec
2017-07-20Remove redundant explicit dependencyMax1-1/+1
There's no need to explicitly mention library package because ${shlibs:Depends} will take care of it automatically. Change-Id: Ibd9cfc3673d828122edb85ba9de7ceb77f0299d0
2017-07-20Add '-t' command line option to enable SCHED_RRHarald Welte1-2/+29
SCHED_RR allows us to operate osmo-trx reliable even under exceptionally high system load, as the realtime scheduler priority will have higher priority than the other "regular" tasks on the system. Change-Id: Ia2452b9763960b2be37fbeee9d832554da68a53f Closes: OS#2344
2017-07-10LimeSDR: Fix sample value rangeignasj1-2/+1
when "sc16" stream arg is passed to SoapyUHD sample value range is -32768 to 32767 Change-Id: I58b8b6b71648bd9cbc105ddaaa9a7cf0a31b3d47
2017-07-10LimeSDR: change tx window type to TX_WINDOW_FIXEDignasj1-1/+1
It seems that TX_WINDOW_USRP1 is for devices that do not support tx sync to timestamp. LimeSDR supports it. Changing to TX_WINDOW_FIXED greatly reduces number of "dumping stale buffer" messages Modified to match current master by Harald Welte. Change-Id: I8de5b165ccd72a62b0f16655618e24ca740d9637
2017-07-10LimeSDR: Change device detection to work with USB and PCIe versionsignasj1-1/+1
Modified to match current master by Harald Welte. Change-Id: Ie43610de0b2196d84caf09717ec8c8ca75ab926d
2017-07-06deb: remove unused dependencyMax1-2/+1
The libdbd dependency is not used because libsqlite3 is used directly - adjust debian/control to match. Change-Id: Id2ab1facad703fa0c1d45084e70d41e73dbad6e7 Related: OS#1929
2017-07-04transceiver: Avoid sending clock indications when trx is not powered onPau Espin Pedrol2-8/+6
Stop calling writeClockInterface() when receiving commands in Transceiver::driveControl, otherwise it fools osmo-bts-trx clock skew check because it is always sending a clock indication with the same fn when it issues any commands during the time in between CMD POWEROFF and RSP POWERON, because fn is not increased during that period. Also use mForceClockInterface flag to delay delivery of first IND CLOCK until we start serving frames, otherwise the first one is sent and only after a long period of time the next clock indications are sent, when the radio starts to process bursts. That makes osmo-bts-trx unhappy because it expects to receive an IND CLOCK aprox at least every 400 frames. This way also we send the first IND CLOCK after the RSP POWERON 0 response. Change-Id: I91b81a4d7627cec39c1814a39ed4be306681b874
2017-07-04cosmetic: transciever: Remove trailing whitespacesPau Espin Pedrol2-12/+11
Change-Id: Ib3fbe768048b2a34a75ace9688e306720e67019a
2017-06-29LimeSDR: set approximate tx offset value to make GSM workTom Tsou1-1/+1
may be fine-tuned in the future Modified to match current master by Harald Welte. Change-Id: Ied215ca9e9d9c346c2a654f96785d1b87b075129
2017-06-27uhd: Always specify samples-per-symbol for device lookupTom Tsou1-2/+2
Fix MCBTS device setup where the map access was failing on the wrong assumption that all devices support 1-SPS TX-RX operation. Some devices and/or configurations such as LIMESDR and MCBTS only support running at 4-SPS. Even though certain settings (e.g. number of physical channels or the FPGA clocking rate) are not dependent on the SPS value, we still need to specify because we use SPS as a parameter for device classification. Fixes: OS#2341 Change-Id: I56e939285d585cc38efa6c329e30e3acebb734eb Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2017-06-22sigProcLib: Specify standard namespace for isnan()Tom Tsou1-1/+1
In commit a3dce85f "sigProcLib: Use explicit NaN check in sinc table generation" Use of std::isnan(double) was added without namespace specifier, which may cause build issues depending on whether the C version isnan() call is available. Add standard namespace to force C++ call usage and potential build issues. Change-Id: I49328c43fdd690a4e6a2b2e949411aaf5674ead1
2017-06-22sigProcLib: Replace dynamically allocated resampling buffersTom Tsou2-76/+39
Instead use object allocated STL vectors. This simplifies code, removes the need to explicitly release buffers, and fixes a memory leak in destructor deallocation. Also, remove simplified init and release sub-calls. Maintain partition filter allocation using memalign() for SIMD alignment requirements. Change-Id: Ie836982794c10fb1b6334e40592d44b200454846
2017-06-19sigProcLib: Use explicit NaN check in sinc table generationTom Tsou1-9/+3
Using "x < 0.01" is a crude check for detecting NaN condition, which occurs in a sinc call when x = 0 due to divide-by-zero. Use stdlib isnan() call for this purpose. Also, as the table is created only once during initialization, use double floats for table value generation. Change-Id: I3a838fe3139fa977dfe906246020a14451185714
2017-06-19sigProcLib: Remove trigonometric tablesTom Tsou1-36/+8
Trigonometric sin/cos tables are unused after initialization. There is no benefit to implementing lookup tables for run-once operations. Also perform initial calculations in double width because there is no penalty for doing so. Change-Id: I45bba5daf8610cbba6af95b92c2142f2256491ff
2017-06-19common: Declare explicit Vector move constructorTom Tsou1-2/+2
Vector class already has a semantically odd non-const copy constructor that serves the same function as a C++11 move constructor. Make the move constructor semantics explicit and address Coverity at the same time. Change-Id: I22e0099abe601b0c59beee808f7560837c6977dd Fixes: Coverity CID 170738
2017-06-16sigProcLib: Remove heap based signal vector allocationsTom Tsou1-84/+51
The osmo-trx internals rely heavily on dynamic alloction of I/Q signal vectors. In a number of cases there is no reason to to use dynamic rather than stack based allocation. Convert these cases accordingly. Change-Id: If53da1bf77b5944b6117765fa98ce12e1ccdeede
2017-06-16sigProcLib: Fix complex/real vector flag in Laurent modulatorTom Tsou1-1/+0
The modulator vector to be shaped by Laurent C1 pulse is complex, but was set as real. The error does not affect behaviour because we only support complex-complex and complex-real calculations; real-real convolution is not supported. So in this case the data vector was already assumed to be complex despite the improper flag setting. Change-Id: I03afc6a93a01fde7a9a02e4eb9d201d3ee37d21a
2017-06-16transceiver: Fix POWEROFF crash on USRP2/N200/X300 devicesTom Tsou1-5/+4
Upon issuing POWEROFF command to a running transceiver, UHD interfacing thread state may become undefined if the device is stopped with I/O threads still active. Bad behavior is device dependent with only network based USRP devices affected. USB based device thread behavior stops and shutdowns as expected. Tested with N200, X300, and B210. Tested solutions include the following: 1. Set pthread_setcanceltype() with PTHREAD_CANCEL_ASYNCHRONOUS 2. Add sleep delay to allow I/O threads to timeout before stopping the device 3. Wait for I/O threads to join after cancellation before stopping the device This patch resolves the issue by with the third approach. Number 1 is not guaranteed to always work with UHD internals as driver code may explicitly set thread parameters. Using sleep calls to fix order-of-operation issues is almost never a good idea. Change-Id: Ib72ab98a27a02084b040319046c92d1c4157ae4c
2017-06-16uhd: Fix USRP2/N200/N210 device detectionTom Tsou1-12/+12
Commit 1fb0ce67 "uhd: Use map container for for device parameter access" inadvertently removed the string identifier for the USRP2 and derived devices (N200/N210). Add the missing USRP2 string identifier. Also search for partial string matches in the UHD provided device and mboard stings. This is necessary to guarantee that strings such as "N200r3" instead of just "N200" are sucessfully found. Tested with N200, X310, B200mini and B210 devices. Change-Id: Ide4e22418e2cc469418cba018970cb0eb9906697
2017-06-15uhd: Fix Tx-RX timing offset settingTom Tsou1-1/+1
Integer timestamp offset was set to zero due to bad cast-operator precedence. Change-Id: Ib1f524cc86416699b3c143e5faddb33d61380767
2017-06-14uhd: Add non-UmTRX channel swap supportTom Tsou1-21/+44
Previously an UmTRX-only feature. Change-Id: I4a0e0c1d69e89993158e948535ad33f54e568d2d Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2017-06-14sigProcLib: Remove unused functions from public interfaceTom Tsou2-467/+52
Also remove entirely completely unused calls. Most of these calls have been around since OpenBTS conception. Nearly a decade is long enough time for deprecation. Change-Id: Ifc122aaff23414c363b4b00f99061eed8a6902d0
2017-06-12uhd: Use map container for for device parameter accessTom Tsou1-274/+84
OsmoTRX is written in C++ so we might as well use built-in container types when applicable. Map access allows removal of significant amounts of special device handling code. Aggregate device rates and timing offsets into a single table with access keyed by device/tx-sps/rx-sps tuples. Change-Id: I8660f75a2b2a13488b913c07637bdd0f5f0f4cf9 Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2017-06-09build: Require and check for gcc C++11 supportTom Tsou3-0/+1022
It is now 2017. We can and should be able to use C++11 features now. Change-Id: I96477e4125390b17b43a3705bb1daf98fa01c9bb Signed-off-by: Tom Tsou <tom.tsou@ettus.com>
2017-06-08PRBS: a Pseudo-random binary sequence (PRBS) generator class.Alexander Chemeris4-0/+157
Implemeted with a Galois LFSR for speed and flexibility compared to Fibonacci version. Aliases for three popular PRBS' are added for convenience - PRBS9, PRBS15 and PRBS64. Note that we can't test PRBS64 completely, because the sequence is too long to be generated. Change-Id: Ib5331ba5d0b5819929541686fdd87905e2177b74
2017-06-08ssedetect: call __builtin_cpu_supports() only if supportedVadim Yanitskiy3-1/+11
Some compilers don't support the __builtin_cpu_supports built-in, so let's make them able to compile the project anyway. Change-Id: I0c90402d8e4c9f196c54b066ff30891c8de3ad2b
2017-06-08buildenv: check for __builtin_cpu_supports call supportVadim Yanitskiy1-0/+27
The '__builtin_cpu_supports' is a GCC's built-in function which returns a positive integer if the run-time CPU supports specified SIMD feature and returns 0 otherwise. This change adds a new check, whether compiler supports this call. See /gcc/X86-Built-in-Functions.html at gcc.gnu.org for reference. Change-Id: I797f638573e8c3aae39c28abb157ce2ac419f3f7
2017-06-08buildenv: cosmetic changesVadim Yanitskiy1-6/+8
Change-Id: I9c52f2981513fa6322bdf992215e3e099ac3ddee
2017-06-08buildenv: fix build on systems without SIMD supportVadim Yanitskiy1-2/+3
HAVE_SSE3 and HAVE_SSE4_1 were never defined if CPU architecture doesn't match the (86*|x86_64*|amd64*) condition. Change-Id: I3350b14dbc91e9b388d0b04a0ed22ba27d436313
2017-06-08buildenv: actually strip unused cpuid functionalityVadim Yanitskiy3-164/+0
Despite the macro message says, that cpuid functionality was stripped it was still partially preset and wasn't used anyhow. Change-Id: I380bc9c13d29319685781ef27973afe6744fcf3d
2017-06-08buildenv: correct the ax_sse macro descriptionVadim Yanitskiy1-6/+5
Change-Id: I4ce65443c8a33ae9add8f6da9d911c3178472ab2
2017-05-30BitVector: Remove Generator class.Alexander Chemeris2-86/+0
It is not used in osmo-trx, because we're not doing FEC or CRC checks. Change-Id: I1509e785c1187ebdafe5b2518bd298fbbd1cd036
2017-05-30Configuration: Variables allocated with 'new' must be freed with 'delete'.Alexander Chemeris1-3/+3
Thank you Valgrind. Change-Id: I8477e4e37282947f9841cee9002565631ca0c0b6
2017-05-29sigProcLib: Fix number of tail bits in random Normal Bursts and zero ↵Alexander Chemeris1-3/+9
Stealing Bits. This bug only affects generation of normal bursts filled with random bits which are used in test mode. It doesn't affect operation of osmo-trx during normal operation. That's why it has stayed unnoticed for so long. Each Normal Burst has 3 tail bits, not 4. Also it's better to set stealing bits to 0 for maximum compatibility. We may want to introduce a selector for each bit whether to set it to 0, to 1 or to a random number. Change-Id: I0377029556c8b681b3ba3b635bf19572b34546ea
2017-05-19debian: remove obsolete dependencyMax1-1/+0
This should fix package build for Ubuntu 17.04: obsolete package hardening-wrapper was removed which cause .deb build failure. The dependency on it is incorrect to begin with because we use DEB_BUILD_MAINT_OPTIONS instead. Change-Id: I3ea72b4123a280a846086d083c4f3189d611f8cf
2017-05-19radioInterface: Remove UmTRX 'diversity' optionTom Tsou9-406/+16
The 'diversity' option was an experimental 2 antenna receiver implementation for UmTRX. The implementation has not been maintained and current working status is unknown. In addition to code rot, Coverity is triggering errors in the associated code sections. Removal of code cleans up many cases of special handling that were necessary to accommodate the implementation. Change-Id: I46752ccf5dbcffbec806081dec03e69a0fbdcdb7
2017-05-19cosmetic: Add info about SSE supportPhilipp Maier1-0/+16
The osmo-trx binary outputs no info about its SSE support status. This commits adds some putput that informs about the SSE of the binary and also tells which of the SSE levels the CPU supports. Change-Id: Iacc83fd668c31644e0efb3e18962cf2870ed1daf
2017-05-19buildenv: Split up SSE3 and SSE4.1 codePhilipp Maier12-661/+893
Currently we find SSE3 and SSE4.1 code mixed togehter along with generic code in one file. This introduces the risk that the compiler exidantly mixes SSE4.1 instructions into an SSE3, or even worse into a generic code path. This commit splits the SSE3 and SSE4.1 code into separate files and compiles them with the matching target options. Change-Id: I846e190e92f1258cd412d1b2d79b539e204e04b3
2017-05-19buildenv: Make build CPU invariantPhilipp Maier1-166/+16
Currently the build environment checks which extension the current CPU supports and picks the compiler flags accordingly. If the build is happening on a machine that does not support the extensions we need (SSE3, SSE4.1), the binary will lack those extensions, even if its intended to be used on a more powerful machine that would support the extensions. This commit removes the CPU tests from the build process. Change-Id: Ic913aa13c23c348ae62e78c9dfd6ed8b0a62798c
2017-05-19cosmetic: remove code duplicationPhilipp Maier5-35/+49
The ARM and the X86 implementation of the conversion functions share the same, non cpu specific implementation in separate files. This commit removes the code duplication by putting the generic implementation into a convert_base.c, similar to to convolve_base.c Change-Id: Ic8d8534a343e27cde79ddc85be4998ebd0cb6e5c
2017-05-19ssedetect: Add runtime CPU detectionPhilipp Maier6-49/+142
The current implementation can select the SSE support level during compiletime only. This commit adds functionality to automatically detect and switch the SSE support level and automatically switch the Implementation if the CPU does not support the required SSE level. Change-Id: Iba74f8a6e4e921ff31e4bd9f0c7c881fe547423a