2018-05-03 13:47:57 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// SCSI Target Emulator RaSCSI (*^..^*)
|
|
|
|
// for Raspberry Pi
|
|
|
|
//
|
|
|
|
// Powered by XM6 TypeG Technology.
|
2020-07-04 14:57:44 +00:00
|
|
|
// Copyright (C) 2016-2020 GIMONS
|
2020-07-05 16:47:17 +00:00
|
|
|
// [ Send Control Command ]
|
2018-05-03 13:47:57 +00:00
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#include "os.h"
|
2021-01-25 16:07:30 +00:00
|
|
|
#include "rascsi_version.h"
|
2018-05-03 13:47:57 +00:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
2020-07-05 16:47:17 +00:00
|
|
|
// Send Command
|
2018-05-03 13:47:57 +00:00
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
BOOL SendCommand(char *buf)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
struct sockaddr_in server;
|
|
|
|
FILE *fp;
|
|
|
|
|
2020-07-05 16:47:17 +00:00
|
|
|
// Create a socket to send the command
|
2018-05-03 13:47:57 +00:00
|
|
|
fd = socket(PF_INET, SOCK_STREAM, 0);
|
|
|
|
memset(&server, 0, sizeof(server));
|
|
|
|
server.sin_family = PF_INET;
|
|
|
|
server.sin_port = htons(6868);
|
|
|
|
server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
|
|
|
|
2020-07-05 16:47:17 +00:00
|
|
|
// Connect
|
2018-05-03 13:47:57 +00:00
|
|
|
if (connect(fd, (struct sockaddr *)&server,
|
|
|
|
sizeof(struct sockaddr_in)) < 0) {
|
|
|
|
fprintf(stderr, "Error : Can't connect to rascsi process\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2020-07-05 16:47:17 +00:00
|
|
|
// Send the command
|
2018-05-03 13:47:57 +00:00
|
|
|
fp = fdopen(fd, "r+");
|
|
|
|
setvbuf(fp, NULL, _IONBF, 0);
|
2020-08-07 19:25:05 +00:00
|
|
|
fputs(buf, fp);
|
2018-05-03 13:47:57 +00:00
|
|
|
|
2020-07-05 16:47:17 +00:00
|
|
|
// Receive the message
|
2018-05-03 13:47:57 +00:00
|
|
|
while (1) {
|
|
|
|
if (fgets((char *)buf, BUFSIZ, fp) == NULL) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
printf("%s", buf);
|
|
|
|
}
|
|
|
|
|
2020-07-05 16:47:17 +00:00
|
|
|
// Close the socket when we're done
|
2018-05-03 13:47:57 +00:00
|
|
|
fclose(fp);
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
2020-07-05 16:47:17 +00:00
|
|
|
// Main processing
|
2018-05-03 13:47:57 +00:00
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
int main(int argc, char* argv[])
|
|
|
|
{
|
|
|
|
int opt;
|
|
|
|
int id;
|
2020-07-04 14:57:44 +00:00
|
|
|
int un;
|
2018-05-03 13:47:57 +00:00
|
|
|
int cmd;
|
|
|
|
int type;
|
|
|
|
char *file;
|
|
|
|
BOOL list;
|
|
|
|
int len;
|
|
|
|
char *ext;
|
|
|
|
char buf[BUFSIZ];
|
|
|
|
|
|
|
|
id = -1;
|
2020-07-04 14:57:44 +00:00
|
|
|
un = 0;
|
2018-05-03 13:47:57 +00:00
|
|
|
cmd = -1;
|
|
|
|
type = -1;
|
|
|
|
file = NULL;
|
|
|
|
list = FALSE;
|
|
|
|
|
2020-07-05 16:47:17 +00:00
|
|
|
// Display help
|
2018-05-03 13:47:57 +00:00
|
|
|
if (argc < 2) {
|
|
|
|
fprintf(stderr, "SCSI Target Emulator RaSCSI Controller\n");
|
2021-01-25 16:07:30 +00:00
|
|
|
fprintf(stderr, "version %s (%s, %s)\n",
|
|
|
|
rascsi_get_version_string(),
|
|
|
|
__DATE__,
|
|
|
|
__TIME__);
|
2018-05-03 13:47:57 +00:00
|
|
|
fprintf(stderr,
|
2020-07-04 14:57:44 +00:00
|
|
|
"Usage: %s -i ID [-u UNIT] [-c CMD] [-t TYPE] [-f FILE]\n",
|
2018-05-03 13:47:57 +00:00
|
|
|
argv[0]);
|
|
|
|
fprintf(stderr, " where ID := {0|1|2|3|4|5|6|7}\n");
|
2020-07-04 14:57:44 +00:00
|
|
|
fprintf(stderr, " UNIT := {0|1} default setting is 0.\n");
|
|
|
|
fprintf(stderr, " CMD := {attach|detach|insert|eject|protect}\n");
|
2021-02-03 01:55:38 +00:00
|
|
|
fprintf(stderr, " TYPE := {hd|mo|cd|bridge}\n");
|
2018-05-03 13:47:57 +00:00
|
|
|
fprintf(stderr, " FILE := image file path\n");
|
|
|
|
fprintf(stderr, " CMD is 'attach' or 'insert' and FILE parameter is required.\n");
|
|
|
|
fprintf(stderr, "Usage: %s -l\n", argv[0]);
|
|
|
|
fprintf(stderr, " Print device list.\n");
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
2020-07-05 16:47:17 +00:00
|
|
|
// Parse the arguments
|
2018-05-03 13:47:57 +00:00
|
|
|
opterr = 0;
|
2020-07-04 14:57:44 +00:00
|
|
|
while ((opt = getopt(argc, argv, "i:u:c:t:f:l")) != -1) {
|
2018-05-03 13:47:57 +00:00
|
|
|
switch (opt) {
|
|
|
|
case 'i':
|
|
|
|
id = optarg[0] - '0';
|
|
|
|
break;
|
|
|
|
|
2020-07-04 14:57:44 +00:00
|
|
|
case 'u':
|
|
|
|
un = optarg[0] - '0';
|
|
|
|
break;
|
|
|
|
|
2018-05-03 13:47:57 +00:00
|
|
|
case 'c':
|
|
|
|
switch (optarg[0]) {
|
|
|
|
case 'a': // ATTACH
|
|
|
|
case 'A':
|
|
|
|
cmd = 0;
|
|
|
|
break;
|
|
|
|
case 'd': // DETACH
|
|
|
|
case 'D':
|
|
|
|
cmd = 1;
|
|
|
|
break;
|
|
|
|
case 'i': // INSERT
|
|
|
|
case 'I':
|
|
|
|
cmd = 2;
|
|
|
|
break;
|
|
|
|
case 'e': // EJECT
|
|
|
|
case 'E':
|
|
|
|
cmd = 3;
|
|
|
|
break;
|
|
|
|
case 'p': // PROTECT
|
|
|
|
case 'P':
|
|
|
|
cmd = 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 't':
|
|
|
|
switch (optarg[0]) {
|
|
|
|
case 's': // HD(SASI)
|
|
|
|
case 'S':
|
|
|
|
case 'h': // HD(SCSI)
|
|
|
|
case 'H':
|
2021-02-03 01:55:38 +00:00
|
|
|
type = 0;
|
2018-05-03 13:47:57 +00:00
|
|
|
break;
|
|
|
|
case 'm': // MO
|
|
|
|
case 'M':
|
2021-02-03 01:55:38 +00:00
|
|
|
type = 2;
|
2018-05-03 13:47:57 +00:00
|
|
|
break;
|
|
|
|
case 'c': // CD
|
|
|
|
case 'C':
|
2021-02-03 01:55:38 +00:00
|
|
|
type = 3;
|
2018-05-03 13:47:57 +00:00
|
|
|
break;
|
|
|
|
case 'b': // BRIDGE
|
|
|
|
case 'B':
|
2021-02-03 01:55:38 +00:00
|
|
|
type = 4;
|
2018-05-03 13:47:57 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'f':
|
|
|
|
file = optarg;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'l':
|
|
|
|
list = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-05 16:47:17 +00:00
|
|
|
// List display only
|
2018-05-03 13:47:57 +00:00
|
|
|
if (id < 0 && cmd < 0 && type < 0 && file == NULL && list) {
|
|
|
|
sprintf(buf, "list\n");
|
|
|
|
SendCommand(buf);
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
2020-07-05 16:47:17 +00:00
|
|
|
// Check the ID number
|
2018-05-03 13:47:57 +00:00
|
|
|
if (id < 0 || id > 7) {
|
2021-02-03 01:55:38 +00:00
|
|
|
fprintf(stderr, "Error : Invalid ID\n");
|
2018-05-03 13:47:57 +00:00
|
|
|
exit(EINVAL);
|
|
|
|
}
|
|
|
|
|
2020-07-05 16:47:17 +00:00
|
|
|
// Check the unit number
|
2020-07-04 14:57:44 +00:00
|
|
|
if (un < 0 || un > 1) {
|
2021-02-03 01:55:38 +00:00
|
|
|
fprintf(stderr, "Error : Invalid UNIT\n");
|
2020-07-04 14:57:44 +00:00
|
|
|
exit(EINVAL);
|
|
|
|
}
|
|
|
|
|
2020-07-05 16:47:17 +00:00
|
|
|
// Command check
|
2018-05-03 13:47:57 +00:00
|
|
|
if (cmd < 0) {
|
2020-07-05 16:47:17 +00:00
|
|
|
cmd = 0; // Default command is ATTATCH
|
2018-05-03 13:47:57 +00:00
|
|
|
}
|
|
|
|
|
2020-07-05 16:47:17 +00:00
|
|
|
// Type Check
|
2018-05-03 13:47:57 +00:00
|
|
|
if (cmd == 0 && type < 0) {
|
|
|
|
|
2020-07-05 16:47:17 +00:00
|
|
|
// Try to determine the file type from the extension
|
2018-05-03 13:47:57 +00:00
|
|
|
len = file ? strlen(file) : 0;
|
|
|
|
if (len > 4 && file[len - 4] == '.') {
|
|
|
|
ext = &file[len - 3];
|
|
|
|
if (xstrcasecmp(ext, "hdf") == 0 ||
|
|
|
|
xstrcasecmp(ext, "hds") == 0 ||
|
|
|
|
xstrcasecmp(ext, "hdn") == 0 ||
|
|
|
|
xstrcasecmp(ext, "hdi") == 0 ||
|
|
|
|
xstrcasecmp(ext, "nhd") == 0 ||
|
|
|
|
xstrcasecmp(ext, "hda") == 0) {
|
|
|
|
// HD(SASI/SCSI)
|
|
|
|
type = 0;
|
|
|
|
} else if (xstrcasecmp(ext, "mos") == 0) {
|
|
|
|
// MO
|
|
|
|
type = 2;
|
|
|
|
} else if (xstrcasecmp(ext, "iso") == 0) {
|
|
|
|
// CD
|
|
|
|
type = 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type < 0) {
|
|
|
|
fprintf(stderr, "Error : Invalid type\n");
|
|
|
|
exit(EINVAL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-05 16:47:17 +00:00
|
|
|
// File check (command is ATTACH and type is HD)
|
2018-05-03 13:47:57 +00:00
|
|
|
if (cmd == 0 && type >= 0 && type <= 1) {
|
|
|
|
if (!file) {
|
|
|
|
fprintf(stderr, "Error : Invalid file path\n");
|
|
|
|
exit(EINVAL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-05 16:47:17 +00:00
|
|
|
// File check (command is INSERT)
|
2018-05-03 13:47:57 +00:00
|
|
|
if (cmd == 2) {
|
|
|
|
if (!file) {
|
|
|
|
fprintf(stderr, "Error : Invalid file path\n");
|
|
|
|
exit(EINVAL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-05 16:47:17 +00:00
|
|
|
// Set unnecessary type to 0
|
2018-05-03 13:47:57 +00:00
|
|
|
if (type < 0) {
|
|
|
|
type = 0;
|
|
|
|
}
|
|
|
|
|
2020-07-05 16:47:17 +00:00
|
|
|
// Generate the command and send it
|
2020-07-04 14:57:44 +00:00
|
|
|
sprintf(buf, "%d %d %d %d %s\n", id, un, cmd, type, file ? file : "-");
|
2018-05-03 13:47:57 +00:00
|
|
|
if (!SendCommand(buf)) {
|
|
|
|
exit(ENOTCONN);
|
|
|
|
}
|
|
|
|
|
2020-07-05 16:47:17 +00:00
|
|
|
// Display the list
|
2018-05-03 13:47:57 +00:00
|
|
|
if (list) {
|
|
|
|
sprintf(buf, "list\n");
|
|
|
|
SendCommand(buf);
|
|
|
|
}
|
|
|
|
|
2020-07-05 16:47:17 +00:00
|
|
|
// All done!
|
2018-05-03 13:47:57 +00:00
|
|
|
exit(0);
|
|
|
|
}
|