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, ¤t_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 *)¤t_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