diff options
Diffstat (limited to 'src/libirecovery.c')
| -rw-r--r-- | src/libirecovery.c | 108 |
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 | |||
| 74 | struct irecv_client_private { | 101 | struct 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 | ||
| 606 | static 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 | |||
| 624 | static void _irecv_deinit(void) | 633 | static 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 | ||
| 640 | static thread_once_t init_once = THREAD_ONCE_INIT; | 649 | INITIALIZER(_irecv_init) |
| 641 | static 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 | ||
| 650 | static 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); | |
| 655 | static 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) | ||
| 660 | BOOL 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 |
| 679 | static int iokit_get_string_descriptor_ascii(irecv_client_t client, uint8_t desc_index, unsigned char * buffer, int size) | 669 | static 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 | ||
| 1337 | void irecv_init(void) | ||
| 1338 | { | ||
| 1339 | #ifndef USE_DUMMY | ||
| 1340 | thread_once(&init_once, _irecv_init); | ||
| 1341 | #endif | ||
| 1342 | } | ||
| 1343 | |||
| 1344 | void 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 |
| 1353 | static 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) | 1329 | static 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) |
