xref: /netbsd-src/usr.sbin/umcpmioctl/putflash.c (revision 3bfaa97146632a7fff2425e11c47d4964bacef79)
1 /*	$NetBSD: putflash.c,v 1.1 2024/12/16 16:37:40 brad Exp $	*/
2 
3 /*
4  * Copyright (c) 2024 Brad Spencer <brad@anduin.eldar.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #ifdef __RCSID
20 __RCSID("$NetBSD: putflash.c,v 1.1 2024/12/16 16:37:40 brad Exp $");
21 #endif
22 
23 /* Functions to parse stuff */
24 
25 #include <stdio.h>
26 #include <errno.h>
27 #include <string.h>
28 #include <stdbool.h>
29 
30 #include <dev/usb/umcpmio_hid_reports.h>
31 #include <dev/usb/umcpmio_io.h>
32 #include <sys/ioctl.h>
33 
34 #undef EXTERN
35 #define EXTERN
36 #include "putflash.h"
37 
38 
39 int
40 parse_flash_gp_req(int fd, struct mcp2221_put_flash_req *req, char *argv[], int start, int end, bool debug)
41 {
42 	int error = 0;
43 	struct umcpmio_ioctl_get_flash current_flash;
44 	int arggood = false;
45 
46 	current_flash.subcode = MCP2221_FLASH_SUBCODE_GP;
47 	error = ioctl(fd, UMCPMIO_GET_FLASH, &current_flash);
48 
49 	if (debug)
50 		fprintf(stderr,"CURRENT FLASH: error=%d\n",error);
51 
52 	if (!error) {
53 		int argcount = start;
54 		uint8_t *gp;
55 
56 		uint8_t *bbuf = (uint8_t *)&current_flash.get_flash_res;
57 		if (debug) {
58 			fprintf(stderr,"CURRENT REQ:\n");
59 			for(int i=0;i < MCP2221_RES_BUFFER_SIZE;i++) {
60 				fprintf(stderr,"%02x ",bbuf[i]);
61 			}
62 			fprintf(stderr,"\n");
63 		}
64 
65 		/* When flash is put, you put ALL of a particular subcode, so
66 		 * you have to do a get + put */
67 
68 		req->u.gp.gp0_settings = current_flash.get_flash_res.u.gp.gp0_settings;
69 		req->u.gp.gp1_settings = current_flash.get_flash_res.u.gp.gp1_settings;
70 		req->u.gp.gp2_settings = current_flash.get_flash_res.u.gp.gp2_settings;
71 		req->u.gp.gp3_settings = current_flash.get_flash_res.u.gp.gp3_settings;
72 
73 		if (debug)
74 			fprintf(stderr,"CURRENT FLASH: %02x %02x %02x %02x\n", current_flash.get_flash_res.u.gp.gp0_settings, current_flash.get_flash_res.u.gp.gp1_settings, current_flash.get_flash_res.u.gp.gp2_settings, current_flash.get_flash_res.u.gp.gp3_settings);
75 
76 		while (argcount < end) {
77 			gp = NULL;
78 			if (strncmp(argv[argcount],"GP0",4) == 0) {
79 				gp = (uint8_t *)&req->u.gp.gp0_settings;
80 			}
81 			if (strncmp(argv[argcount],"GP1",4) == 0) {
82 				gp = (uint8_t *)&req->u.gp.gp1_settings;
83 			}
84 			if (strncmp(argv[argcount],"GP2",4) == 0) {
85 				gp = (uint8_t *)&req->u.gp.gp2_settings;
86 			}
87 			if (strncmp(argv[argcount],"GP3",4) == 0) {
88 				gp = (uint8_t *)&req->u.gp.gp3_settings;
89 			}
90 			if (gp == NULL) {
91 				if (debug)
92 					fprintf(stderr,"NOT GPn: %d %s\n",argcount,argv[argcount]);
93 				error = EINVAL;
94 				break;
95 			}
96 			argcount++;
97 			if (argcount < end) {
98 				arggood = false;
99 				if (strncmp(argv[argcount],"GPIO_PIN_INPUT",15) == 0) {
100 					*gp &= MCP2221_FLASH_GPIO_VALUE_MASK;
101 					*gp |= MCP2221_FLASH_GPIO_INPUT;
102 					arggood = true;
103 				}
104 				if (strncmp(argv[argcount],"GPIO_PIN_OUTPUT",16) == 0) {
105 					*gp &= MCP2221_FLASH_GPIO_VALUE_MASK;
106 					arggood = true;
107 				}
108 				if (strncmp(argv[argcount],"GPIO_PIN_ALT0",14) == 0) {
109 					*gp &= (MCP2221_FLASH_GPIO_VALUE_MASK | MCP2221_FLASH_GPIO_INPUT);
110 					*gp &= ~MCP2221_FLASH_PIN_TYPE_MASK;
111 					*gp |= MCP2221_FLASH_PIN_IS_ALT0;
112 					arggood = true;
113 				}
114 				if (strncmp(argv[argcount],"GPIO_PIN_ALT1",14) == 0) {
115 					*gp &= (MCP2221_FLASH_GPIO_VALUE_MASK | MCP2221_FLASH_GPIO_INPUT);
116 					*gp &= ~MCP2221_FLASH_PIN_TYPE_MASK;
117 					*gp |= MCP2221_FLASH_PIN_IS_ALT1;
118 					arggood = true;
119 				}
120 				if (strncmp(argv[argcount],"GPIO_PIN_ALT2",14) == 0) {
121 					*gp &= (MCP2221_FLASH_GPIO_VALUE_MASK | MCP2221_FLASH_GPIO_INPUT);
122 					*gp &= ~MCP2221_FLASH_PIN_TYPE_MASK;
123 					*gp |= MCP2221_FLASH_PIN_IS_ALT2;
124 					arggood = true;
125 				}
126 				if (strncmp(argv[argcount],"GPIO_PIN_ALT3",14) == 0) {
127 					*gp &= (MCP2221_FLASH_GPIO_VALUE_MASK | MCP2221_FLASH_GPIO_INPUT);
128 					*gp &= ~MCP2221_FLASH_PIN_TYPE_MASK;
129 					*gp |= MCP2221_FLASH_PIN_IS_DED;
130 					arggood = true;
131 				}
132 				if (strncmp(argv[argcount],"DEFAULT_OUTPUT_ZERO",20) == 0) {
133 					*gp &= ~MCP2221_FLASH_GPIO_VALUE_MASK;
134 					arggood = true;
135 				}
136 				if (strncmp(argv[argcount],"DEFAULT_OUTPUT_ONE",19) == 0) {
137 					*gp |= MCP2221_FLASH_GPIO_VALUE_MASK;
138 					arggood = true;
139 				}
140 				if (!arggood) {
141 					if (debug)
142 						fprintf(stderr,"BAD ARGUMENT: %d %s\n",argcount,argv[argcount]);
143 					error = EINVAL;
144 					break;
145 				}
146 			} else {
147 				error = EINVAL;
148 			}
149 
150 			argcount++;
151 		}
152 	}
153 
154 	return(error);
155 }
156