summaryrefslogtreecommitdiffstats
path: root/src/libirecovery.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libirecovery.c')
-rw-r--r--src/libirecovery.c108
1 files changed, 42 insertions, 66 deletions
diff --git a/src/libirecovery.c b/src/libirecovery.c
index 009ad76..fde15a9 100644
--- a/src/libirecovery.c
+++ b/src/libirecovery.c
@@ -71,6 +71,33 @@
71 71
72#include "libirecovery.h" 72#include "libirecovery.h"
73 73
74// Reference: https://stackoverflow.com/a/2390626/1806760
75// Initializer/finalizer sample for MSVC and GCC/Clang.
76// 2010-2016 Joe Lowe. Released into the public domain.
77
78#ifdef __cplusplus
79 #define INITIALIZER(f) \
80 static void f(void); \
81 struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \
82 static void f(void)
83#elif defined(_MSC_VER)
84 #pragma section(".CRT$XCU",read)
85 #define INITIALIZER2_(f,p) \
86 static void f(void); \
87 __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
88 __pragma(comment(linker,"/include:" p #f "_")) \
89 static void f(void)
90 #ifdef _WIN64
91 #define INITIALIZER(f) INITIALIZER2_(f,"")
92 #else
93 #define INITIALIZER(f) INITIALIZER2_(f,"_")
94 #endif
95#else
96 #define INITIALIZER(f) \
97 static void f(void) __attribute__((__constructor__)); \
98 static void f(void)
99#endif
100
74struct irecv_client_private { 101struct irecv_client_private {
75 int debug; 102 int debug;
76 int usb_config; 103 int usb_config;
@@ -603,24 +630,6 @@ static libusb_context* irecv_hotplug_ctx = NULL;
603#endif 630#endif
604#endif 631#endif
605 632
606static void _irecv_init(void)
607{
608 char* dbglvl = getenv("LIBIRECOVERY_DEBUG_LEVEL");
609 if (dbglvl) {
610 libirecovery_debug = strtol(dbglvl, NULL, 0);
611 irecv_set_debug_level(libirecovery_debug);
612 }
613#ifndef USE_DUMMY
614#ifndef _WIN32
615#ifndef HAVE_IOKIT
616 libusb_init(&libirecovery_context);
617#endif
618#endif
619 collection_init(&listeners);
620 mutex_init(&listener_mutex);
621#endif
622}
623
624static void _irecv_deinit(void) 633static void _irecv_deinit(void)
625{ 634{
626#ifndef USE_DUMMY 635#ifndef USE_DUMMY
@@ -637,43 +646,24 @@ static void _irecv_deinit(void)
637#endif 646#endif
638} 647}
639 648
640static thread_once_t init_once = THREAD_ONCE_INIT; 649INITIALIZER(_irecv_init)
641static thread_once_t deinit_once = THREAD_ONCE_INIT;
642
643#ifndef HAVE_ATTRIBUTE_CONSTRUCTOR
644 #if defined(__llvm__) || defined(__GNUC__)
645 #define HAVE_ATTRIBUTE_CONSTRUCTOR
646 #endif
647#endif
648
649#ifdef HAVE_ATTRIBUTE_CONSTRUCTOR
650static void __attribute__((constructor)) libirecovery_initialize(void)
651{ 650{
652 thread_once(&init_once, _irecv_init); 651 char* dbglvl = getenv("LIBIRECOVERY_DEBUG_LEVEL");
653} 652 if (dbglvl) {
654 653 libirecovery_debug = strtol(dbglvl, NULL, 0);
655static void __attribute__((destructor)) libirecovery_deinitialize(void) 654 irecv_set_debug_level(libirecovery_debug);
656{
657 thread_once(&deinit_once, _irecv_deinit);
658}
659#elif defined(_WIN32)
660BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved)
661{
662 switch (dwReason) {
663 case DLL_PROCESS_ATTACH:
664 thread_once(&init_once, _irecv_init);
665 break;
666 case DLL_PROCESS_DETACH:
667 thread_once(&deinit_once, _irecv_deinit);
668 break;
669 default:
670 break;
671 } 655 }
672 return 1; 656#ifndef USE_DUMMY
673} 657#ifndef _WIN32
674#else 658#ifndef HAVE_IOKIT
675#warning No compiler support for constructor/destructor attributes, some features might not be available. 659 libusb_init(&libirecovery_context);
660#endif
676#endif 661#endif
662 collection_init(&listeners);
663 mutex_init(&listener_mutex);
664#endif
665 atexit(_irecv_deinit);
666}
677 667
678#ifdef HAVE_IOKIT 668#ifdef HAVE_IOKIT
679static int iokit_get_string_descriptor_ascii(irecv_client_t client, uint8_t desc_index, unsigned char * buffer, int size) 669static int iokit_get_string_descriptor_ascii(irecv_client_t client, uint8_t desc_index, unsigned char * buffer, int size)
@@ -1334,20 +1324,6 @@ static int check_context(irecv_client_t client)
1334} 1324}
1335#endif 1325#endif
1336 1326
1337void irecv_init(void)
1338{
1339#ifndef USE_DUMMY
1340 thread_once(&init_once, _irecv_init);
1341#endif
1342}
1343
1344void irecv_exit(void)
1345{
1346#ifndef USE_DUMMY
1347 thread_once(&deinit_once, _irecv_deinit);
1348#endif
1349}
1350
1351#ifndef USE_DUMMY 1327#ifndef USE_DUMMY
1352#ifdef HAVE_IOKIT 1328#ifdef HAVE_IOKIT
1353static int iokit_usb_control_transfer(irecv_client_t client, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, unsigned char *data, uint16_t w_length, unsigned int timeout) 1329static int iokit_usb_control_transfer(irecv_client_t client, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, unsigned char *data, uint16_t w_length, unsigned int timeout)