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