summaryrefslogtreecommitdiff
path: root/avr/cmd_attach.c
blob: 09496875c3bf28f0b3ce034f419659c263b2d6db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
 * (C) Copyright 2016 Leo C. <erbl259-lmu@yahoo.de>
 *
 * SPDX-License-Identifier:	GPL-2.0
 */

/*
 * attach channels to devices
 */

#include "cmd_attach.h"

#include "command.h"
#include "z180-serv.h"
#include "getopt-min.h"


/*
 * attach [[options] [unit [diskfile]]]
 *
 * detach unit
 * attach -d unit
 *
 * attach -o reattach unit
 * attach -o reattach unit diskfile
 *
 * attach unit diskfile
 *
 */

command_ret_t do_attach(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
{
	uint8_t unit = 0;
	char *filename = NULL;
	bool detach = false;
	bool detach_all = false;
	drv_opt_t options = 0;
	int res;

	(void) cmdtp; (void) flag;


	if (argv[0][0] == 'd') {
		/* we are called as 'detach' */
		detach = true;
	} else if (argc == 1) {
		/* no arguments */
		drv_list();
		return CMD_RET_SUCCESS;
	}

	/* reset getopt() */
	optind = 0;

	int opt;
	while ((opt = getopt(argc, argv, PSTR("darwo:"))) != -1) {
		switch (opt) {
		case 'd':
			detach = true;
			break;
		case 'a':
			detach_all = true;
			break;
		case 'r':
			options |= DRV_OPT_RO;
			break;
		case 'w':
			options &= ~DRV_OPT_RO;
			break;
		case 'o':
			{
				static const FLASH char delim[] = {", "};
				char *p = strtok_P(optarg, delim);
				while (p != NULL) {
					if (!strcmp_P(p, PSTR("ro")))
						options |= DRV_OPT_RO;
					else if (!strcmp_P(p, PSTR("rw")))
						options &= ~DRV_OPT_RO;
					else if (!strcmp_P(p, PSTR("debug")))
						options |= DRV_OPT_DEBUG;
					else if (!strcmp_P(p, PSTR("nodebug")))
						options &= ~DRV_OPT_DEBUG;
					else if (!strcmp_P(p, PSTR("reattach")))
						options |= DRV_OPT_REATTATCH;
					else
						return CMD_RET_USAGE;

					p = strtok_P(NULL, delim);
				}
			}
			break;
		default: /* '?' */
			return CMD_RET_USAGE;
		}
	}

	/* remaining arguments */
	argc -= optind;
	if ( !( (argc == 0 && detach && detach_all) ||
			(argc == 1 && detach) ||
			(argc == 1 && (options & DRV_OPT_REATTATCH)) ||
			 argc == 2) )
		return CMD_RET_USAGE;

	if (argc > 0 && ((strlen(argv[optind]) != 4) ||
			strncmp_P(argv[optind], PSTR("dsk"), 3) ||
			(unit = argv[optind][3] - '0') >= CONFIG_CPM_MAX_DRIVE)) {

		cmd_error(CMD_RET_FAILURE, 0, PSTR("Invalid device: '%s'"), argv[optind]);
	}

	if (detach) {
		if (detach_all)
			for (uint8_t i = 0; i < CONFIG_CPM_MAX_DRIVE; i++)
				drv_detach(i);
		else
			drv_detach(unit);
		return CMD_RET_SUCCESS;
	}

	if (argc == 2)
		filename = argv[++optind];

	res = drv_attach(unit, filename, options);
	if (res)
		cmd_error(CMD_RET_FAILURE, res, PSTR("Attachment of '%s' to dsk%d failed"),	filename, unit);

	return CMD_RET_SUCCESS;
}