Home | History | Annotate | Line # | Download | only in umcpmioctl
      1 /*	$NetBSD: putflash.c,v 1.3 2025/03/22 06:09:48 rillig Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2024 Brad Spencer <brad (at) 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 #include <sys/cdefs.h>
     20 #ifdef __RCSID
     21 __RCSID("$NetBSD: putflash.c,v 1.3 2025/03/22 06:09:48 rillig Exp $");
     22 #endif
     23 
     24 /* Functions to parse stuff */
     25 
     26 #include <stdio.h>
     27 #include <errno.h>
     28 #include <string.h>
     29 #include <stdbool.h>
     30 
     31 #include <dev/usb/umcpmio_hid_reports.h>
     32 #include <dev/usb/umcpmio_io.h>
     33 #include <sys/ioctl.h>
     34 
     35 #undef EXTERN
     36 #define EXTERN
     37 #include "putflash.h"
     38 
     39 
     40 int
     41 parse_flash_gp_req(int fd, struct mcp2221_put_flash_req *req, char *argv[], int start, int end, bool debug)
     42 {
     43 	int error = 0;
     44 	struct umcpmio_ioctl_get_flash current_flash;
     45 	int arggood = false;
     46 
     47 	current_flash.subcode = MCP2221_FLASH_SUBCODE_GP;
     48 	error = ioctl(fd, UMCPMIO_GET_FLASH, &current_flash);
     49 
     50 	if (debug)
     51 		fprintf(stderr, "CURRENT FLASH: error=%d\n", error);
     52 
     53 	if (!error) {
     54 		int argcount = start;
     55 		uint8_t *gp;
     56 
     57 		uint8_t *bbuf = (uint8_t *)&current_flash.get_flash_res;
     58 		if (debug) {
     59 			fprintf(stderr, "CURRENT REQ:\n");
     60 			for (int i = 0; i < MCP2221_RES_BUFFER_SIZE; i++) {
     61 				fprintf(stderr, "%02x ", bbuf[i]);
     62 			}
     63 			fprintf(stderr, "\n");
     64 		}
     65 
     66 		/*
     67 		 * When flash is put, you put ALL of a particular subcode, so
     68 		 * you have to do a get + put
     69 		 */
     70 
     71 		req->u.gp.gp0_settings = current_flash.get_flash_res.u.gp.gp0_settings;
     72 		req->u.gp.gp1_settings = current_flash.get_flash_res.u.gp.gp1_settings;
     73 		req->u.gp.gp2_settings = current_flash.get_flash_res.u.gp.gp2_settings;
     74 		req->u.gp.gp3_settings = current_flash.get_flash_res.u.gp.gp3_settings;
     75 
     76 		if (debug)
     77 			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);
     78 
     79 		while (argcount < end) {
     80 			gp = NULL;
     81 			if (strncmp(argv[argcount], "GP0", 4) == 0) {
     82 				gp = (uint8_t *)&req->u.gp.gp0_settings;
     83 			}
     84 			if (strncmp(argv[argcount], "GP1", 4) == 0) {
     85 				gp = (uint8_t *)&req->u.gp.gp1_settings;
     86 			}
     87 			if (strncmp(argv[argcount], "GP2", 4) == 0) {
     88 				gp = (uint8_t *)&req->u.gp.gp2_settings;
     89 			}
     90 			if (strncmp(argv[argcount], "GP3", 4) == 0) {
     91 				gp = (uint8_t *)&req->u.gp.gp3_settings;
     92 			}
     93 			if (gp == NULL) {
     94 				if (debug)
     95 					fprintf(stderr, "NOT GPn: %d %s\n", argcount, argv[argcount]);
     96 				error = EINVAL;
     97 				break;
     98 			}
     99 			argcount++;
    100 			if (argcount < end) {
    101 				arggood = false;
    102 				if (strncmp(argv[argcount], "GPIO_PIN_INPUT", 15) == 0) {
    103 					*gp &= MCP2221_FLASH_GPIO_VALUE_MASK;
    104 					*gp |= MCP2221_FLASH_GPIO_INPUT;
    105 					arggood = true;
    106 				}
    107 				if (strncmp(argv[argcount], "GPIO_PIN_OUTPUT", 16) == 0) {
    108 					*gp &= MCP2221_FLASH_GPIO_VALUE_MASK;
    109 					arggood = true;
    110 				}
    111 				if (strncmp(argv[argcount], "GPIO_PIN_ALT0", 14) == 0) {
    112 					*gp &= (MCP2221_FLASH_GPIO_VALUE_MASK | MCP2221_FLASH_GPIO_INPUT);
    113 					*gp &= ~MCP2221_FLASH_PIN_TYPE_MASK;
    114 					*gp |= MCP2221_FLASH_PIN_IS_ALT0;
    115 					arggood = true;
    116 				}
    117 				if (strncmp(argv[argcount], "GPIO_PIN_ALT1", 14) == 0) {
    118 					*gp &= (MCP2221_FLASH_GPIO_VALUE_MASK | MCP2221_FLASH_GPIO_INPUT);
    119 					*gp &= ~MCP2221_FLASH_PIN_TYPE_MASK;
    120 					*gp |= MCP2221_FLASH_PIN_IS_ALT1;
    121 					arggood = true;
    122 				}
    123 				if (strncmp(argv[argcount], "GPIO_PIN_ALT2", 14) == 0) {
    124 					*gp &= (MCP2221_FLASH_GPIO_VALUE_MASK | MCP2221_FLASH_GPIO_INPUT);
    125 					*gp &= ~MCP2221_FLASH_PIN_TYPE_MASK;
    126 					*gp |= MCP2221_FLASH_PIN_IS_ALT2;
    127 					arggood = true;
    128 				}
    129 				if (strncmp(argv[argcount], "GPIO_PIN_ALT3", 14) == 0) {
    130 					*gp &= (MCP2221_FLASH_GPIO_VALUE_MASK | MCP2221_FLASH_GPIO_INPUT);
    131 					*gp &= ~MCP2221_FLASH_PIN_TYPE_MASK;
    132 					*gp |= MCP2221_FLASH_PIN_IS_DED;
    133 					arggood = true;
    134 				}
    135 				if (strncmp(argv[argcount], "DEFAULT_OUTPUT_ZERO", 20) == 0) {
    136 					*gp &= ~MCP2221_FLASH_GPIO_VALUE_MASK;
    137 					arggood = true;
    138 				}
    139 				if (strncmp(argv[argcount], "DEFAULT_OUTPUT_ONE", 19) == 0) {
    140 					*gp |= MCP2221_FLASH_GPIO_VALUE_MASK;
    141 					arggood = true;
    142 				}
    143 				if (!arggood) {
    144 					if (debug)
    145 						fprintf(stderr, "BAD ARGUMENT: %d %s\n", argcount, argv[argcount]);
    146 					error = EINVAL;
    147 					break;
    148 				}
    149 			} else {
    150 				error = EINVAL;
    151 			}
    152 
    153 			argcount++;
    154 		}
    155 	}
    156 
    157 	return (error);
    158 }
    159