46 static const unsigned char prog_tdchange[] = {
47 #include "tdchange.inc"
56 printf(
"cbmctrl version " OPENCBM_VERSION
", built on " __DATE__
" at " __TIME__
"\n");
61 static int check_if_parameters_ok(
OPTIONS *
const options)
63 if (options->
argc != 0)
65 fprintf(stderr,
"Extra parameter, aborting...\n");
71 static int get_argument_char(
OPTIONS *
const options,
unsigned char *where)
73 if (options->
argc > 0)
75 *where = arch_atoc(options->
argv[0]);
82 fprintf(stderr,
"Not enough parameters, aborting!\n");
88 get_argument_string(
OPTIONS *
const options,
char *where[],
unsigned int *len)
90 if (options->
argc > 0)
93 *where = options->
argv[0];
96 *len = strlen(*where);
104 fprintf(stderr,
"Not enough parameters, aborting!\n");
109 static int get_argument_file_for_write(
OPTIONS *
const options, FILE **f)
111 char *filename = NULL;
115 if (options->
argc > 0)
117 get_argument_string(options, &filename, NULL);
119 if (filename && strcmp(filename,
"-") == 0)
123 if (check_if_parameters_ok(options))
130 *f = fopen(filename,
"wb");
136 *f = arch_fdopen(arch_fileno(stdout),
"wb");
141 arch_setbinmode(arch_fileno(stdout));
146 arch_error(0, arch_get_errno(),
"could not open output file: %s",
147 (filename != 0) ? filename :
"stdout");
155 static int get_argument_file_for_read(
OPTIONS *
const options, FILE **f,
char **fn)
157 char *filename = NULL;
161 if (options->
argc > 0)
163 get_argument_string(options, &filename, NULL);
165 if (filename && strcmp(filename,
"-") == 0)
169 if (check_if_parameters_ok(options))
174 filename =
"(stdin)";
179 arch_setbinmode(arch_fileno(stdin));
185 *f = fopen(filename,
"rb");
188 arch_error(0, arch_get_errno(),
"could not open %s", filename);
193 arch_error(0, arch_get_errno(),
"could not stat %s", filename);
205 process_individual_option(
OPTIONS *
const options,
const char short_options[],
struct option long_options[])
207 static int firstcall = 1;
221 option = getopt_long(options->
argc, options->
argv, short_options, long_options, NULL);
228 options->
argc -= optind;
229 options->
argv += optind;
237 skip_options(
OPTIONS *
const options)
239 if (process_individual_option(options,
"+", NULL) != EOF)
245 static int hex2val(
const char ch)
247 if (ch>=
'0' && ch<=
'9')
250 if (ch>=
'A' && ch<=
'F')
251 return ch -
'A' + 10;
253 if (ch>=
'a' && ch<=
'f')
254 return ch -
'a' + 10;
257 (ch==0) ?
"Not enough digits for hex value given\n"
258 :
"Unknown hex character '%c'.\n", ch);
263 process_specific_byte_parameter(
char *
string,
int stringlen, PETSCII_RAW petsciiraw)
266 char *pread = string;
267 char *pwrite = pread;
279 int val = hex2val(ch);
285 val2 = hex2val(*pread++);
290 ch = (val << 4) | val2;
298 if (petsciiraw == PA_PETSCII)
312 string_concat(
const char *string1,
int len1,
const char *string2,
int len2)
316 if ((string1 != NULL) && (len1 == 0))
317 len1 = strlen(string1);
319 if ((string2 != NULL) && (len2 == 0))
320 len2 = strlen(string2);
322 buffer = calloc(1, len1 + len2 + 1);
327 memcpy(buffer, string1, len1);
330 memcpy(buffer + len1, string2, len2);
337 get_extended_argument_string(
int extended,
339 char *
string[],
unsigned int *stringlen)
342 char *commandline = NULL;
343 char *extended_commandline = NULL;
344 unsigned int commandline_len = 0;
345 unsigned int extended_commandline_len = 0;
347 rv = get_argument_string(options, &commandline, &commandline_len);
354 int n = process_specific_byte_parameter(commandline, commandline_len, options->
petsciiraw);
373 if (options->
argc > 0)
382 extended_commandline = malloc(options->
argc + 1);
384 if (extended_commandline == NULL)
386 fprintf(stderr,
"Not enough memory for all parameters, aborting...\n");
392 p = extended_commandline;
394 while (--options->
argc >= 0)
399 c = strtol(options->
argv[0], &tail, 0);
401 if(c < 0 || c > 0xff || *tail)
403 arch_error(0, 0,
"invalid byte: %s", options->
argv[0]);
407 extended_commandline_len++;
421 *
string = string_concat(commandline, commandline_len, extended_commandline, extended_commandline_len);
422 *stringlen = commandline_len + extended_commandline_len;
424 if (extended_commandline)
425 free(extended_commandline);
427 if (check_if_parameters_ok(options))
438 int rv = skip_options(options);
440 rv = rv || check_if_parameters_ok(options);
453 int rv = skip_options(options);
455 rv = rv || check_if_parameters_ok(options);
468 int rv = skip_options(options);
470 rv = rv || check_if_parameters_ok(options);
483 int rv = skip_options(options);
485 rv = rv || check_if_parameters_ok(options);
498 int rv = skip_options(options);
500 rv = rv || check_if_parameters_ok(options);
515 unsigned char secondary;
517 rv = skip_options(options);
519 rv = rv || get_argument_char(options, &unit);
520 rv = rv || get_argument_char(options, &secondary);
522 if (rv || check_if_parameters_ok(options))
535 unsigned char secondary;
537 rv = skip_options(options);
539 rv = rv || get_argument_char(options, &unit);
540 rv = rv || get_argument_char(options, &secondary);
542 if (rv || check_if_parameters_ok(options))
545 return cbm_talk(fd, unit, secondary);
553 int rv = skip_options(options);
555 rv = rv || check_if_parameters_ok(options);
568 int rv = skip_options(options);
570 rv = rv || check_if_parameters_ok(options);
585 unsigned char secondary;
587 unsigned int filenamelen = 0;
591 static const char short_options[] =
"+e";
592 static struct option long_options[] =
594 {
"extended", no_argument, NULL,
'e'},
595 {NULL, no_argument, NULL, 0 }
600 while ((c = process_individual_option(options, short_options, long_options)) != EOF)
613 rv = get_argument_char(options, &unit);
614 rv = rv || get_argument_char(options, &secondary);
615 rv = rv || get_extended_argument_string(extended, options, &filename, &filenamelen);
620 rv =
cbm_open(fd, unit, secondary, filename, filenamelen);
634 unsigned char secondary;
636 rv = skip_options(options);
638 rv = rv || get_argument_char(options, &unit);
639 rv = rv || get_argument_char(options, &secondary);
641 if (rv || check_if_parameters_ok(options))
653 unsigned char buf[2048];
656 if (skip_options(options))
659 if (get_argument_file_for_write(options, &f))
670 for (i=0; i < size; i++)
675 if(size != (
int) fwrite(buf, 1, size, f))
696 unsigned char buf[2048];
699 if (skip_options(options))
702 if (get_argument_file_for_read(options, &f, &fn))
706 size = fread(buf, 1,
sizeof(buf), f);
708 if(size == 0 && feof(f))
710 arch_error(0, 0,
"no data: %s", fn);
711 if(f != stdin) fclose(f);
722 for (i=0; i < size; i++)
734 size = fread(buf, 1,
sizeof(buf), f);
735 if(size == 0 && feof(f))
738 if(f != stdin) fclose(f);
746 arch_error(0, 0,
"could not read %s", fn);
750 if(f != stdin) fclose(f);
761 unsigned int commandlinelen = 0;
766 static const char short_options[] =
"+e";
767 static struct option long_options[] =
769 {
"extended", no_argument, NULL,
'e'},
770 {NULL, no_argument, NULL, 0 }
775 while ((c = process_individual_option(options, short_options, long_options)) != EOF)
788 rv = get_extended_argument_string(extended, options, &commandline, &commandlinelen);
797 for (i=0; i < commandlinelen; i++)
803 if(rv < 0 || commandlinelen != (
unsigned int) rv)
812 if (commandline != NULL)
829 rv = skip_options(options);
831 rv = rv || get_argument_char(options, &unit);
833 if (rv || check_if_parameters_ok(options))
843 return (rv == 99) ? 1 : 0;
855 unsigned int commandlinelen = 0;
859 static const char short_options[] =
"+e";
860 static struct option long_options[] =
862 {
"extended", no_argument, NULL,
'e'},
863 {NULL, no_argument, NULL, 0 }
868 while ((c = process_individual_option(options, short_options, long_options)) != EOF)
881 rv = get_argument_char(options, &unit);
882 rv = rv || get_extended_argument_string(extended, options, &commandline, &commandlinelen);
890 if (commandlinelen > 0)
902 if (commandline != NULL)
916 unsigned char command[] = {
'$',
'0' };
920 rv = skip_options(options);
922 rv = rv || get_argument_char(options, &unit);
924 if (options->
argc > 0)
926 rv = rv || get_argument_char(options, command+1);
929 if (rv || check_if_parameters_ok(options))
932 rv =
cbm_open(fd, unit, 0, command,
sizeof(command));
944 printf(
"%u ", (
unsigned char)buf[0] | (
unsigned char)buf[1] << 8 );
974 static void show_monkey(
unsigned int c)
982 const static char monkey[]={
",oO*^!:;"};
984 c %=
sizeof(monkey) - 1;
985 fprintf(stderr, (c != 0) ?
"\b%c" :
"\b.%c" , monkey[c]);
996 int addr, count, rv = 0;
997 char *tail, buf[256];
1002 if (skip_options(options))
1007 if (get_argument_char(options, &unit))
1013 if (get_argument_string(options, &tmpstring, NULL))
1016 addr = strtol(tmpstring, &tail, 0);
1017 if(addr < 0 || addr > 0xffff || *tail)
1019 arch_error(0, 0,
"invalid address: %s", tmpstring);
1026 if (get_argument_string(options, &tmpstring, NULL))
1029 count = strtol(tmpstring, &tail, 0);
1030 if((count + addr) > 0x10000 || *tail)
1032 arch_error(0, arch_get_errno(),
"invalid byte count %s", tmpstring);
1039 if (get_argument_file_for_write(options, &f))
1046 show_monkey(count /
sizeof(buf));
1048 c = (count >
sizeof(buf)) ?
sizeof(buf) : count;
1050 if (c + (addr & 0xFF) > 0x100) {
1051 c = 0x100 - (addr & 0xFF);
1054 if(c != cbm_download(fd, unit, addr, buf, c))
1057 fprintf(stderr,
"A transfer error occurred!\n");
1068 for (i = 0; i < c; i++)
1072 fwrite(buf, 1, c, f);
1093 unsigned char addr_buf[2];
1094 unsigned int buflen = 65537;
1098 if (skip_options(options))
1103 if (get_argument_char(options, &unit))
1109 if (get_argument_string(options, &tmpstring, NULL))
1112 addr = strtol(tmpstring, &tail, 0);
1113 if(addr < -1 || addr > 0xffff || *tail)
1115 arch_error(0, 0,
"invalid address: %s", tmpstring);
1119 if (get_argument_file_for_read(options, &f, &fn))
1125 buf = malloc(buflen);
1128 fprintf(stderr,
"Not enough memory for buffer.\n");
1135 if(fread(addr_buf, 2, 1, f) != 1)
1137 arch_error(0, arch_get_errno(),
"could not read %s", fn);
1138 if(f != stdin) fclose(f);
1145 addr = addr_buf[0] | (addr_buf[1] << 8);
1148 size = fread(buf, 1, buflen, f);
1151 arch_error(0, 0,
"could not read %s", fn);
1152 if(f != stdin) fclose(f);
1156 else if(size == 0 && feof(f))
1158 arch_error(0, 0,
"no data: %s", fn);
1159 if(f != stdin) fclose(f);
1164 if(addr + size > 0x10000)
1166 arch_error(0, 0,
"program too big: %s", fn);
1167 if (f != stdin) fclose(f);
1172 if(f != stdin) fclose(f);
1181 for (i = 0; i < size; i++)
1185 rv = (
cbm_upload(fd, unit, addr, buf, size) == (int)size) ? 0 : 1;
1188 fprintf(stderr,
"A transfer error occurred!\n");
1201 unsigned int num_devices;
1202 unsigned char device;
1203 const char *type_str;
1205 if (skip_options(options))
1208 if (check_if_parameters_ok(options))
1213 for( device = 8; device < 16; device++ )
1216 if(
cbm_identify( fd, device, &device_type, &type_str ) == 0 )
1219 const char *cable_str =
"(cannot determine cable type)";
1232 cable_str =
"(XP1541)";
1240 printf(
"%2d: %s %s\n", device, type_str, cable_str );
1244 return num_devices > 0 ? 0 : 1;
1255 rv = skip_options(options);
1257 rv = rv || get_argument_char(options, &unit);
1259 if (rv || check_if_parameters_ok(options))
1278 fprintf(stderr,
"Drive %u is a 1581, which is not supported (yet).\n", unit);
1297 if (
cbm_upload(fd, unit, 0x500, prog_tdchange,
sizeof(prog_tdchange)) !=
sizeof(prog_tdchange))
1344 PETSCII_RAW petsciiraw;
1347 char *shorthelp_text;
1351 static struct prog prog_table[] =
1353 {1,
"lock" , PA_UNSPEC, do_lock ,
"",
1354 "Lock the parallel port for the use by cbm4win/cbm4linux.",
1355 "This command locks the parallel port for the use by cbm4win/cbm4linux,\n"
1356 "so that sequences of e.g. talk/read/untalk commands are not broken by\n"
1357 "concurrent processes wanting to access the parallel port." },
1359 {1,
"unlock" , PA_UNSPEC, do_unlock ,
"",
1360 "Unlock the parallel port for the use by cbm4win/cbm4linux.",
1361 "This command unlocks the parallel port again so that other processes\n"
1362 "get a chance to access the parallel port." },
1364 {1,
"listen" , PA_UNSPEC, do_listen ,
"<device> <secadr>",
1365 "perform a listen on the IEC bus",
1366 "Output a listen command on the IEC bus.\n"
1367 "<device> is the device number,\n"
1368 "<secadr> the secondary address to use for this.\n\n"
1369 "This has to be undone later with an unlisten command." },
1371 {1,
"talk" , PA_UNSPEC, do_talk ,
"<device> <secadr>",
1372 "perform a talk on the IEC bus",
1373 "Output a talk command on the IEC bus.\n"
1374 "<device> is the device number,\n"
1375 "<secadr> the secondary address to use for this.\n\n"
1376 "This has to be undone later with an untalk command." },
1378 {1,
"unlisten", PA_UNSPEC, do_unlisten,
"",
1379 "perform an unlisten on the IEC bus",
1380 "Undo one or more previous listen commands.\n"
1381 "This affects all drives." },
1383 {1,
"untalk" , PA_UNSPEC, do_untalk ,
"",
1384 "perform an untalk on the IEC bus",
1385 "Undo one or more previous talk commands.\n"
1386 "This affects all drives." },
1388 {1,
"open" , PA_RAW, do_open ,
"[-e|--extended] <device> <secadr> <filename> [<file1>...<fileN>]",
1389 "perform an open on the IEC bus",
1390 "Output an open command on the IEC bus.\n"
1391 "<device> is the device number,\n"
1392 "<secadr> the secondary address to use for this.\n"
1393 "<filename> is the name of the file to be opened.\n"
1394 " It must be given, but may be empty by specifying it as \"\".\n"
1395 "<file1..N> are additional bytes to append to the filename <filename>.\n"
1396 " Single bytes can be given as decimal, octal (0 prefix) or\n"
1397 " sedecimal (0x prefix).\n\n"
1398 "If the option -e or --extended is given, an extended format is used:\n"
1399 " You can specify extra characters by given their ASCII value in hex,\n"
1400 " prepended with '%', that is: '%20' => SPACE, '%41' => 'A', '%35' => '5',\n"
1401 " and-so-on. A '%' is given by giving its hex ASCII: '%25' => '%'.\n\n"
1402 "Opening a file has to be undone later with a close command.\n\n"
1404 "- You cannot do an open without a filename.\n"
1405 " Although a CBM machine (i.e., a C64) allows this, it is an internal operation\n"
1406 " to the computer only.\n"
1407 "- If used with the global --petscii option, this action is equivalent\n"
1408 " to the deprecated command-line 'cbmctrl popen'.\n"
1409 "- If using both --petscii and --extended option, the bytes given via the\n"
1410 " '%' meta-character or as <file1> .. <fileN> are *not* converted to petscii." },
1412 {1,
"popen" , PA_PETSCII, do_open ,
"<device> <secadr> <filename>",
1413 "deprecated; use 'cbmctrl --petscii open' instead!",
1414 "This command is deprecated; use 'cbmctrl -p open' instead!" },
1416 {1,
"close" , PA_UNSPEC, do_close ,
"<device> <secadr>",
1417 "perform a close on the IEC bus",
1418 "Undo a previous open command." },
1420 {1,
"read" , PA_RAW, do_read ,
"[<file>]",
1421 "read raw data from the IEC bus",
1422 "With this command, you can read raw data from the IEC bus.\n"
1423 "<file> (optional) file name of a file to write the contents to.\n"
1424 " If this name is not given or it is a dash ('-'), the\n"
1425 " contents will be written to stdout, normally the console." },
1427 {1,
"write" , PA_RAW, do_write ,
"[<file>]",
1428 "write raw data to the IEC bus",
1429 "With this command, you can write raw data to the IEC bus.\n"
1430 "<file> (optional) file name of a file to read the values from.\n"
1431 " If this name is not given or it is a dash ('-'), the\n"
1432 " contents will be read from stdin, normally the console." },
1434 {1,
"put" , PA_RAW, do_put ,
"[-e|--extended] <datastr> [<data1> ... <dataN>]",
1435 "put specified data to the IEC bus",
1436 "With this command, you can write raw data to the IEC bus.\n"
1437 "<datastr> is the string to output to the IEC bus.\n"
1438 " It must be given, but may be empty by specifying it as \"\".\n\n"
1439 "<data1..N> are additional bytes to append to the string <datastr>.\n"
1440 " Single bytes can be given as decimal, octal (0 prefix) or\n"
1441 " sedecimal (0x prefix).\n\n"
1442 "If the option -e or --extended is given, an extended format is used:\n"
1443 " You can specify extra characters by given their ASCII value in hex,\n"
1444 " prepended with '%', that is: '%20' => SPACE, '%41' => 'A', '%35' => '5',\n"
1445 " and-so-on. A '%' is given by giving its hex ASCII: '%25' => '%'.\n\n"
1447 "- If using both --pestscii and --extended option, the bytes given via the\n"
1448 " '%' meta-character or as <data1> .. <dataN> are *not* converted to petscii." },
1450 {1,
"status" , PA_PETSCII, do_status ,
"<device>",
1451 "give the status of the specified drive",
1452 "This command gets the status (the so-called 'error channel')"
1453 "of the given drive and outputs it on the screen.\n"
1454 "<device> is the device number of the drive." },
1456 {1,
"command" , PA_RAW, do_command ,
"[-e|--extended] <device> <cmdstr> [<cmd1> ... <cmdN>]",
1457 "issue a command to the specified drive",
1458 "This command issues a command to a specific drive.\n"
1459 "This command is a command that you normally give to\n"
1460 "channel 15 (i.e., N: to format a drive, V: to validate, etc.).\n\n"
1461 "<device> is the device number of the drive.\n\n"
1462 "<cmdstr> is the command to execute in the drive.\n"
1463 " It must be given, but may be empty by specifying it as \"\".\n\n"
1464 "<cmd1..N> are additional bytes to append to the command string <cmdstr>.\n"
1465 " Single bytes can be given as decimal, octal (0 prefix) or\n"
1466 " sedecimal (0x prefix).\n\n"
1467 "If the option -e or --extended is given, an extended format is used:\n"
1468 " You can specify extra characters by given their ASCII value in hex,\n"
1469 " prepended with '%', that is: '%20' => SPACE, '%41' => 'A', '%35' => '5',\n"
1470 " and-so-on. A '%' is given by giving its hex ASCII: '%25' => '%'.\n\n"
1471 "Example: Write the bytes $29, $49 into memory locations $0077 and $0078\n"
1472 " of drive 8 (which gives the drive the address 9):\n"
1473 " cbmctrl -p command -e 8 m-w 119 0 2 41 73\n"
1474 " or cbmctrl -p command -e 8 m-w%77%00 2 0x29 0x49\n\n"
1476 "- If --raw is used (default), you have to give the commands in uppercase\n"
1477 " letters, lowercase will NOT work!\n"
1478 " If --petscii is used, you must give the commands in lowercase.\n"
1479 "- If used with the global --petscii option, this action is equivalent\n"
1480 " to the deprecated command-line 'cbmctrl pcommand'.\n"
1481 "- If using both --petscii and --extended option, the bytes given via the\n"
1482 " '%' meta-character or as <cmd1> .. <cmdN> are *not* converted to petscii." },
1484 {1,
"pcommand", PA_PETSCII, do_command ,
"[-e|--extended] <device> <cmdstr>",
1485 "deprecated; use 'cbmctrl --petscii command' instead!",
1486 "This command is deprecated; use 'cbmctrl -p command' instead!\n\n"
1487 "NOTE: You have to give the commands in lower-case letters.\n"
1488 " Upper case will NOT work!\n" },
1490 {1,
"dir" , PA_PETSCII, do_dir ,
"<device> [<drive>]",
1491 "output the directory of the disk in the specified drive",
1492 "This command gets the directory of a disk in the drive.\n\n"
1493 "<device> is the device number of the drive (bus ID).\n"
1494 "<drive> is the drive number of a dual drive (LUN), default is 0." },
1496 {1,
"download", PA_RAW, do_download,
"<device> <adr> <count> [<file>]",
1497 "download memory contents from the floppy drive",
1498 "With this command, you can get data from the floppy drive memory.\n"
1499 "<device> is the device number of the drive.\n"
1500 "<adr> is the starting address of the memory region to get.\n"
1501 " it can be given in decimal or in hex (with a 0x prefix).\n"
1502 "<count> is the number of bytes to read.\n"
1503 " it can be given in decimal or in hex (with a 0x prefix).\n"
1504 "<file> (optional) file name of a file to write the contents to.\n"
1505 " If this name is not given or it is a dash ('-'), the\n"
1506 " contents will be written to stdout, normally the console.\n\n"
1508 " cbmctrl download 8 0xc000 0x4000 1541ROM.BIN\n"
1509 " * reads the 1541 ROM (from $C000 to $FFFF) from drive 8 into 1541ROM.BIN" },
1511 {1,
"upload" , PA_RAW, do_upload ,
"<device> <adr> [<file>]",
1512 "upload memory contents to the floppy drive",
1513 "With this command, you can write data to the floppy drive memory.\n"
1514 "<device> is the device number of the drive.\n"
1515 "<adr> is the starting address of the memory region to write to.\n"
1516 " it can be given in decimal or in hex (with a 0x prefix).\n"
1517 " If this is -1, the first two bytes from the file are\n"
1518 " considered as start address.\n"
1519 "<file> (optional) file name of a file to read the values from.\n"
1520 " If this name is not given or it is a dash ('-'), the\n"
1521 " contents will be read from stdin, normally the console."
1523 " cbmctrl upload 8 0x500 BUFFER2.BIN\n"
1524 " * writes the file BUFFER2.BIN to drive 8, address $500." },
1526 {1,
"clk" , PA_UNSPEC, do_iec_clk ,
"",
1527 "Set the clk line on the IEC bus.",
1528 "This command unconditionally sets the CLK line on the IEC bus." },
1530 {1,
"uclk" , PA_UNSPEC, do_iec_uclk ,
"",
1531 "Unset the clk line on the IEC bus.",
1532 "This command unconditionally unsets the CLK line on the IEC bus." },
1534 {1,
"reset" , PA_UNSPEC, do_reset ,
"",
1535 "reset all drives on the IEC bus",
1536 "This command performs a (physical) reset of all drives on the IEC bus." },
1538 {1,
"detect" , PA_UNSPEC, do_detect ,
"",
1539 "detect all drives on the IEC bus",
1540 "This command tries to detect all drives on the IEC bus.\n"
1541 "For this, this command accesses all possible drives and tries to read\n"
1542 "some bytes from their memory. If a drive is detected, its name is output.\n"
1543 "Additionally, this routine determines if the drive is connected via a\n"
1544 "parallel cable (XP1541 companion cable)." },
1546 {1,
"change" , PA_UNSPEC, do_change ,
"<device>",
1547 "wait for a disk to be changed in the specified drive",
1548 "This command waits for a disk to be changed in the specified drive.\n\n"
1549 "For this, it makes the following assumptions:\n\n"
1550 "* there is already a disk in the drive.\n"
1551 "* that disk will be removed and replaced by another disk.\n"
1552 "* we do not want to return from this command until the disk is completely\n"
1553 " inserted and ready to be read/written.\n\n"
1554 "Because of this, just opening the drive and closing it again (without\n"
1555 "actually removing the disk) will not work in most cases." },
1557 {0, NULL, PA_UNSPEC, NULL, NULL, NULL}
1560 static struct prog *
1561 process_cmdline_find_command(
OPTIONS *options)
1563 if (options->
argc >= 1)
1565 const char *
const name = options->
argv[0];
1568 for (i=0; prog_table[i].name; i++)
1570 if (strcmp(name, prog_table[i].name) == 0)
1577 return &prog_table[i];
1592 do_version(fd, options);
1596 if (options->
argc == 0)
1598 printf(
"control serial CBM devices\n"
1600 " Synopsis: cbmctrl [global_options] [action] [action_opt] [--] [action_args]\n"
1602 " Global options:\n"
1604 " -h, --help: Output this help screen if specified without an action.\n"
1605 " Outputs some help information about a specific action\n"
1606 " if an action is specified.\n"
1607 " -V, --version: Output version information\n"
1608 " -@, --adapter: Tell OpenCBM which backend plugin and bus to use. This option\n"
1609 " requires an argument of the form <plugin>[:<bus>].\n"
1610 " <plugin> is the backend plugin's name to use (e.g.: xa1541)\n"
1611 " <bus> is a bus unit identifier, if supported by the backend;\n"
1612 " look up the backend's documentation for the supported\n"
1613 " bus unit identifier(s) and the format for <bus>\n"
1614 " -p, --petscii: Convert input or output parameter from CBM format (PETSCII)\n"
1615 " into PC format (ASCII). Default with all actions but 'open'\n"
1617 " -r, --raw: Do not convert data between CBM and PC format.\n"
1618 " Default with 'open' and 'command'.\n"
1619 " -- Delimiter between action_opt and action_args; if any of the\n"
1620 " arguments in action_args starts with a '-', make sure to set\n"
1621 " the '--' so the argument is not treated as an option,\n"
1624 " action: one of:\n"
1627 for(i=0; prog_table[i].prog; i++)
1629 printf(
" %-9s %s\n", prog_table[i].name, prog_table[i].shorthelp_text);
1632 printf(
"\nFor more information on a specific action, try --help <action>.\n");
1639 pprog = process_cmdline_find_command(options);
1643 printf(
" cbmctrl %s %s\n\n %s\n\n%s\n",
1644 pprog->name, pprog->arglist, pprog->shorthelp_text, pprog->help_text);
1648 printf(
" Nothing known about \"cbmctrl %s\".\n", options->
argv[0]);
1656 set_option(
int *Where,
int NewValue,
int OldValue,
const char *
const Description)
1660 if (*Where != OldValue)
1663 fprintf(stderr,
"Specified option '%s', but there is a conflicting option,\n"
1664 "or it is specified twice!\n", Description);
1673 set_option_petsciiraw(PETSCII_RAW *Where, PETSCII_RAW NewValue,
int IgnoreError)
1677 if (!IgnoreError && (*Where != PA_UNSPEC))
1680 fprintf(stderr,
"Specified option '--petscii' and '--raw' in one command!\n");
1689 process_cmdline_common_options(
int argc,
char **argv,
OPTIONS *options)
1691 unsigned int use_rc = 1;
1695 static const char short_options[] =
"+fhVpr@:";
1696 static struct option long_options[] =
1698 {
"adapter" , required_argument, NULL,
'@' },
1699 {
"forget" , no_argument, NULL,
'f' },
1700 {
"help" , no_argument, NULL,
'h' },
1701 {
"version" , no_argument, NULL,
'V' },
1702 {
"petscii" , no_argument, NULL,
'p' },
1703 {
"raw" , no_argument, NULL,
'r' },
1704 { NULL , no_argument, NULL, 0 }
1708 memset(options, 0,
sizeof(*options));
1712 options->
argc = argc;
1713 options->
argv = argv;
1720 while ((option = getopt_long(options->
argc, options->
argv, short_options, long_options, &option_index)) != EOF)
1733 while ((option = getopt_long(options->
argc, options->
argv, short_options, long_options, &option_index)) != EOF)
1738 fprintf(stderr,
"unknown option %s specified!\n",
1739 options->
argv[optind-1]);
1749 set_option(&options->
help, 1, 0,
"--help");
1760 set_option(&options->
version, 1, 0,
"--version");
1764 options->
error |= set_option_petsciiraw(&options->
petsciiraw, PA_PETSCII, 0);
1768 options->
error |= set_option_petsciiraw(&options->
petsciiraw, PA_RAW, 0);
1774 options->
argc -= optind;
1775 options->
argv += optind;
1777 return options->
error;
1781 free_options(
OPTIONS *
const options)
1787 process_version_help(
OPTIONS *
const options)
1793 do_help(0, options);
1799 do_version(0, NULL);
1803 if (processed && options->
argc > 0)
1804 fprintf(stderr,
"Extra parameters on command-line are ignored.\n");
1809 int ARCH_MAINDECL
main(
int argc,
char *argv[])
1822 rv = process_cmdline_common_options(argc, argv, &options);
1826 if (process_version_help(&options))
1829 pprog = process_cmdline_find_command(&options);
1833 printf(
"invalid command. For info on possible commands, try the --help parameter.\n\n");
1842 if (pprog->need_driver)
1847 if (arch_get_errno())
1853 fprintf(stderr,
"An error occurred opening OpenCBM, aborting...\n");
1858 rv = pprog->prog(fd, &options) != 0;
1859 if (rv && arch_get_errno())
1861 arch_error(0, arch_get_errno(),
"%s", pprog->name);
1864 if (pprog->need_driver)
1869 free_options(&options);
int CBMAPIDECL cbm_identify_xp1541(CBM_FILE HandleDevice, unsigned char DeviceAddress, enum cbm_device_type_e *CbmDeviceType, enum cbm_cable_type_e *CableType)
Identify the cable connected to a specific floppy drive.
int version
option: print version information
int CBMAPIDECL cbm_talk(CBM_FILE HandleDevice, unsigned char DeviceAddress, unsigned char SecondaryAddress)
Send a TALK on the IEC serial bus.
char * cbmlibmisc_strdup(const char *const OldString)
Duplicate a given string.
int CBMAPIDECL cbm_listen(CBM_FILE HandleDevice, unsigned char DeviceAddress, unsigned char SecondaryAddress)
Send a LISTEN on the IEC serial bus.
char ** argv
a (modifieable) copy of the argument list, as given to main()
void CBMAPIDECL cbm_unlock(CBM_FILE HandleDevice)
Unlock the parallel port for the driver.
void cbmlibmisc_strfree(const char *String)
Free a string.
int error
there was an error in processing the options (=1), or not (=0)
int CBMAPIDECL cbm_device_status(CBM_FILE HandleDevice, unsigned char DeviceAddress, void *Buffer, size_t BufferLength)
Read the drive status from a floppy.
int help
option: the user requested help for the specified command
int ownargv
remember: This is the original argv (=0), or this is a malloc()ed copy of it (=1) ...
int CBMAPIDECL cbm_close(CBM_FILE HandleDevice, unsigned char DeviceAddress, unsigned char SecondaryAddress)
Close a file on the IEC serial bus.
struct to remember the general options to the program
const char *CBMAPIDECL cbm_get_driver_name_ex(char *Adapter)
Get the name of the driver for a specific parallel port, extended version.
int ARCH_MAINDECL main(int argc, char **argv)
Initialize the xum1541 device This function tries to find and identify the xum1541 device...
int CBMAPIDECL cbm_driver_open_ex(CBM_FILE *HandleDevice, char *Adapter)
Opens the driver, extended version.
void CBMAPIDECL cbm_lock(CBM_FILE HandleDevice)
Lock the parallel port for the driver.
void CBMAPIDECL cbm_iec_set(CBM_FILE HandleDevice, int Line)
Activate a line on the IEC serial bus.
char *CBMAPIDECL cbm_petscii2ascii(char *Str)
Convert an null-termined PETSCII string to ASCII.
int CBMAPIDECL cbm_raw_write(CBM_FILE HandleDevice, const void *Buffer, size_t Count)
Write data to the IEC serial bus.
void CBMAPIDECL cbm_driver_close(CBM_FILE HandleDevice)
Closes the driver.
int CBMAPIDECL cbm_unlisten(CBM_FILE HandleDevice)
Send an UNLISTEN on the IEC serial bus.
int arch_filesize(const char *Filename, off_t *Filesize)
Obtain the size of a given file.
void CBMAPIDECL cbm_iec_release(CBM_FILE HandleDevice, int Line)
Deactivate a line on the IEC serial bus.
int CBMAPIDECL cbm_open(CBM_FILE HandleDevice, unsigned char DeviceAddress, unsigned char SecondaryAddress, const void *Filename, size_t FilenameLength)
Open a file on the IEC serial bus.
#define arch_set_errno(_x)
int argc
a (modifieable) copy of the number of arguments, as given to main()
int CBMAPIDECL cbm_raw_read(CBM_FILE HandleDevice, void *Buffer, size_t Count)
Read data from the IEC serial bus.
int CBMAPIDECL cbm_reset(CBM_FILE HandleDevice)
RESET all devices.
int CBMAPIDECL cbm_iec_wait(CBM_FILE HandleDevice, int Line, int State)
Wait for a line to have a specific state.
char *CBMAPIDECL cbm_ascii2petscii(char *Str)
Convert an null-termined ASCII string to PETSCII.
int CBMAPIDECL cbm_exec_command(CBM_FILE HandleDevice, unsigned char DeviceAddress, const void *Command, size_t Size)
Executes a command in the floppy drive.
char CBMAPIDECL cbm_petscii2ascii_c(char Character)
Convert a PETSCII character to ASCII.
int CBMAPIDECL cbm_identify(CBM_FILE HandleDevice, unsigned char DeviceAddress, enum cbm_device_type_e *CbmDeviceType, const char **CbmDeviceString)
Identify the connected floppy drive.
DLL interface for accessing the driver.
char CBMAPIDECL cbm_ascii2petscii_c(char Character)
Convert an ASCII character to PETSCII.
char * adapter
option: an explicit adapter was specified
int CBMAPIDECL cbm_untalk(CBM_FILE HandleDevice)
Send an UNTALK on the IEC serial bus.
Define makros and functions which account for differences between the different architectures.
int CBMAPIDECL cbm_upload(CBM_FILE HandleDevice, unsigned char DeviceAddress, int DriveMemAddress, const void *Program, size_t Size)
Upload a program into a floppy's drive memory.
PETSCII_RAW petsciiraw
option: The user requested PETSCII or RAW, or nothing
Some functions for string handling.