Home | History | Annotate | Line # | Download | only in tadpolectl
      1 /* $NetBSD: tadpolectl.c,v 1.10 2018/01/23 19:01:33 sevan Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 1999 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Tim Rightnour.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <ctype.h>
     33 #include <err.h>
     34 #include <stdio.h>
     35 #include <string.h>
     36 #include <stdlib.h>
     37 #include <fcntl.h>
     38 #include <unistd.h>
     39 #include <sys/ioctl.h>
     40 #include <sys/types.h>
     41 #include <sys/envsys.h>
     42 #include <machine/apmvar.h>
     43 #include <machine/tctrl.h>
     44 
     45 #define TCTRL_DEV	"/dev/tctrl0"
     46 
     47 int aflag, nflag, wflag, dev;
     48 
     49 #define PROTO(x) int x(int, int, int);
     50 static void usage(void) __dead;
     51 static void parse(char *);
     52 char *dashdot(const char *);
     53 PROTO(hw_version)
     54 PROTO(hw_microcontroller_version)
     55 PROTO(hw_poweroncycles)
     56 PROTO(hw_poweronseconds)
     57 PROTO(hw_power_mains)
     58 PROTO(hw_power_battery_int)
     59 PROTO(hw_power_battery_ext)
     60 PROTO(hw_power_battery_int_chargerate)
     61 PROTO(hw_power_battery_ext_chargerate)
     62 PROTO(hw_power_battery_int_chargelevel)
     63 PROTO(hw_power_battery_ext_chargelevel)
     64 PROTO(hw_video_external)
     65 PROTO(hw_video_lid)
     66 PROTO(hw_video_syncinva)
     67 PROTO(hw_video_syncinvb)
     68 PROTO(hw_video_compsync)
     69 PROTO(hw_video_tft_brightness)
     70 PROTO(hw_speaker_freq)
     71 PROTO(hw_speaker_volume)
     72 PROTO(hw_kbd_repeat_delay)
     73 PROTO(hw_kbd_repeat_speed)
     74 PROTO(hw_mouse_recalibrate)
     75 PROTO(hw_power_battery_chargedisabled)
     76 PROTO(hw_mouse_disable)
     77 PROTO(hw_kbd_click)
     78 PROTO(hw_mouse_intclick)
     79 PROTO(hw_mouse_extclick)
     80 PROTO(hw_mouse_sensitivity)
     81 PROTO(hw_serial_power)
     82 
     83 #define NUM_MIBS 29
     84 #define TABLE(n) { __STRING(n), 0, n }
     85 
     86 struct {
     87 	const char *mib;
     88 	int value;
     89 	int (*funcptr)(int, int, int);
     90 } table[NUM_MIBS] = {
     91 	TABLE(hw_microcontroller_version),
     92 	TABLE(hw_version),
     93 	TABLE(hw_poweroncycles),
     94 	TABLE(hw_poweronseconds),
     95 	TABLE(hw_power_mains),
     96 	TABLE(hw_power_battery_int),
     97 	TABLE(hw_power_battery_ext),
     98 	TABLE(hw_power_battery_chargedisabled),
     99 	TABLE(hw_power_battery_int_chargerate),
    100 	TABLE(hw_power_battery_ext_chargerate),
    101 	TABLE(hw_power_battery_int_chargelevel),
    102 	TABLE(hw_power_battery_ext_chargelevel),
    103 	TABLE(hw_video_external),
    104 	TABLE(hw_video_lid),
    105 	TABLE(hw_video_syncinva),
    106 	TABLE(hw_video_syncinvb),
    107 	TABLE(hw_video_compsync),
    108 	TABLE(hw_video_tft_brightness),
    109 	TABLE(hw_speaker_freq),
    110 	TABLE(hw_speaker_volume),
    111 	TABLE(hw_kbd_repeat_delay),
    112 	TABLE(hw_kbd_repeat_speed),
    113 	TABLE(hw_kbd_click),
    114 	TABLE(hw_mouse_recalibrate),
    115 	TABLE(hw_mouse_disable),
    116 	TABLE(hw_mouse_intclick),
    117 	TABLE(hw_mouse_extclick),
    118 	TABLE(hw_mouse_sensitivity),
    119 	TABLE(hw_serial_power),
    120 };
    121 
    122 #define FUNC(x) \
    123 int \
    124 x(readflg, new, num) \
    125 	int readflg, new, num;
    126 
    127 #define READ_REQ(a, b, c) \
    128 	req.cmdbuf[0] = a; \
    129 	req.cmdlen = b; \
    130 	req.rsplen = c; \
    131 	ioctl(dev, TCTRL_CMD_REQ, &req)
    132 
    133 #define WRITE_REQ(a, b, c) \
    134 	req.cmdbuf[0] = a; \
    135 	req.cmdlen = b; \
    136 	req.rsplen = c; \
    137 	ioctl(dev, TCTRL_CMD_REQ, &req)
    138 
    139 #define READ_ONLY \
    140 	if (!readflg) \
    141 		return(0)
    142 
    143 /* hardware functions */
    144 
    145 FUNC(hw_mouse_sensitivity)
    146 {
    147 	struct tctrl_req req;
    148 
    149 	req.cmdbuf[1] = 0xff;
    150 	req.cmdbuf[2] = 0x00;
    151 	READ_REQ(0x2c, 3, 2);
    152 	table[num].value = req.rspbuf[0];
    153 	if (readflg)
    154 		return(1);
    155 	if (new == 0)
    156 		req.cmdbuf[2] = 0x00;
    157 	else if (new > 255)
    158 		req.cmdbuf[2] = 0xff;
    159 	else
    160 		req.cmdbuf[2] = new;
    161 	req.cmdbuf[1] = 0x00;
    162 	WRITE_REQ(0x2c, 3, 2);
    163 	req.cmdbuf[1] = 0xff;
    164 	req.cmdbuf[2] = 0x00;
    165 	READ_REQ(0x2c, 3, 2);
    166 	table[num].value = req.rspbuf[0];
    167 	return(1);
    168 }
    169 
    170 FUNC(hw_power_battery_chargedisabled)
    171 {
    172 	struct tctrl_req req;
    173 
    174 	req.cmdbuf[1] = 0xff;
    175 	req.cmdbuf[2] = 0x00;
    176 	READ_REQ(0x22, 3, 2);
    177 	table[num].value = req.rspbuf[0]&0x01 ? 1 : 0;
    178 	if (readflg)
    179 		return(1);
    180 	if (new == 0)
    181 		req.cmdbuf[2] = 0x00;
    182 	else
    183 		req.cmdbuf[2] = 0x01;
    184 	req.cmdbuf[1] = ~0x01;
    185 	WRITE_REQ(0x22, 3, 2);
    186 	req.cmdbuf[1] = 0xff;
    187 	req.cmdbuf[2] = 0x00;
    188 	READ_REQ(0x22, 3, 2);
    189 	table[num].value = req.rspbuf[0]&0x01 ? 1 : 0;
    190 	return(1);
    191 }
    192 
    193 FUNC(hw_mouse_disable)
    194 {
    195 	struct tctrl_req req;
    196 
    197 	req.cmdbuf[1] = 0xff;
    198 	req.cmdbuf[2] = 0x00;
    199 	READ_REQ(0x22, 3, 2);
    200 	table[num].value = req.rspbuf[0]&0x02 ? 1 : 0;
    201 	if (readflg)
    202 		return(1);
    203 	if (new == 0)
    204 		req.cmdbuf[2] = 0x00;
    205 	else
    206 		req.cmdbuf[2] = 0x02;
    207 	req.cmdbuf[1] = ~0x02;
    208 	WRITE_REQ(0x22, 3, 2);
    209 	req.cmdbuf[1] = 0xff;
    210 	req.cmdbuf[2] = 0x00;
    211 	READ_REQ(0x22, 3, 2);
    212 	table[num].value = req.rspbuf[0]&0x02 ? 1 : 0;
    213 	return(1);
    214 }
    215 
    216 FUNC(hw_kbd_click)
    217 {
    218 	struct tctrl_req req;
    219 
    220 	req.cmdbuf[1] = 0xff;
    221 	req.cmdbuf[2] = 0x00;
    222 	READ_REQ(0x22, 3, 2);
    223 	table[num].value = req.rspbuf[0]&0x04 ? 1 : 0;
    224 	if (readflg)
    225 		return(1);
    226 	if (new == 0)
    227 		req.cmdbuf[2] = 0x00;
    228 	else
    229 		req.cmdbuf[2] = 0x04;
    230 	req.cmdbuf[1] = ~0x04;
    231 	WRITE_REQ(0x22, 3, 2);
    232 	req.cmdbuf[1] = 0xff;
    233 	req.cmdbuf[2] = 0x00;
    234 	READ_REQ(0x22, 3, 2);
    235 	table[num].value = req.rspbuf[0]&0x04 ? 1 : 0;
    236 	return(1);
    237 }
    238 
    239 FUNC(hw_mouse_intclick)
    240 {
    241 	struct tctrl_req req;
    242 
    243 	req.cmdbuf[1] = 0xff;
    244 	req.cmdbuf[2] = 0x00;
    245 	READ_REQ(0x22, 3, 2);
    246 	table[num].value = req.rspbuf[0]&0x08 ? 1 : 0;
    247 	if (readflg)
    248 		return(1);
    249 	if (new == 0)
    250 		req.cmdbuf[2] = 0x00;
    251 	else
    252 		req.cmdbuf[2] = 0x08;
    253 	req.cmdbuf[1] = ~0x08;
    254 	WRITE_REQ(0x22, 3, 2);
    255 	req.cmdbuf[1] = 0xff;
    256 	req.cmdbuf[2] = 0x00;
    257 	READ_REQ(0x22, 3, 2);
    258 	table[num].value = req.rspbuf[0]&0x08 ? 1 : 0;
    259 	return(1);
    260 }
    261 
    262 FUNC(hw_mouse_extclick)
    263 {
    264 	struct tctrl_req req;
    265 
    266 	req.cmdbuf[1] = 0xff;
    267 	req.cmdbuf[2] = 0x00;
    268 	READ_REQ(0x22, 3, 2);
    269 	table[num].value = req.rspbuf[0]&0x10 ? 1 : 0;
    270 	if (readflg)
    271 		return(1);
    272 	if (new == 0)
    273 		req.cmdbuf[2] = 0x00;
    274 	else
    275 		req.cmdbuf[2] = 0x10;
    276 	req.cmdbuf[1] = ~0x10;
    277 	WRITE_REQ(0x22, 3, 2);
    278 	req.cmdbuf[1] = 0xff;
    279 	req.cmdbuf[2] = 0x00;
    280 	READ_REQ(0x22, 3, 2);
    281 	table[num].value = req.rspbuf[0]&0x10 ? 1 : 0;
    282 	return(1);
    283 }
    284 
    285 /* ARGSUSED */
    286 FUNC(hw_mouse_recalibrate)
    287 {
    288 	struct tctrl_req req;
    289 
    290 	table[num].value = 0;
    291 	if (readflg)
    292 		return(1);
    293 	READ_REQ(0x36, 1, 1);
    294 	return(1);
    295 }
    296 
    297 FUNC(hw_kbd_repeat_delay)
    298 {
    299 	struct tctrl_req req;
    300 
    301 	req.cmdbuf[1] = 0xff;
    302 	req.cmdbuf[2] = 0x00;
    303 	READ_REQ(0x28, 3, 2);
    304 	table[num].value = req.rspbuf[0];
    305 	if (readflg)
    306 		return(1);
    307 	if (new == 0)
    308 		req.cmdbuf[2] = 0x00;
    309 	else if (new > 255)
    310 		req.cmdbuf[2] = 0xff;
    311 	else
    312 		req.cmdbuf[2] = new;
    313 	req.cmdbuf[1] = 0x00;
    314 	WRITE_REQ(0x28, 3, 2);
    315 	req.cmdbuf[1] = 0xff;
    316 	req.cmdbuf[2] = 0x00;
    317 	READ_REQ(0x28, 3, 2);
    318 	table[num].value = req.rspbuf[0];
    319 	return(1);
    320 }
    321 
    322 FUNC(hw_kbd_repeat_speed)
    323 {
    324 	struct tctrl_req req;
    325 
    326 	req.cmdbuf[1] = 0xff;
    327 	req.cmdbuf[2] = 0x00;
    328 	READ_REQ(0x29, 3, 2);
    329 	table[num].value = req.rspbuf[0];
    330 	if (readflg)
    331 		return(1);
    332 	if (new == 0)
    333 		req.cmdbuf[2] = 0x00;
    334 	else if (new > 255)
    335 		req.cmdbuf[2] = 0xff;
    336 	else
    337 		req.cmdbuf[2] = new;
    338 	req.cmdbuf[1] = 0x00;
    339 	WRITE_REQ(0x29, 3, 2);
    340 	req.cmdbuf[1] = 0xff;
    341 	req.cmdbuf[2] = 0x00;
    342 	READ_REQ(0x29, 3, 2);
    343 	table[num].value = req.rspbuf[0];
    344 	return(1);
    345 }
    346 
    347 FUNC(hw_speaker_freq)
    348 {
    349 	struct tctrl_req req;
    350 
    351 	table[num].value = 0;
    352 	if (readflg)
    353 		return(1);
    354 	req.cmdbuf[1] = new * 256;
    355 	req.cmdbuf[2] = new % 256;
    356 	WRITE_REQ(0x37, 3, 1);
    357 	return(1);
    358 }
    359 
    360 FUNC(hw_speaker_volume)
    361 {
    362 	struct tctrl_req req;
    363 
    364 	req.cmdbuf[1] = 0xff;
    365 	req.cmdbuf[2] = 0x00;
    366 	READ_REQ(0x23, 3, 2);
    367 	table[num].value = req.rspbuf[0];
    368 	if (readflg)
    369 		return(1);
    370 	if (new == 0)
    371 		req.cmdbuf[2] = 0x00;
    372 	else if (new > 255)
    373 		req.cmdbuf[2] = 0xff;
    374 	else
    375 		req.cmdbuf[2] = new;
    376 	req.cmdbuf[1] = 0x00;
    377 	WRITE_REQ(0x23, 3, 2);
    378 	req.cmdbuf[1] = 0xff;
    379 	req.cmdbuf[2] = 0x00;
    380 	READ_REQ(0x23, 3, 2);
    381 	table[num].value = req.rspbuf[0];
    382 	return(1);
    383 }
    384 
    385 FUNC(hw_video_tft_brightness)
    386 {
    387 	struct tctrl_req req;
    388 
    389 	req.cmdbuf[1] = 0xff;
    390 	req.cmdbuf[2] = 0x00;
    391 	READ_REQ(0x24, 3, 2);
    392 	table[num].value = req.rspbuf[0];
    393 	if (readflg)
    394 		return(1);
    395 	if (new == 0)
    396 		req.cmdbuf[2] = 0x00;
    397 	else if (new > 255)
    398 		req.cmdbuf[2] = 0xff;
    399 	else
    400 		req.cmdbuf[2] = new;
    401 	req.cmdbuf[1] = 0x00;
    402 	WRITE_REQ(0x24, 3, 2);
    403 	req.cmdbuf[1] = 0xff;
    404 	req.cmdbuf[2] = 0x00;
    405 	READ_REQ(0x24, 3, 2);
    406 	table[num].value = req.rspbuf[0];
    407 	return(1);
    408 }
    409 
    410 FUNC(hw_video_syncinva)
    411 {
    412 	struct tctrl_req req;
    413 
    414 	req.cmdbuf[1] = 0xff;
    415 	req.cmdbuf[2] = 0x00;
    416 	READ_REQ(0x21, 3, 2);
    417 	table[num].value = req.rspbuf[0]&0x02 ? 1 : 0;
    418 	if (readflg)
    419 		return(1);
    420 	if (new == 0)
    421 		req.cmdbuf[2] = 0x00;
    422 	else
    423 		req.cmdbuf[2] = 0x02;
    424 	req.cmdbuf[1] = ~0x02;
    425 	WRITE_REQ(0x21, 3, 2);
    426 	req.cmdbuf[1] = 0xff;
    427 	req.cmdbuf[2] = 0x00;
    428 	READ_REQ(0x21, 3, 2);
    429 	table[num].value = req.rspbuf[0]&0x02 ? 1 : 0;
    430 	return(1);
    431 }
    432 
    433 FUNC(hw_video_syncinvb)
    434 {
    435 	struct tctrl_req req;
    436 
    437 	req.cmdbuf[1] = 0xff;
    438 	req.cmdbuf[2] = 0x00;
    439 	READ_REQ(0x21, 3, 2);
    440 	table[num].value = req.rspbuf[0]&0x04 ? 1 : 0;
    441 	if (readflg)
    442 		return(1);
    443 	if (new == 0)
    444 		req.cmdbuf[2] = 0x00;
    445 	else
    446 		req.cmdbuf[2] = 0x04;
    447 	req.cmdbuf[1] = ~0x04;
    448 	WRITE_REQ(0x21, 3, 2);
    449 	req.cmdbuf[1] = 0xff;
    450 	req.cmdbuf[2] = 0x00;
    451 	READ_REQ(0x21, 3, 2);
    452 	table[num].value = req.rspbuf[0]&0x04 ? 1 : 0;
    453 	return(1);
    454 }
    455 
    456 FUNC(hw_video_compsync)
    457 {
    458 	struct tctrl_req req;
    459 
    460 	req.cmdbuf[1] = 0xff;
    461 	req.cmdbuf[2] = 0x00;
    462 	READ_REQ(0x21, 3, 2);
    463 	table[num].value = req.rspbuf[0]&0x10 ? 1 : 0;
    464 	if (readflg)
    465 		return(1);
    466 	if (new == 0)
    467 		req.cmdbuf[2] = 0x00;
    468 	else
    469 		req.cmdbuf[2] = 0x10;
    470 	req.cmdbuf[1] = ~0x10;
    471 	WRITE_REQ(0x21, 3, 2);
    472 	req.cmdbuf[1] = 0xff;
    473 	req.cmdbuf[2] = 0x00;
    474 	READ_REQ(0x21, 3, 2);
    475 	table[num].value = req.rspbuf[0]&0x10 ? 1 : 0;
    476 	return(1);
    477 }
    478 
    479 /* ARGSUSED */
    480 FUNC(hw_video_lid)
    481 {
    482 	struct tctrl_req req;
    483 	short i;
    484 
    485 	READ_ONLY;
    486 	READ_REQ(0x11, 1, 3);
    487 	i = (req.rspbuf[0]<<8) + req.rspbuf[1];
    488 	table[num].value = i&0x0040 ? 0 : 1;
    489 	return(1);
    490 }
    491 
    492 /* ARGSUSED */
    493 FUNC(hw_video_external)
    494 {
    495 	struct tctrl_req req;
    496 	short i;
    497 
    498 	READ_ONLY;
    499 	READ_REQ(0x11, 1, 3);
    500 	i = (req.rspbuf[0]<<8) + req.rspbuf[1];
    501 	table[num].value = i&0x0008 ? 1 : 0;
    502 	return(1);
    503 }
    504 
    505 /* ARGSUSED */
    506 FUNC(hw_power_battery_int_chargelevel)
    507 {
    508 	struct tctrl_req req;
    509 
    510 	READ_ONLY;
    511 	READ_REQ(0x7a, 1, 3);
    512 	table[num].value = req.rspbuf[0] == 0xfb ? 0 : req.rspbuf[0];
    513 	return(1);
    514 
    515 }
    516 
    517 /* ARGSUSED */
    518 FUNC(hw_power_battery_ext_chargelevel)
    519 {
    520 	struct tctrl_req req;
    521 
    522 	READ_ONLY;
    523 	READ_REQ(0x7b, 1, 3);
    524 	table[num].value = req.rspbuf[0] == 0xfb ? 0 : req.rspbuf[0];
    525 	return(1);
    526 }
    527 
    528 FUNC(hw_power_battery_int_chargerate)
    529 {
    530 	struct tctrl_req req;
    531 
    532 	READ_REQ(0x18, 1, 2);
    533 	table[num].value = req.rspbuf[0];
    534 	if (readflg)
    535 		return(1);
    536 	req.cmdbuf[1] = new < 255 ? new : 255;
    537 	WRITE_REQ(0x39, 2, 1);
    538 	READ_REQ(0x18, 1, 2);
    539 	table[num].value = req.rspbuf[0];
    540 	return(1);
    541 }
    542 
    543 FUNC(hw_power_battery_ext_chargerate)
    544 {
    545 	struct tctrl_req req;
    546 
    547 	READ_REQ(0x18, 1, 2);
    548 	table[num].value = req.rspbuf[0];
    549 	if (readflg)
    550 		return(1);
    551 	req.cmdbuf[1] = new < 255 ? new : 255;
    552 	WRITE_REQ(0x39, 2, 1);
    553 	READ_REQ(0x18, 1, 2);
    554 	table[num].value = req.rspbuf[0];
    555 	return(1);
    556 }
    557 
    558 /* ARGSUSED */
    559 FUNC(hw_power_battery_ext)
    560 {
    561 	int i;
    562 	struct tctrl_req req;
    563 
    564 	READ_ONLY;
    565 	READ_REQ(0x11, 1, 3);
    566 	i = (req.rspbuf[0]<<8) + req.rspbuf[1];
    567 	table[num].value = i&0x0004 ? 1 : 0;
    568 	return(1);
    569 }
    570 
    571 /* ARGSUSED */
    572 FUNC(hw_power_battery_int)
    573 {
    574 	int i;
    575 	struct tctrl_req req;
    576 
    577 	READ_ONLY;
    578 	READ_REQ(0x11, 1, 3);
    579 	i = (req.rspbuf[0]<<8) + req.rspbuf[1];
    580 	table[num].value = i&0x0002 ? 1 : 0;
    581 	return(1);
    582 }
    583 
    584 /* ARGSUSED */
    585 FUNC(hw_power_mains)
    586 {
    587 	int i;
    588 	struct tctrl_req req;
    589 
    590 	READ_ONLY;
    591 	READ_REQ(0x11, 1, 3);
    592 	i = (req.rspbuf[0]<<8) + req.rspbuf[1];
    593 	table[num].value = i&0x0001 ? 1 : 0;
    594 	return(1);
    595 }
    596 
    597 /* ARGSUSED */
    598 FUNC(hw_poweroncycles)
    599 {
    600 	struct tctrl_req req;
    601 
    602 	READ_ONLY;
    603 	READ_REQ(0x09, 1, 5);
    604 	table[num].value = (req.rspbuf[0]<<24)+(req.rspbuf[1]<<16)+
    605 	    (req.rspbuf[2]<<8)+req.rspbuf[3];
    606 	return(1);
    607 }
    608 
    609 /* ARGSUSED */
    610 FUNC(hw_poweronseconds)
    611 {
    612 	struct tctrl_req req;
    613 
    614 	READ_ONLY;
    615 	READ_REQ(0x0a, 1, 5);
    616 	table[num].value = (req.rspbuf[0]<<24)+(req.rspbuf[1]<<16)+
    617 	    (req.rspbuf[2]<<8)+req.rspbuf[3];
    618 	return(1);
    619 }
    620 
    621 /* ARGSUSED */
    622 FUNC(hw_microcontroller_version)
    623 {
    624 	char buf[BUFSIZ];
    625 	struct tctrl_req req;
    626 
    627 	READ_ONLY;
    628 	READ_REQ(0x04, 1, 3);
    629 	snprintf(buf, sizeof(buf), "%d%d", req.rspbuf[0]*1000,
    630 	    req.rspbuf[1]*10);
    631 	table[num].value = atoi(strdup(buf));
    632 	return(1);
    633 }
    634 
    635 
    636 /* ARGSUSED */
    637 FUNC(hw_version)
    638 {
    639 	char buf[BUFSIZ];
    640 	struct tctrl_req req;
    641 
    642 	READ_ONLY;
    643 	READ_REQ(0x03, 1, 3);
    644 	snprintf(buf, sizeof(buf), "%d%d", req.rspbuf[0]*1000,
    645 	    req.rspbuf[1]*10);
    646 	table[num].value = atoi(strdup(buf));
    647 	return(1);
    648 }
    649 
    650 FUNC(hw_serial_power)
    651 {
    652 	struct tctrl_pwr pwrreq;
    653 
    654 	if (!readflg) {
    655 		pwrreq.rw = 0x00;
    656 		pwrreq.state = new;
    657 		ioctl(dev, TCTRL_SERIAL_PWR, &pwrreq);
    658 	}
    659 	pwrreq.rw = 0x01;
    660 	ioctl(dev, TCTRL_SERIAL_PWR, &pwrreq);
    661 	table[num].value = pwrreq.state;
    662 	return(1);
    663 }
    664 
    665 static void
    666 usage(void)
    667 {
    668 	(void)fprintf(stderr,
    669 	    "usage: tadpolectl [-n] name ...\n"
    670 	    "       tadpolectl [-n] -w name=value\n"
    671 	    "       tadpolectl [-n] -a\n");
    672 	exit(1);
    673 }
    674 
    675 static void
    676 parse(string)
    677 	char *string;
    678 {
    679 	char *cp, buf[BUFSIZ];
    680 	int newval = 0;
    681 	int i, j, ret;
    682 
    683 	string = dashdot(string);
    684 	snprintf(buf, (size_t)BUFSIZ, "%s", string);
    685 	if ((cp = strchr(string, '=')) != NULL) {
    686 		if (!wflag)
    687 			errx(2, "Must specify -w to set variables");
    688 		*strchr(buf, '=') = '\0';
    689 		*cp++ = '\0';
    690 		while (isspace((unsigned char) *cp))
    691 			cp++;
    692 		newval = atoi(cp);
    693 	}
    694 	for (j=0,i=-1; j < NUM_MIBS; j++) {
    695 		if (strcmp(string, table[j].mib) == 0) {
    696 			i = j;
    697 			break;
    698 		}
    699 	}
    700 	if (i == -1)
    701 		errx(2, "Named value does not exist");
    702 
    703 	if (wflag) {
    704 		ret = (*table[i].funcptr)(0, newval, i);
    705 		if (!ret)
    706 			errx(2, "Cannot modify this value");
    707 	} else
    708 		ret = (*table[i].funcptr)(1, 0, i);
    709 	if (nflag)
    710 		printf("%d\n", table[i].value);
    711 	else
    712 		printf("%s = %d\n", dashdot(table[i].mib), table[i].value);
    713 }
    714 
    715 char *
    716 dashdot(const char *string)
    717 {
    718 	char *p;
    719 	char *save;
    720 
    721 	p = strdup(string);
    722 	save = p;
    723 
    724 	for (; (*p = *string) != '\0'; ++p, ++string) {
    725 		if (*p == '.')
    726 			*p = '_';
    727 		else if (*p == '_')
    728 			*p = '.';
    729 	}
    730 	return(save);
    731 }
    732 
    733 int
    734 main(int argc, char *argv[])
    735 {
    736 	int ch, j;
    737 
    738 	while ((ch = getopt(argc, argv, "anw")) != -1) {
    739 		switch (ch) {
    740 
    741 		case 'a':
    742 			aflag = 1;
    743 			break;
    744 		case 'n':
    745 			nflag = 1;
    746 			break;
    747 		case 'w':
    748 			wflag = 1;
    749 			break;
    750 		default:
    751 			usage();
    752 		}
    753 	}
    754 	argc -= optind;
    755 	argv += optind;
    756 
    757 	if ((dev = open(TCTRL_DEV, O_RDONLY, NULL)) == -1)
    758 		err(1, "%s", TCTRL_DEV);
    759 
    760 	if (aflag) {
    761 		for (j=0; j < NUM_MIBS; j++) {
    762 			(void)(*table[j].funcptr)(1, 0, j);
    763 			if (nflag)
    764 				printf("%d\n", table[j].value);
    765 			else
    766 				printf("%s = %d\n", dashdot(table[j].mib),
    767 				    table[j].value);
    768 		}
    769 		return(0);
    770 	}
    771 	if (argc == 0)
    772 		usage();
    773 	while (argc-- > 0)
    774 		parse(*argv++);
    775 	return(0);
    776 }
    777