From bc2a5ffc0b6a1e324e80905f389fafcebf14b28a Mon Sep 17 00:00:00 2001 From: Ernesto Castellotti Date: Fri, 8 Feb 2019 22:51:12 +0100 Subject: [PATCH] Initial standard implementation (read only) --- .gitignore | 114 ++++++++++++++++++++++++++++++++++ CMakeLists.txt | 35 +++++++++++ examples/example.c | 40 ++++++++++++ include/usbextreme.h | 119 +++++++++++++++++++++++++++++++++++ lib/usbextreme.c | 143 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 451 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 examples/example.c create mode 100644 include/usbextreme.h create mode 100644 lib/usbextreme.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b0c3f99 --- /dev/null +++ b/.gitignore @@ -0,0 +1,114 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps + +# C++ objects and libs +*.slo +*.lo +*.o +*.a +*.la +*.lai +*.so +*.dll +*.dylib + +# Qt-es +object_script.*.Release +object_script.*.Debug +*_plugin_import.cpp +/.qmake.cache +/.qmake.stash +*.pro.user +*.pro.user.* +*.qbs.user +*.qbs.user.* +*.moc +moc_*.cpp +moc_*.h +qrc_*.cpp +ui_*.h +*.qmlc +*.jsc +Makefile* +*build-* + +# Qt unit tests +target_wrapper.* + +# QtCreator +*.autosave + +# QtCreator Qml +*.qmlproject.user +*.qmlproject.user.* + +# QtCreator CMake +CMakeLists.txt.user* + +# QtCreator 4.8< compilation database +compile_commands.json + +# QtCreator local machine specific files for imported projects +*creator.user* diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..93f051a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 2.8.9) +INCLUDE(CheckIncludeFile) +project(Open-USB-Extreme) +include_directories(include) +# check headers +check_include_file("stdint.h" HAVE_STDINT) +if (HAVE_STDINT) + add_definitions(-DHAVE_STDINT) +endif() + +check_include_file("stddef.h" HAVE_STDDEF) +if (HAVE_STDDEF) + add_definitions(-DHAVE_STDDEF) +endif() + +file(GLOB SOURCES "lib/*.c") +file(GLOB HEADERS "include/*.h") +file(GLOB EXAMPLE_SOURCES "examples/*.c") +set (CMAKE_CXX_STANDARD 89) +#set(CMAKE_C_FLAGS "-Wall -pedantic -Wextra -Werror") +add_library(${PROJECT_NAME} SHARED ${SOURCES}) +add_executable(open-usbextreme-example ${EXAMPLE_SOURCES}) +target_link_libraries(open-usbextreme-example ${PROJECT_NAME}) + +install(TARGETS ${PROJECT_NAME} + LIBRARY DESTINATION lib +) + +INSTALL(FILES ${HEADERS} + DESTINATION include +) + +INSTALL(TARGETS open-usbextreme-example + RUNTIME DESTINATION bin +) diff --git a/examples/example.c b/examples/example.c new file mode 100644 index 0000000..66721f3 --- /dev/null +++ b/examples/example.c @@ -0,0 +1,40 @@ +#include +#include +#include + +int main(int argc, char *argv[]) { + if (argc < 2) { + printf("Usage: open-usbextreme-example \n"); + return 1; + } + + FILE *f = fopen(argv[1], "rb"); + fseek(f, 0, SEEK_END); + long fsize = ftell(f); + + if (fsize <= 0) { + return 1; + } + + unsigned long size = *(unsigned long*) &fsize; + fseek(f, 0, SEEK_SET); + + void *data = malloc(size + 1); + fread(data, size, 1, f); + fclose(f); + + usb_extreme_headers headers; + + if(oue_read_headers(&headers, data, size) <= 0) { + return 1; + } + + usb_extreme_filestat filestats[10]; + int nstats = oue_read(filestats, headers, 10); + + int i; + for(i = 0; i < nstats; i++) { + printf("Game name [%d]: %s\n", filestats[i].offset, filestats[i].name); + } + return 0; +} diff --git a/include/usbextreme.h b/include/usbextreme.h new file mode 100644 index 0000000..2c3025f --- /dev/null +++ b/include/usbextreme.h @@ -0,0 +1,119 @@ +#ifndef USBEXTREME_H +#define USBEXTREME_H + +#ifndef u8 + #if HAVE_STDINT + #include + typedef uint8_t u8; + typedef uint16_t u16; + #else + #error "u8 and u16 types have not been defined and missing stdint.h, please define your implementation of u8 and u16" + #endif +#endif + +#ifndef size_t + #if HAVE_STDDEF + #include + #else + #error "size_t type has not been defined and missing stddef.h, please define your implementation of size_t" + #endif +#endif + +#define USBEXTREME_NAME_LENGTH 32 +#define USBEXTREME_ID_LENGTH 15 +#define USBEXTREME_NAME_EXT_LENGTH 10 +#define USBEXTREME_MAGIC 0x08 + +typedef enum { + SCECdGDTFUNCFAIL = -1, + SCECdNODISC = 0x00, + SCECdDETCT, + SCECdDETCTCD, + SCECdDETCTDVDS, + SCECdDETCTDVDD, + SCECdUNKNOWN, + + SCECdPSCD = 0x10, + SCECdPSCDDA, + SCECdPS2CD, + SCECdPS2CDDA, + SCECdPS2DVD, + + SCECdCDDA = 0xFD, + SCECdDVDV, + SCECdIllegalMediaoffset +} SCECdvdMediaType; + +typedef enum { + USB_EXTREME_V0 = 0x00, + USB_EXTREME_V1 +} usb_extreme_versions; + +typedef struct __attribute__((__packed__)) { + u8 empty[6 + USBEXTREME_ID_LENGTH + USBEXTREME_NAME_LENGTH]; + u8 magic; + u8 empty2[10]; +} usb_extreme_base; + +typedef struct __attribute__((__packed__)) { + char name[USBEXTREME_NAME_LENGTH]; + char id[USBEXTREME_ID_LENGTH]; + u8 n_parts; + u8 type; + u8 empty[4]; + u8 magic; + u8 empty2[USBEXTREME_NAME_EXT_LENGTH]; +} usb_extreme_v0; + +typedef struct __attribute__((__packed__)) { + char name[USBEXTREME_NAME_LENGTH]; + char id[USBEXTREME_ID_LENGTH]; + u8 n_parts; + u8 type; + u16 size; + u8 video_mode; + u8 usb_extreme_version; + u8 magic; + char name_ext[USBEXTREME_NAME_EXT_LENGTH]; +} usb_extreme_v1; + +typedef struct { + int offset; + char name[USBEXTREME_NAME_LENGTH + USBEXTREME_NAME_EXT_LENGTH]; + SCECdvdMediaType type; + u16 size; + u8 video_mode; + usb_extreme_versions usb_extreme_version; +} usb_extreme_filestat; + +typedef struct { + void *first_header; + usb_extreme_base *headers; + int num_headers; + size_t headerslen; + usb_extreme_versions version; +} usb_extreme_headers; + +#define USBEXTREME_HEADER_SIZE sizeof(usb_extreme_base) + +/* Global headers functions */ +int is_oue(const void *headers, const size_t headerslen); +usb_extreme_versions get_version(u8 version); +int oue_point_headers(usb_extreme_base **headers, void *raw_headers, size_t headerslen); +int oue_num_headers(int *num_headers, const void *headers, size_t headerslen); +int oue_version(usb_extreme_versions *version, const void *headers, size_t headerslen); +int oue_read_headers(usb_extreme_headers *headers, void *raw_headers, const size_t headerslen); + +/* Read functions */ +int oue_read(usb_extreme_filestat *filestats, const usb_extreme_headers headers, const int filestats_nlen); + +/* implementation in development + * +int oue_add(usb_extreme_headers *headers, const usb_extreme_filestat filestat); + +int oue_edit(usb_extreme_headers *headers, const usb_extreme_filestat filestat); + +int oue_remove(usb_extreme_headers *headers, const usb_extreme_filestat filestat); +*/ + +#endif /* !USBEXTREME_H */ diff --git a/lib/usbextreme.c b/lib/usbextreme.c new file mode 100644 index 0000000..90e68fe --- /dev/null +++ b/lib/usbextreme.c @@ -0,0 +1,143 @@ +#include +#include + +int is_oue(const void *headers, const size_t headerslen) { + const usb_extreme_base *headers_oeu = headers; + int headers_nlen = (int) (headerslen / USBEXTREME_HEADER_SIZE); + int i; + + for(i = 0; i < headers_nlen; i++) { + const usb_extreme_base header = headers_oeu[i]; + + if (header.magic != USBEXTREME_MAGIC) { + return 0; + } + } + + return 1; +} + +usb_extreme_versions get_version(u8 version) { + switch (version) { + case 0: { + return USB_EXTREME_V0; + } + + case 1: { + return USB_EXTREME_V1; + } + + default: { + return USB_EXTREME_V1; + } + } +} + +int oue_point_headers(usb_extreme_base **headers, void *raw_headers, size_t headerslen) { + int headers_nlen; + + if (oue_num_headers(&headers_nlen, raw_headers, headerslen) <= 0) { + return -1; + } + + *headers = raw_headers; + return headers_nlen; +} + +int oue_num_headers(int *num_headers, const void *headers, size_t headerslen) { + int headers_nlen = (int) (headerslen / USBEXTREME_HEADER_SIZE); + + if (!is_oue(headers, headerslen)) { + return -1; + } + + *num_headers = headers_nlen; + return headers_nlen; +} + +int oue_version(usb_extreme_versions *version, const void *headers, size_t headerslen) { + const usb_extreme_v1 *headers_oeu = headers; + int headers_nlen = (int) (headerslen / USBEXTREME_HEADER_SIZE); + usb_extreme_versions first_version = USB_EXTREME_V0; + int i; + + if(!is_oue(headers, headerslen)) { + return -1; + } + + for(i = 0; i < headers_nlen; i++) { + const usb_extreme_v1 header = headers_oeu[i]; + + if (i == 0) { + first_version = get_version(header.usb_extreme_version); + } else { + if (first_version != get_version(header.usb_extreme_version)) { + *version = USB_EXTREME_V0; + return -2; + } + } + } + + *version = first_version; + return 1; +} + +int oue_read_headers(usb_extreme_headers *headers, void *raw_headers, const size_t headerslen) { + usb_extreme_base *headers_ptr; + usb_extreme_versions version; + int num_headers = (int) (headerslen / USBEXTREME_HEADER_SIZE); + usb_extreme_headers headers_temp = {NULL, NULL, 0, 0, 0}; + + if(oue_point_headers(&headers_ptr, raw_headers, headerslen) <= 0) { + return -1; + } + + if(oue_version(&version, raw_headers, headerslen) <= 0) { + return -1; + } + + headers_temp.first_header = raw_headers; + headers_temp.headers = headers_ptr; + headers_temp.num_headers = num_headers; + headers_temp.headerslen = headerslen; + headers_temp.version = version; + *headers = headers_temp; + return 1; +} + +int oue_read(usb_extreme_filestat *filestat, const usb_extreme_headers headers, const int filestats_nlen) { + int offset = filestats_nlen; + usb_extreme_v1 *headers_full = (usb_extreme_v1*) headers.headers; + usb_extreme_v1 header; + usb_extreme_filestat filestats_temp = {0, {'0'}, 0, 0, 0, 0}; + u16 size = 0; + u8 video_mode = 0; + u8 usb_extreme_version; + int i; + + for(i = 0; i < headers.num_headers; i++) { + if(offset == 0) { + return i; + } + + header = headers_full[i]; + strncpy(filestats_temp.name, header.name, USBEXTREME_NAME_LENGTH); + usb_extreme_version = header.usb_extreme_version; + + if(usb_extreme_version >= 1) { + size = header.size; + video_mode = header.video_mode; + strncat(filestats_temp.name, header.name_ext, USBEXTREME_NAME_EXT_LENGTH); + } + + filestats_temp.size = size; + filestats_temp.type = header.type; + filestats_temp.offset = i; + filestats_temp.video_mode = video_mode; + filestats_temp.usb_extreme_version = usb_extreme_version; + filestat[i] = filestats_temp; + offset -= 1; + } + + return i; +}