cdrom: add function to get list of available drives (initial linux implementation), show list in "Dump Drive" menu entry

This commit is contained in:
Brad Parker 2019-07-03 14:19:16 -04:00
parent 36c2fc847d
commit 9a52595ce3
7 changed files with 112 additions and 20 deletions

View File

@ -34,16 +34,19 @@
#include <retro_endianness.h>
#include <retro_miscellaneous.h>
#include <vfs/vfs_implementation.h>
#include <lists/string_list.h>
#include <lists/dir_list.h>
#include <string/stdstring.h>
#include <math.h>
#include <unistd.h>
#ifdef __linux__
#if defined(__linux__) && !defined(ANDROID)
#include <stropts.h>
#include <scsi/sg.h>
#endif
#ifdef _WIN32
#if defined(_WIN32) && !defined(_XBOX)
#include <winioctl.h>
#include <ntddscsi.h>
#endif
@ -86,7 +89,7 @@ void increment_msf(unsigned char *min, unsigned char *sec, unsigned char *frame)
*frame = (*frame < 74) ? (*frame + 1) : 0;
}
#ifdef _WIN32
#if defined(_WIN32) && !defined(_XBOX)
static int cdrom_send_command_win32(HANDLE fh, CDROM_CMD_Direction dir, void *buf, size_t len, unsigned char *cmd, size_t cmd_len, unsigned char *sense, size_t sense_len)
{
DWORD ioctl_bytes;
@ -134,7 +137,7 @@ static int cdrom_send_command_win32(HANDLE fh, CDROM_CMD_Direction dir, void *bu
}
#endif
#ifdef __linux__
#if defined(__linux__) && !defined(ANDROID)
static int cdrom_send_command_linux(int fd, CDROM_CMD_Direction dir, void *buf, size_t len, unsigned char *cmd, size_t cmd_len, unsigned char *sense, size_t sense_len)
{
sg_io_hdr_t sgio = {0};
@ -172,7 +175,7 @@ static int cdrom_send_command_linux(int fd, CDROM_CMD_Direction dir, void *buf,
}
#endif
static int cdrom_send_command(libretro_vfs_implementation_file *stream, CDROM_CMD_Direction dir, void *buf, size_t len, unsigned char *cmd, size_t cmd_len, size_t skip)
static int cdrom_send_command(const libretro_vfs_implementation_file *stream, CDROM_CMD_Direction dir, void *buf, size_t len, unsigned char *cmd, size_t cmd_len, size_t skip)
{
unsigned char *xfer_buf;
unsigned char sense[CDROM_MAX_SENSE_BYTES] = {0};
@ -204,10 +207,10 @@ static int cdrom_send_command(libretro_vfs_implementation_file *stream, CDROM_CM
#endif
retry:
#ifdef __linux__
#if defined(__linux__) && !defined(ANDROID)
if (!cdrom_send_command_linux(fileno(stream->fp), dir, xfer_buf, len + skip, cmd, cmd_len, sense, sizeof(sense)))
#else
#ifdef _WIN32
#if defined(_WIN32) && !defined(_XBOX)
if (!cdrom_send_command_win32(stream->fh, dir, xfer_buf, len + skip, cmd, cmd_len, sense, sizeof(sense)))
#endif
#endif
@ -554,7 +557,7 @@ int cdrom_write_cue(libretro_vfs_implementation_file *stream, char **out_buf, si
cdrom_read_track_info(stream, point, toc);
#ifdef _WIN32
#if defined(_WIN32) && !defined(_XBOX)
pos += snprintf(*out_buf + pos, len - pos, "FILE \"cdrom://%c://drive-track%02d.bin\" BINARY\n", cdrom_drive, point);
#else
pos += snprintf(*out_buf + pos, len - pos, "FILE \"cdrom://drive%c-track%02d.bin\" BINARY\n", cdrom_drive, point);
@ -585,7 +588,7 @@ int cdrom_write_cue(libretro_vfs_implementation_file *stream, char **out_buf, si
}
/* needs 32 bytes for full vendor, product and version */
int cdrom_get_inquiry(libretro_vfs_implementation_file *stream, char *model, int len)
int cdrom_get_inquiry(const libretro_vfs_implementation_file *stream, char *model, int len, bool *is_cdrom)
{
/* MMC Command: INQUIRY */
unsigned char cdb[] = {0x12, 0, 0, 0, 0xff, 0};
@ -613,6 +616,9 @@ int cdrom_get_inquiry(libretro_vfs_implementation_file *stream, char *model, int
memcpy(model + 26, buf + 32, 4);
}
if (is_cdrom && buf[0] == 5)
*is_cdrom = true;
return 0;
}
@ -747,3 +753,61 @@ int cdrom_close_tray(libretro_vfs_implementation_file *stream)
return 0;
}
struct string_list* cdrom_get_available_drives(void)
{
struct string_list *list = string_list_new();
int drive_index = 0;
#if defined(__linux__) && !defined(ANDROID)
struct string_list *dir_list = dir_list_new("/dev", NULL, false, false, false, false);
int i;
if (!dir_list)
return list;
for (i = 0; i < dir_list->size; i++)
{
if (strstr(dir_list->elems[i].data, "/dev/sg"))
{
char drive_model[32] = {0};
char drive_string[64] = {0};
union string_list_elem_attr attr = {0};
int dev_index = 0;
RFILE *file = filestream_open(dir_list->elems[i].data, RETRO_VFS_FILE_ACCESS_READ, 0);
const libretro_vfs_implementation_file *stream;
bool is_cdrom = false;
if (!file)
continue;
stream = filestream_get_vfs_handle(file);
cdrom_get_inquiry(stream, drive_model, sizeof(drive_model), &is_cdrom);
filestream_close(file);
if (!is_cdrom)
continue;
sscanf(dir_list->elems[i].data + strlen("/dev/sg"), "%d", &dev_index);
attr.i = dev_index;
snprintf(drive_string, sizeof(drive_string), "Drive %d: ", drive_index + 1);
if (!string_is_empty(drive_model))
strlcat(drive_string, drive_model, sizeof(drive_string));
else
strlcat(drive_string, "Unknown Drive", sizeof(drive_string));
string_list_append(list, drive_string, attr);
drive_index++;
}
}
string_list_free(dir_list);
#else
string_list_append(list, "Drive 1", attr);
#endif
return list;
}

View File

@ -40,6 +40,8 @@ typedef struct retro_vfs_file_handle libretro_vfs_implementation_file;
typedef struct libretro_vfs_implementation_file libretro_vfs_implementation_file;
#endif
struct string_list;
RETRO_BEGIN_DECLS
typedef struct
@ -73,7 +75,7 @@ int cdrom_read_subq(libretro_vfs_implementation_file *stream, unsigned char *buf
int cdrom_write_cue(libretro_vfs_implementation_file *stream, char **out_buf, size_t *out_len, char cdrom_drive, unsigned char *num_tracks, cdrom_toc_t *toc);
/* needs 32 bytes for full vendor, product and version */
int cdrom_get_inquiry(libretro_vfs_implementation_file *stream, char *model, int len);
int cdrom_get_inquiry(const libretro_vfs_implementation_file *stream, char *model, int len, bool *is_cdrom);
int cdrom_read(libretro_vfs_implementation_file *stream, unsigned char min, unsigned char sec, unsigned char frame, void *s, size_t len, size_t skip);
@ -87,6 +89,9 @@ int cdrom_open_tray(libretro_vfs_implementation_file *stream);
int cdrom_close_tray(libretro_vfs_implementation_file *stream);
/* must be freed by the caller */
struct string_list* cdrom_get_available_drives(void);
RETRO_END_DECLS
#endif

View File

@ -53,7 +53,7 @@ void string_list_free(struct string_list *list)
free(list->elems);
}
list->elems = NULL;
list->elems = NULL;
free(list);
}

View File

@ -410,7 +410,7 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
if (stream->scheme == VFS_SCHEME_CDROM)
{
retro_vfs_file_open_cdrom(stream, path, mode, hints);
#ifdef _WIN32
#if defined(_WIN32) && !defined(_XBOX)
if (!stream->fh)
goto error;
#else

View File

@ -26,7 +26,7 @@
#include <string/stdstring.h>
#include <cdrom/cdrom.h>
#ifdef _WIN32
#if defined(_WIN32) && !defined(_XBOX)
#include <windows.h>
#endif
@ -127,7 +127,7 @@ void retro_vfs_file_open_cdrom(
libretro_vfs_implementation_file *stream,
const char *path, unsigned mode, unsigned hints)
{
#ifdef __linux__
#if defined(__linux__) && !defined(ANDROID)
char model[32] = {0};
char cdrom_path[] = "/dev/sg1";
size_t path_len = strlen(path);
@ -176,7 +176,7 @@ void retro_vfs_file_open_cdrom(
if (stream->fp)
{
if (!cdrom_get_inquiry(stream, model, sizeof(model)))
if (!cdrom_get_inquiry(stream, model, sizeof(model), NULL))
{
#ifdef CDROM_DEBUG
printf("CDROM Model: %s\n", model);
@ -211,7 +211,7 @@ void retro_vfs_file_open_cdrom(
#endif
}
#endif
#ifdef _WIN32
#if defined(_WIN32) && !defined(_XBOX)
char model[32] = {0};
char cdrom_path[] = "\\\\.\\D:";
size_t path_len = strlen(path);
@ -313,7 +313,7 @@ int retro_vfs_file_close_cdrom(libretro_vfs_implementation_file *stream)
fflush(stdout);
#endif
#ifdef _WIN32
#if defined(_WIN32) && !defined(_XBOX)
if (!stream->fh || !CloseHandle(stream->fh))
return -1;
#else

View File

@ -60,6 +60,10 @@
#include "../frontend/drivers/platform_unix.h"
#endif
#ifdef HAVE_CDROM
#include <cdrom/cdrom.h>
#endif
#include "menu_cbs.h"
#include "menu_content.h"
#include "menu_driver.h"
@ -4890,23 +4894,40 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type,
switch (type)
{
#ifdef HAVE_CDROM
case DISPLAYLIST_DUMP_DISC:
{
int i;
struct string_list *list = cdrom_get_available_drives();
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
count = 0;
/* TODO/FIXME - remove 'count = 0;' and implement disk list */
if (count == 0)
for (i = 0; list && i < list->size; i++)
{
menu_entries_append_enum(info->list,
list->elems[i].data,
"",
0,
MENU_SET_CDROM_LIST,
0, i);
}
if (list->size == 0)
menu_entries_append_enum(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY),
msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY),
MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY,
FILE_TYPE_NONE, 0, 0);
string_list_free(list);
info->need_push = true;
info->need_refresh = true;
info->need_clear = true;
break;
}
#endif
#if defined(HAVE_LAKKA_SWITCH) || defined(HAVE_LIBNX)
case DISPLAYLIST_SWITCH_CPU_PROFILE:
{

View File

@ -194,6 +194,8 @@ enum menu_settings_type
MENU_SET_SWITCH_CPU_PROFILE,
#endif
MENU_SET_CDROM_LIST,
MENU_SETTINGS_LAST
};