From 0be95c5c701a694f5f143df5b71f3beae32c2418 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Thu, 17 Oct 2019 23:19:06 +0100 Subject: [PATCH] Implement reading SDHCI registers from sysfs in Linux. --- device.c | 17 ++++++ dicmote.h | 9 +++ linux/device.c | 155 +++++++++++++++++++++++++++++++++++++++++++++++++ linux/linux.h | 9 +++ 4 files changed, 190 insertions(+) diff --git a/device.c b/device.c index 84c0341..afed2cc 100644 --- a/device.c +++ b/device.c @@ -35,4 +35,21 @@ int32_t GetDeviceType(const char* devicePath) #else return DICMOTE_DEVICE_TYPE_UNKNOWN; #endif +} + +int32_t GetSdhciRegisters(const char* devicePath, + char** csd, + char** cid, + char** ocr, + char** scr, + int* csd_len, + int* cid_len, + int* ocr_len, + int* scr_len) +{ +#if defined(__linux__) && !defined(__ANDROID__) + return linux_get_sdhci_registers(devicePath, csd, cid, ocr, scr, csd_len, cid_len, ocr_len, scr_len); +#else + return -1; +#endif } \ No newline at end of file diff --git a/dicmote.h b/dicmote.h index f094eaa..aa4b785 100644 --- a/dicmote.h +++ b/dicmote.h @@ -405,5 +405,14 @@ int32_t SendScsiCommand(int device_fd, uint32_t* sense_len); int hexchr2bin(const char hex, char* out); size_t hexs2bin(const char* hex, unsigned char** out); +int32_t GetSdhciRegisters(const char* devicePath, + char** csd, + char** cid, + char** ocr, + char** scr, + int* csd_len, + int* cid_len, + int* ocr_len, + int* scr_len); #endif diff --git a/linux/device.c b/linux/device.c index be3c961..8cc5d5f 100644 --- a/linux/device.c +++ b/linux/device.c @@ -117,4 +117,159 @@ int32_t linux_get_device_type(const char* devicePath) udev_unref(udev); return deviceType; +} + +int32_t linux_get_sdhci_registers(const char* devicePath, + char** csd, + char** cid, + char** ocr, + char** scr, + int* csd_len, + int* cid_len, + int* ocr_len, + int* scr_len) +{ + char* tmpString; + char* sysfsPath_csd; + char* sysfsPath_cid; + char* sysfsPath_scr; + char* sysfsPath_ocr; + size_t len; + FILE* file; + *csd = NULL; + *cid = NULL; + *ocr = NULL; + *scr = NULL; + *csd_len = 0; + *cid_len = 0; + *ocr_len = 0; + *scr_len = 0; + size_t n = 1026; + + if(strncmp(devicePath, "/dev/mmcblk", 11) != 0) return 0; + + len = strlen(devicePath) + 19; + sysfsPath_csd = malloc(len); + sysfsPath_cid = malloc(len); + sysfsPath_scr = malloc(len); + sysfsPath_ocr = malloc(len); + tmpString = malloc(1024); + + if(!sysfsPath_csd || !sysfsPath_cid || !sysfsPath_scr || !sysfsPath_ocr || !tmpString) + { + free(sysfsPath_csd); + free(sysfsPath_cid); + free(sysfsPath_scr); + free(sysfsPath_ocr); + free(tmpString); + return 0; + } + + memset(sysfsPath_csd, 0, len); + memset(sysfsPath_cid, 0, len); + memset(sysfsPath_scr, 0, len); + memset(sysfsPath_ocr, 0, len); + memset(tmpString, 0, strlen(devicePath) - 5); + + memcpy(tmpString, devicePath + 5, strlen(devicePath) - 5); + snprintf(sysfsPath_csd, len, "/sys/block/%s/device/csd", tmpString); + snprintf(sysfsPath_cid, len, "/sys/block/%s/device/cid", tmpString); + snprintf(sysfsPath_scr, len, "/sys/block/%s/device/scr", tmpString); + snprintf(sysfsPath_ocr, len, "/sys/block/%s/device/ocr", tmpString); + + if(access(sysfsPath_csd, R_OK) == 0) + { + file = fopen(sysfsPath_csd, "r"); + + if(file != NULL) + { + len = getline(&tmpString, &n, file); + if(len > 0) + { + *csd_len = hexs2bin(tmpString, (unsigned char**)csd); + + if(*csd_len <= 0) + { + *csd_len = 0; + *csd = NULL; + } + } + + fclose(file); + } + } + + if(access(sysfsPath_cid, R_OK) == 0) + { + file = fopen(sysfsPath_cid, "r"); + + if(file != NULL) + { + len = getline(&tmpString, &n, file); + if(len > 0) + { + *cid_len = hexs2bin(tmpString, (unsigned char**)cid); + + if(*cid_len <= 0) + { + *cid_len = 0; + *cid = NULL; + } + } + + fclose(file); + } + } + + if(access(sysfsPath_scr, R_OK) == 0) + { + file = fopen(sysfsPath_scr, "r"); + + if(file != NULL) + { + len = getline(&tmpString, &n, file); + if(len > 0) + { + *scr_len = hexs2bin(tmpString, (unsigned char**)scr); + + if(*scr_len <= 0) + { + *scr_len = 0; + *scr = NULL; + } + } + + fclose(file); + } + } + + if(access(sysfsPath_ocr, R_OK) == 0) + { + file = fopen(sysfsPath_ocr, "r"); + + if(file != NULL) + { + len = getline(&tmpString, &n, file); + if(len > 0) + { + *ocr_len = hexs2bin(tmpString, (unsigned char**)ocr); + + if(*ocr_len <= 0) + { + *ocr_len = 0; + *ocr = NULL; + } + } + + fclose(file); + } + } + + free(sysfsPath_csd); + free(sysfsPath_cid); + free(sysfsPath_scr); + free(sysfsPath_ocr); + free(tmpString); + + return csd_len != 0 || cid_len != 0 || scr_len != 0 || ocr_len != 0; } \ No newline at end of file diff --git a/linux/linux.h b/linux/linux.h index 6ac7f7e..d49ec4c 100644 --- a/linux/linux.h +++ b/linux/linux.h @@ -35,4 +35,13 @@ int32_t linux_send_scsi_command(int device_fd, uint32_t cdb_len, uint32_t* buf_len, uint32_t* sense_len); +int32_t linux_get_sdhci_registers(const char* devicePath, + char** csd, + char** cid, + char** ocr, + char** scr, + int* csd_len, + int* cid_len, + int* ocr_len, + int* scr_len); #endif // DICREMOTE_LINUX_H