digitools/0000775000175000017500000000000010500060471012634 5ustar calkinacalkinadigitools/it8705.c0000644000175000017500000001066010463624520013752 0ustar calkinacalkina/* it8705.c - A user-space library to access the it8705 chip. Copyright (c) 2006 Andrew Calkin Copyright (c) 2005 Richard Taylor Heavily based on code for accessing/initializing it8712/it8705 written by (C) Copyright 2004 Wojtek Kaniewski This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include "digitools.h" #include "i2c-dev.h" #include "it8705.h" extern unsigned char addr; extern unsigned char data; unsigned char it87_read_byte(unsigned char addr) { outb(addr, IT87_ACCESS_REG); return inb(IT87_RETURN_REG); } unsigned char it87_read_ec_byte(unsigned char addr) { outb(addr, IT8705_EC_ACCESS_REG); return inb(IT8705_EC_RETURN_REG); } int it87_write_ec_byte (unsigned char addr, unsigned char data) { outb(addr, IT8705_EC_ACCESS_REG); outb(data, IT8705_EC_RETURN_REG); if (it87_read_ec_byte(addr) != data) { #ifndef SILENT printf("Error Writing EC addr: 0x%02X, wrote: 0x%02X, read: 0x%02X\n", addr, data, it87_read_ec_byte(addr)); #endif return -1; } return 0; } int it87_write_byte (unsigned char addr, unsigned char data) { outb(addr, IT87_ACCESS_REG); outb(data, IT87_RETURN_REG); if ((addr != IT8705_CFG_CTRL) && (it87_read_byte(addr) != data)) { #ifndef SILENT printf("Error Writing addr: 0x%02X, wrote: 0x%02X, read: 0x%02X\n", addr, data, it87_read_byte(addr)); #endif return -1; } return 0; } int it87_ec_port_open(void) { if (ioperm(IT8705_EC_ACCESS_REG, 2, 1) == -1) { #ifndef SILENT printf("Error getting access\n"); #endif exit(1); } else return 0; } void it87_ec_port_close(void) { ioperm(IT8705_EC_ACCESS_REG, 2, 0); } int it87_open(void) { if (ioperm(IT87_ACCESS_REG, 2, 1) == -1) { #ifndef SILENT printf("Error getting access!\n"); #endif exit(1); } outb(0x87, IT87_ACCESS_REG); outb(0x01, IT87_ACCESS_REG); outb(0x55, IT87_ACCESS_REG); outb(0x55, IT87_ACCESS_REG); if (it87_read_byte(0x20) != 0x87 || it87_read_byte(0x21) != 0x05) { #ifndef SILENT printf("IT8705 not found!\nIdent values are %02X%02X.\n" "Should be 8705\n",it87_read_byte(0x20), it87_read_byte(0x21)); #endif exit(1); } return 0; } void it87_close(void) { /* To exit pnp mode we need to set bit 1 of IT8705_CFG_CTRL bit 0 is the reset bit. This register is write only */ it87_write_byte(IT8705_CFG_CTRL, 0x02); ioperm(IT87_ACCESS_REG, 2, 0); } /* Note: Returns hexified version of temperature: Temp = 34 DegC, return will be 0x34 On error, returns 0 to fail gracefully */ char it87_get_temp(void) { int temp; char temp_dec = 0; /* Get the temperature from the IT87 */ temp=it87_read_ec_byte(IT8705_TEMP_REG1); temp &= 0xFF; temp_dec = ((temp / 10) << 4) & 0xf0; temp_dec |= (temp % 10) & 0x0f; return temp_dec; } void it87_ldn_set(unsigned char ldn) { outb(0x07,IT87_ACCESS_REG); outb(ldn,IT87_RETURN_REG); } unsigned char it87_read_cir_byte(unsigned char addr) { return inb(IT87_CIR_DEFAULT_IOBASE + addr); } int it87_write_cir_byte (unsigned char addr, unsigned char data) { outb(data, IT87_CIR_DEFAULT_IOBASE + addr); if (it87_read_cir_byte(addr) != data) { #ifndef SILENT printf("Error Writing CIR addr: 0x%02X, wrote: 0x%02X, read: 0x%02X\n", addr, data, it87_read_cir_byte(addr)); #endif return -1; } return 0; } int it87_cir_port_open(void) { if (ioperm(IT87_CIR_DEFAULT_IOBASE, 10, 1) == -1) { #ifndef SILENT printf("Error getting access!\n"); #endif exit(1); } else return 0; } void it87_cir_port_close(void) { ioperm(IT87_CIR_DEFAULT_IOBASE, 10, 0); } digitools/i2c-dev.h0000664000175000017500000003007110413531142014240 0ustar calkinacalkina/* i2c-dev.h - i2c-bus driver, char device interface Copyright (C) 1995-97 Simon G. Vogl Copyright (C) 1998-99 Frodo Looijaard This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* $Id: i2c-dev.h,v 1.7 2003/01/21 20:01:26 kmalkki Exp $ */ #ifndef LIB_I2CDEV_H #define LIB_I2CDEV_H #include #include /* -- i2c.h -- */ /* * I2C Message - used for pure i2c transaction, also from /dev interface */ struct i2c_msg { __u16 addr; /* slave address */ unsigned short flags; #define I2C_M_TEN 0x10 /* we have a ten bit chip address */ #define I2C_M_RD 0x01 #define I2C_M_NOSTART 0x4000 #define I2C_M_REV_DIR_ADDR 0x2000 #define I2C_M_IGNORE_NAK 0x1000 #define I2C_M_NO_RD_ACK 0x0800 short len; /* msg length */ char *buf; /* pointer to msg data */ int err; short done; }; /* To determine what functionality is present */ #define I2C_FUNC_I2C 0x00000001 #define I2C_FUNC_10BIT_ADDR 0x00000002 #define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART,..} */ #define I2C_FUNC_SMBUS_HWPEC_CALC 0x00000008 /* SMBus 2.0 */ #define I2C_FUNC_SMBUS_READ_WORD_DATA_PEC 0x00000800 /* SMBus 2.0 */ #define I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC 0x00001000 /* SMBus 2.0 */ #define I2C_FUNC_SMBUS_PROC_CALL_PEC 0x00002000 /* SMBus 2.0 */ #define I2C_FUNC_SMBUS_BLOCK_PROC_CALL_PEC 0x00004000 /* SMBus 2.0 */ #define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */ #define I2C_FUNC_SMBUS_QUICK 0x00010000 #define I2C_FUNC_SMBUS_READ_BYTE 0x00020000 #define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000 #define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000 #define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000 #define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000 #define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000 #define I2C_FUNC_SMBUS_PROC_CALL 0x00800000 #define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000 #define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000 #define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */ #define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */ #define I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 0x10000000 /* I2C-like block xfer */ #define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2 0x20000000 /* w/ 2-byte reg. addr. */ #define I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC 0x40000000 /* SMBus 2.0 */ #define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC 0x80000000 /* SMBus 2.0 */ #define I2C_FUNC_SMBUS_BYTE I2C_FUNC_SMBUS_READ_BYTE | \ I2C_FUNC_SMBUS_WRITE_BYTE #define I2C_FUNC_SMBUS_BYTE_DATA I2C_FUNC_SMBUS_READ_BYTE_DATA | \ I2C_FUNC_SMBUS_WRITE_BYTE_DATA #define I2C_FUNC_SMBUS_WORD_DATA I2C_FUNC_SMBUS_READ_WORD_DATA | \ I2C_FUNC_SMBUS_WRITE_WORD_DATA #define I2C_FUNC_SMBUS_BLOCK_DATA I2C_FUNC_SMBUS_READ_BLOCK_DATA | \ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA #define I2C_FUNC_SMBUS_I2C_BLOCK I2C_FUNC_SMBUS_READ_I2C_BLOCK | \ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK #define I2C_FUNC_SMBUS_I2C_BLOCK_2 I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 | \ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2 #define I2C_FUNC_SMBUS_BLOCK_DATA_PEC I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC | \ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC #define I2C_FUNC_SMBUS_WORD_DATA_PEC I2C_FUNC_SMBUS_READ_WORD_DATA_PEC | \ I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC #define I2C_FUNC_SMBUS_READ_BYTE_PEC I2C_FUNC_SMBUS_READ_BYTE_DATA #define I2C_FUNC_SMBUS_WRITE_BYTE_PEC I2C_FUNC_SMBUS_WRITE_BYTE_DATA #define I2C_FUNC_SMBUS_READ_BYTE_DATA_PEC I2C_FUNC_SMBUS_READ_WORD_DATA #define I2C_FUNC_SMBUS_WRITE_BYTE_DATA_PEC I2C_FUNC_SMBUS_WRITE_WORD_DATA #define I2C_FUNC_SMBUS_BYTE_PEC I2C_FUNC_SMBUS_BYTE_DATA #define I2C_FUNC_SMBUS_BYTE_DATA_PEC I2C_FUNC_SMBUS_WORD_DATA #define I2C_FUNC_SMBUS_EMUL I2C_FUNC_SMBUS_QUICK | \ I2C_FUNC_SMBUS_BYTE | \ I2C_FUNC_SMBUS_BYTE_DATA | \ I2C_FUNC_SMBUS_WORD_DATA | \ I2C_FUNC_SMBUS_PROC_CALL | \ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC | \ I2C_FUNC_SMBUS_I2C_BLOCK /* * Data for SMBus Messages */ #define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */ #define I2C_SMBUS_I2C_BLOCK_MAX 32 /* Not specified but we use same structure */ union i2c_smbus_data { __u8 byte; __u16 word; __u8 block[I2C_SMBUS_BLOCK_MAX + 3]; /* block[0] is used for length */ /* one more for read length in block process call */ /* and one more for PEC */ }; /* smbus_access read or write markers */ #define I2C_SMBUS_READ 1 #define I2C_SMBUS_WRITE 0 /* SMBus transaction types (size parameter in the above functions) Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */ #define I2C_SMBUS_QUICK 0 #define I2C_SMBUS_BYTE 1 #define I2C_SMBUS_BYTE_DATA 2 #define I2C_SMBUS_WORD_DATA 3 #define I2C_SMBUS_PROC_CALL 4 #define I2C_SMBUS_BLOCK_DATA 5 #define I2C_SMBUS_I2C_BLOCK_DATA 6 #define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */ #define I2C_SMBUS_BLOCK_DATA_PEC 8 /* SMBus 2.0 */ #define I2C_SMBUS_PROC_CALL_PEC 9 /* SMBus 2.0 */ #define I2C_SMBUS_BLOCK_PROC_CALL_PEC 10 /* SMBus 2.0 */ #define I2C_SMBUS_WORD_DATA_PEC 11 /* SMBus 2.0 */ /* ----- commands for the ioctl like i2c_command call: * note that additional calls are defined in the algorithm and hw * dependent layers - these can be listed here, or see the * corresponding header files. */ /* -> bit-adapter specific ioctls */ #define I2C_RETRIES 0x0701 /* number of times a device address */ /* should be polled when not */ /* acknowledging */ #define I2C_TIMEOUT 0x0702 /* set timeout - call with int */ /* this is for i2c-dev.c */ #define I2C_SLAVE 0x0703 /* Change slave address */ /* Attn.: Slave address is 7 or 10 bits */ #define I2C_SLAVE_FORCE 0x0706 /* Change slave address */ /* Attn.: Slave address is 7 or 10 bits */ /* This changes the address, even if it */ /* is already taken! */ #define I2C_TENBIT 0x0704 /* 0 for 7 bit addrs, != 0 for 10 bit */ #define I2C_FUNCS 0x0705 /* Get the adapter functionality */ #define I2C_RDWR 0x0707 /* Combined R/W transfer (one stop only)*/ #define I2C_PEC 0x0708 /* != 0 for SMBus PEC */ #if 0 #define I2C_ACK_TEST 0x0710 /* See if a slave is at a specific address */ #endif #define I2C_SMBUS 0x0720 /* SMBus-level access */ /* -- i2c.h -- */ /* Note: 10-bit addresses are NOT supported! */ /* This is the structure as used in the I2C_SMBUS ioctl call */ struct i2c_smbus_ioctl_data { char read_write; __u8 command; int size; union i2c_smbus_data *data; }; /* This is the structure as used in the I2C_RDWR ioctl call */ struct i2c_rdwr_ioctl_data { struct i2c_msg *msgs; /* pointers to i2c_msgs */ int nmsgs; /* number of i2c_msgs */ }; static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command, int size, union i2c_smbus_data *data) { struct i2c_smbus_ioctl_data args; args.read_write = read_write; args.command = command; args.size = size; args.data = data; return ioctl(file,I2C_SMBUS,&args); } static inline __s32 i2c_smbus_write_quick(int file, __u8 value) { return i2c_smbus_access(file,value,0,I2C_SMBUS_QUICK,NULL); } static inline __s32 i2c_smbus_read_byte(int file) { union i2c_smbus_data data; if (i2c_smbus_access(file,I2C_SMBUS_READ,0,I2C_SMBUS_BYTE,&data)) return -1; else return 0x0FF & data.byte; } static inline __s32 i2c_smbus_write_byte(int file, __u8 value) { return i2c_smbus_access(file,I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,NULL); } static inline __s32 i2c_smbus_read_byte_data(int file, __u8 command) { union i2c_smbus_data data; if (i2c_smbus_access(file,I2C_SMBUS_READ,command, I2C_SMBUS_BYTE_DATA,&data)) return -1; else return 0x0FF & data.byte; } static inline __s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value) { union i2c_smbus_data data; data.byte = value; return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, I2C_SMBUS_BYTE_DATA, &data); } static inline __s32 i2c_smbus_read_word_data(int file, __u8 command) { union i2c_smbus_data data; if (i2c_smbus_access(file,I2C_SMBUS_READ,command, I2C_SMBUS_WORD_DATA,&data)) return -1; else return 0x0FFFF & data.word; } static inline __s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value) { union i2c_smbus_data data; data.word = value; return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, I2C_SMBUS_WORD_DATA, &data); } static inline __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value) { union i2c_smbus_data data; data.word = value; if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command, I2C_SMBUS_PROC_CALL,&data)) return -1; else return 0x0FFFF & data.word; } /* Returns the number of read bytes */ static inline __s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values) { union i2c_smbus_data data; int i; if (i2c_smbus_access(file,I2C_SMBUS_READ,command, I2C_SMBUS_BLOCK_DATA,&data)) return -1; else { for (i = 1; i <= data.block[0]; i++) values[i-1] = data.block[i]; return data.block[0]; } } static inline __s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length, __u8 *values) { union i2c_smbus_data data; int i; if (length > 32) length = 32; for (i = 1; i <= length; i++) data.block[i] = values[i-1]; data.block[0] = length; return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, I2C_SMBUS_BLOCK_DATA, &data); } /* Returns the number of read bytes */ static inline __s32 i2c_smbus_read_i2c_block_data(int file, __u8 command, __u8 *values) { union i2c_smbus_data data; int i; if (i2c_smbus_access(file,I2C_SMBUS_READ,command, I2C_SMBUS_I2C_BLOCK_DATA,&data)) return -1; else { for (i = 1; i <= data.block[0]; i++) values[i-1] = data.block[i]; return data.block[0]; } } static inline __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command, __u8 length, __u8 *values) { union i2c_smbus_data data; int i; if (length > 32) length = 32; for (i = 1; i <= length; i++) data.block[i] = values[i-1]; data.block[0] = length; return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, I2C_SMBUS_I2C_BLOCK_DATA, &data); } /* Returns the number of read bytes */ static inline __s32 i2c_smbus_block_process_call(int file, __u8 command, __u8 length, __u8 *values) { union i2c_smbus_data data; int i; if (length > 32) length = 32; for (i = 1; i <= length; i++) data.block[i] = values[i-1]; data.block[0] = length; if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command, I2C_SMBUS_BLOCK_PROC_CALL,&data)) return -1; else { for (i = 1; i <= data.block[0]; i++) values[i-1] = data.block[i]; return data.block[0]; } } #endif /* LIB_I2CDEV_H */ digitools/sndctrl.h0000664000175000017500000000167510413531142014470 0ustar calkinacalkina/* sndctrl.h - A simple user-space program to access an ALSA mixer device. Copyright (c) 2005 Andrew Calkin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ int getvolume(long *vol); int setvolume(long newvol); int getvolrange(long *vmin, long *vmax); digitools/digifan.h0000664000175000017500000000265010414703014014412 0ustar calkinacalkina/* digifan.h - Fan control program for the ASUS Digimatrix. * * (C) Copyright 2006 Andrew Calkin * (C) Copyright 2004 Richard Taylor * * based on code for accessing/initializing it8712/it8705 written by * * (C) Copyright 2004 Wojtek Kaniewski * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License Version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define FAN_OFF 1 #define FAN_AUTO 2 #define FAN_INTELLIGENT 3 #define AUTO 0x80 #define FAN_MAX_PWM 0x7f #define OFF 0x5 /* Not completely off, but very low speed (safety) */ #define FAN_DEFAULT_MIN 30 #define FAN_DEFAULT_GRADIENT 4 #define FAN_DEFAULT_OFFSET 30 int digifan_main(int argc, char **argv); digitools/AUTHORS0000644000175000017500000000015010463614232013706 0ustar calkinacalkinaRichard Taylor Andrew Calkin Ben Potter digitools/digiwake.c0000644000175000017500000001131510463614232014573 0ustar calkinacalkina/* digiwake.c - Program to set IT87 registers to allow Wake-on-CIR * (consumer infra-red remote) for the ASUS Digimatrix * * (C) Copyright 2006 Ben Potter * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License Version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include #include "digiwake.h" #include "it8705.h" #include "digitools.h" static struct option digiwake_longopts[] = { { "read", 0, 0, 'r' }, { "write", 0, 0, 'w' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { NULL, 0, 0, 0 } }; static void digiwake_help(char *argv0) { #ifndef SILENT printf( "\n" "Usage: %s [OPTIONS]\n" "\n" " WARNING: If you are using this on a system other than the ASUS\n" " DigiMatrix, then there is a chance that you may cause damage.\n" " This program needs to be run as root.\n" "\n" " -r, --read Attempts to read keycode.\n" " -w, --write Attempts to write keycode.\n" " -v, --version Print version number.\n" " -h, --help Display this help message.\n" "\n", argv0); #endif } int digiwake_main(int argc, char **argv) { /* unsigned char writeData[10] = {0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x30, 0xcf}; */ int i = 0; int ch = 0; int longindex = 0; BOOL b_read = FALSE; BOOL b_write = FALSE; if ( (int)getuid() != 0) { #ifndef SILENT fprintf(stderr,"Must be root to run this program!\n"); #endif return -1; } if (argc == 1) { #ifndef SILENT printf("\nPlease supply some parameters.\n" "Use %s -h for list.\n\n", argv[0]); #endif return 1; } /* Parse input params */ for (;;) { if ((ch = getopt_long(argc, argv, "rwvh", digiwake_longopts, &longindex)) == -1) break; switch (ch) { case 'r': b_read = TRUE; break; case 'w': b_write = TRUE; break; case 'v': #ifndef SILENT printf("ASUS DigiMatrix Wake-On-CIR, from DigiTools " "Version %s\n", DIGI_VER); #endif break; case 'h': default: digiwake_help(argv[0]); return 0; break; } } if(b_read) { it87_open(); it87_ldn_set(IT8705_PME_LDN); printf("Read Data: "); for (i=0; i<18; i++) { it87_write_byte(PME_INDX_REG,BASE_ADDR+i); printf("0x%02X ",it87_read_byte(PME_DATA_REG)); } printf("\n"); it87_ldn_set(IT8705_CIR_LDN); /* Switch to CIR */ (void)it87_cir_port_open(); printf("CIR-DR: 0x%02X\n",it87_read_cir_byte(IT87_CIR_DR)); printf("CIR-IER: 0x%02X\n",it87_read_cir_byte(IT87_CIR_IER)); printf("CIR-RCR: 0x%02X\n",it87_read_cir_byte(IT87_CIR_RCR)); printf("CIR-TCR1: 0x%02X\n",it87_read_cir_byte(IT87_CIR_TCR1)); printf("CIR-TCR2: 0x%02X\n",it87_read_cir_byte(IT87_CIR_TCR2)); printf("CIR-TSR: 0x%02X\n",it87_read_cir_byte(IT87_CIR_TSR)); printf("CIR-RSR: 0x%02X\n",it87_read_cir_byte(IT87_CIR_RSR)); printf("CIR-BDLR: 0x%02X\n",it87_read_cir_byte(IT87_CIR_BDLR)); printf("CIR-BDHR: 0x%02X\n",it87_read_cir_byte(IT87_CIR_BDHR)); printf("CIR-IIR: 0x%02X\n",it87_read_cir_byte(IT87_CIR_IIR)); it87_cir_port_close(); it87_close(); } if(b_write) { it87_open(); it87_ldn_set(IT8705_PME_LDN); /* for (i=0; i<10; i++) { it87_write_byte(PME_INDX_REG,BASE_ADDR+i); it87_write_byte(PME_DATA_REG,writeData[(int)i]); } it87_write_byte(PME_ENABLE,0x1); */ it87_ldn_set(IT8705_CIR_LDN); /* Switch to CIR */ (void)it87_cir_port_open(); it87_write_cir_byte(IT87_CIR_IER,0x1C); /* Allow us to reset baudrate */ it87_write_cir_byte(IT87_CIR_BDHR,0x0); /* Baudrate */ it87_write_cir_byte(IT87_CIR_BDLR,0x45); /* Baudrate */ it87_write_cir_byte(IT87_CIR_IER,0x0C); /* Prevent change of baudrate */ it87_cir_port_close(); it87_close(); } #ifndef SILENT printf("Program exiting...\n\n"); #endif return 0; } digitools/digitools.h0000644000175000017500000000246310500060362015004 0ustar calkinacalkina/* digitools.h - A user-space program to handle the ASUS DigiMatrix special capabilities. Copyright (c) 2006 Andrew Calkin and Ben Potter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define DIGI_VER "1.03" #ifndef FALSE typedef enum _bool { FALSE=0, TRUE } BOOL; #endif void daemon_kill(void); void daemon_init(void); int digifan_main(int argc, char **argv); int digiradio_main(int argc, char **argv); int digipanel_main(int argc, char **argv); int digifan_main(int argc, char **argv); int digiwake_main(int argc, char **argv); int ozedit_main(int argc, char **argv); digitools/digipanel.c0000644000175000017500000003042610463614232014747 0ustar calkinacalkina/* digipanel.c - A user-space program to write to the ASUS DigiMatrix front panel. Copyright (c) 2005 Richard Taylor 2006 Andrew Calkin and Ben Potter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include "digitools.h" #include "i2c-dev.h" #include "it8705.h" #include "oz263.h" #include "digipanel.h" #include "sndctrl.h" static struct option digipanel_longopts[] = { { "display", 1, 0, 'd' }, { "reinit", 1, 0, 'D' }, { "temp", 0, 0, 't' }, { "volume", 0, 0, 'l' }, { "time", 0, 0, 's' }, { "kill", 0, 0, 'k' }, { "version", 0, 0, 'v' }, { "help", 0, 0, 'h' }, { NULL, 0, 0, 0 } }; static struct option digiradio_longopts[] = { { "radio", 0, 0, 'r' }, { "control", 1, 0, 'c' }, { "version", 0, 0, 'v' }, { "help", 0, 0, 'h' }, { NULL, 0, 0, 0 } }; static void digipanel_help(char *argv0) { #ifndef SILENT printf( "\n" "Usage: %s [OPTIONS]\n" "\n" " WARNING: If you are using this on a system other than the ASUS\n" " DigiMatrix, then there is a chance that you may destroy an EEPROM.\n" " This program needs to be run as root.\n" "\n" " -s, --time Display the local time.\n" " -t, --temp Display the temperature.\n" " -l, --volume Display (any changes of) the volume control.\n" " -k, --kill Stop the daemon (if running) and exit.\n" "\n" " -d, --display [\"xxxxxx\"] Set the display to the numbers specified.\n" " -D, --reinit [\"xxxxxx\"] As above, but re-initilises the display first.\n" "\n" " -v, --version Print version number.\n" " -h, --help Display this help message.\n" "\n", argv0); #endif } static void digiradio_help(char *argv0) { #ifndef SILENT printf( "\n" "Usage: %s [OPTIONS]\n" "\n" " WARNING: If you are using this on a system other than the ASUS\n" " DigiMatrix, then there is a chance that you may destroy an EEPROM.\n" " This program needs to be run as root.\n" "\n" " -r, --radio [am | fm | off] Set the radio to am, fm or off.\n" " -c, --control [seek-|seek+|fine-|fine+|ch-|ch+|prog|cancel|store]\n" " Control the radio, where:\n" " seek+/- seeks to the next station\n" " fine+/- manually increases / decreases frequency\n" " ch+/- selects a stored presets\n" " prog begins storing the current frequency\n" " (use ch+/- to choose preset location)\n" " cancel aborts the store\n" " store commits the frequency to the flashing preset\n" "\n" " -v, --version Print version number.\n" " -h, --help Display this help message.\n" "\n", argv0); #endif } int digipanel_main(int argc, char *argv[]) { extern char digits[7]; extern int file; int ch, longindex = 0; BOOL b_update_temp = FALSE; BOOL b_update_time = FALSE; BOOL b_update_volume = FALSE; extern LED led; extern PP pp; extern DOTS dots; time_t current_time; struct tm *time_date; /* default displays are set to ' ' and ' ' respectively */ char ascii_time[5] = {0x0f, 0x0f, 0x0f, 0x0f,'\0'}; char current_temp[3] = {0x0f, 0x0f,'\0'}; char volume; long vol_current; long vol_min, vol_max; getvolrange(&vol_min, &vol_max); int vol_step=1; if ( (int)getuid() != 0) { #ifndef SILENT fprintf(stderr,"Must be root to run this program!\n"); #endif return -1; } if (argc == 1) { #ifndef SILENT printf("\nPlease supply some parameters.\n" "Use %s -h for list.\n\n", argv[0]); #endif return 1; } /* Parse input params */ for (;;) { if ((ch = getopt_long(argc, argv, "d:D:tlskvh", digipanel_longopts, &longindex)) == -1) break; switch (ch) { case 'd': case 'D': if (!file) file=oz263_I2C_init(); strncpy(digits, optarg, 6); digits[6]='\0'; #ifndef SILENT printf("Args = %s\n", optarg); printf("Setting display to: %s", digits); #endif if (strstr(optarg, " play")) { pp = PP_PLAY; #ifndef SILENT printf(" play"); #endif } else if (strstr(optarg, " pause")) { pp = PP_PAUSE; #ifndef SILENT printf(" pause"); #endif } if (strstr(optarg, " am")) { led = LED_AM; #ifndef SILENT printf(" am"); #endif } else if (strstr(optarg, " fm")) { led = LED_FM; #ifndef SILENT printf(" fm"); #endif } else if (strstr(optarg, " cd")) { led = LED_CD; #ifndef SILENT printf(" cd"); #endif } else if (strstr(optarg, " hd")) { led = LED_HD; #ifndef SILENT printf(" hd"); #endif } if (strstr(optarg, "both")) { dots = DOTS_BOTH; #ifndef SILENT printf(" :"); #endif } else if (strstr(optarg, "middle")) { dots = DOTS_MIDDLE; #ifndef SILENT printf(" -"); #endif } else if (strstr(optarg, "bottom")) { dots = DOTS_BOTTOM; #ifndef SILENT printf(" ."); #endif } printf("\n"); if (ch == 'D') oz263_display(file, digits, led, pp, dots, (BOOL)1); else oz263_display(file, digits, led, pp, dots, (BOOL)0); break; case 't': it87_open(); (void)it87_ec_port_open(); b_update_temp = TRUE; break; case 'l': b_update_volume = TRUE; break; case 's': b_update_time = TRUE; break; case 'v': #ifndef SILENT printf("ASUS DigiMatrix Panel Control, from DigiTools " "Version %s\n", DIGI_VER); #endif break; case 'k': #ifndef SILENT printf("Stopping the %s daemon\n",argv[0]); #endif daemon_kill(); exit(0); case 'h': digipanel_help(argv[0]); return 0; break; default: digipanel_help(argv[0]); return 0; break; } } if (b_update_temp || b_update_time || b_update_volume) { if (!file) file=oz263_I2C_init(); daemon_kill(); /* Attempt to enter daemon mode, return control to terminal */ daemon_init(); } else exit(0); /* Begin daemon loop */ unsigned int temp_counter = 0; while (1) { if (temp_counter >= (TEMP_UPDATE_INTERVAL_MS / VOL_UPDATE_INTERVAL_MS)) { temp_counter = 0; if (b_update_temp) sprintf(current_temp, "%02X", it87_get_temp()); if (b_update_time) { /* Make the dots flash */ if (dots == DOTS_NONE) dots = DOTS_BOTH; else dots = DOTS_NONE; time(¤t_time); time_date = localtime(¤t_time); strftime(ascii_time, 5, "%H%M", time_date); } if (b_update_time || b_update_temp) { sprintf(digits, "%s%s", current_temp, ascii_time); oz263_display(file, digits, led, pp, dots, (BOOL)0); } } if (b_update_volume) { oz263_write_byte(file, 0x24); volume = oz263_read_byte(file); if (volume != -120 && volume != 0) { /* Set delay time to hold display */ for (temp_counter=12; temp_counter > 0; temp_counter--) { getvolume(&vol_current); if (volume > 0) /*use vol_max-1 so never 100 (3digits)*/ { if (vol_current+vol_step < vol_max-1) vol_current=vol_current+vol_step; else vol_current=vol_max-1; } if (volume < 0) { if (vol_current-vol_step > vol_min) vol_current=vol_current-vol_step; else vol_current=vol_min; } setvolume(vol_current); dots = DOTS_NONE; sprintf(digits, "%02ld ", (100*(vol_current-vol_min))/(vol_max-vol_min)); oz263_display(file, digits, led, pp, dots, (BOOL)0); usleep(VOL_UPDATE_INTERVAL_MS * 1000); /* Delay of 500ms*/ oz263_write_byte(file, 0x24); volume = oz263_read_byte(file); } } } usleep(VOL_UPDATE_INTERVAL_MS * 1000); /* Delay of 500ms*/ temp_counter++; } } int digiradio_main(int argc, char *argv[]) { int file=0; int ch, longindex = 0; if ( (int)getuid() != 0) { #ifndef SILENT fprintf(stderr,"Must be root to run this program!\n"); #endif return -1; } if (argc == 1) { #ifndef SILENT printf("\nPlease supply some parameters.\n" "Use %s -h for list.\n\n", argv[0]); #endif return 1; } /* Parse input params */ for (;;) { if ((ch = getopt_long(argc, argv, "r:c:vh", digiradio_longopts, &longindex)) == -1) break; switch (ch) { case 'r': if (!file) file=oz263_I2C_init(); #ifndef SILENT printf("Setting radio "); #endif if (!strcmp(optarg, "fm")) { #ifndef SILENT printf("ON - FM\n"); #endif oz263_radio_mode(file, FM_RADIO); } else if (!strcmp(optarg, "am")) { #ifndef SILENT printf("ON - AM\n"); #endif oz263_radio_mode(file, AM_RADIO); } else { #ifndef SILENT printf("OFF \n"); #endif oz263_radio_mode(file, OFF_MODE); } break; case 'c': if (!file) file=oz263_I2C_init(); #ifndef SILENT printf("Controlling radio: "); #endif if (!strcmp(optarg, "seek-")) { #ifndef SILENT printf("Seeking down\n"); #endif oz263_radio_control(file, SEEK_DOWN); } else if (!strcmp(optarg, "seek+")) { #ifndef SILENT printf("Seeking up\n"); #endif oz263_radio_control(file, SEEK_UP); } else if (!strcmp(optarg, "fine-")) { #ifndef SILENT printf("Fine tuning down\n"); #endif oz263_radio_control(file, FINE_TUNE_DOWN); } else if (!strcmp(optarg, "fine+")) { #ifndef SILENT printf("Fine tuning up\n"); #endif oz263_radio_control(file, FINE_TUNE_UP); } else if (!strcmp(optarg, "ch-")) { #ifndef SILENT printf("Previous preset\n"); #endif oz263_radio_control(file, CHANNEL_PREV); } else if (!strcmp(optarg, "ch+")) { #ifndef SILENT printf("Next preset\n"); #endif oz263_radio_control(file, CHANNEL_NEXT); } else if (!strcmp(optarg, "prog")) { #ifndef SILENT printf("Program preset - now select preset with ch+/-\n"); #endif oz263_radio_control(file, STORE_START); } else if (!strcmp(optarg, "cancel")) { #ifndef SILENT printf("Program store cancelled\n"); #endif oz263_radio_control(file, STORE_CANCEL); } else if (!strcmp(optarg, "store")) { #ifndef SILENT printf("Preset stored\n"); #endif oz263_radio_control(file, STORE_COMMIT); } break; case 'v': #ifndef SILENT printf("ASUS DigiMatrix Radio Control, from DigiTools " "Version %s\n", DIGI_VER); #endif break; case 'h': digiradio_help(argv[0]); return 0; break; default: digiradio_help(argv[0]); return 0; break; } } exit(0); } digitools/CHANGELOG0000644000175000017500000000066410463625025014064 0ustar calkinacalkina1.02: Code cleanup- Conform to stricter GCC warnings 1.01: Code cleanups- No RaNdOm capitalizations in variable names - Consistent "return value" as opposed to "return(value)" notation - New make target "dist" for creating .tar.gz and .tar.bz2 excluding .svn directory, for distribution. - Test daemon successfully killed, or else try more forcefully. 1.00: Initial release version. digitools/digiwake.h0000664000175000017500000000156010413531142014574 0ustar calkinacalkina/* digiwake.h - Program to set IT87 registers to allow Wake-on-CIR * (consumer infra-red remote) for the ASUS Digimatrix * * (C) Copyright 2006 Ben Potter * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License Version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ int digiwake_main(int argc, char **argv); digitools/oz263.h0000664000175000017500000000620310463624625013710 0ustar calkinacalkina/* oz263.h: Functions for accessing the oz263 chip. Also, find and return the SiS96x i2c bus device for the digimatrix setpanel program, for both 2.4 and 2.6 kernels. Copyright (c) 2005 Andrew Calkin and Ben Potter Based heavily on the codebase for the header given directly below, and the original setpanel.c code, written by Richard Taylor, Ben Potter and Cyril Lacoux. Original header: i2cbusses: Print the installed i2c busses for both 2.4 and 2.6 kernels. Part of user-space programs to access for I2C devices. Copyright (c) 1999-2003 Frodo Looijaard and Mark D. Studebaker This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Address on the I2C bus of the AudioDJ (OZ268) IC */ #define AUDIODJ_I2C_ADDRESS 0x49 typedef enum _control { SEEK_DOWN = 0, SEEK_UP, FINE_TUNE_DOWN, FINE_TUNE_UP, CHANNEL_PREV, CHANNEL_NEXT, STORE_START, STORE_CANCEL, STORE_COMMIT } CONTROL; typedef enum _radio_mode { OFF_MODE = 0, AM_RADIO, FM_RADIO, CD_MODE, HD_MODE } RADIO_MODE; /* Dots are in reg 0x06 0x00 = No Dots. 0x01 = middle dot 0x02 = bottom dot 0x03 = both dots */ typedef enum _dots { DOTS_NONE = 0, DOTS_MIDDLE, DOTS_BOTTOM, DOTS_BOTH } DOTS; /* First digit: 0x80 of 0x00 makes LED not light up for representative mode. All digits: 0x0f = blank 0x0e = 'C' (2nd Digit = 'D') CD MODE LED 0x0d = 'P' (2nd Digit = '-') HD MODE LED 0x0c = '-' (2nd Digit = 'M') Invalid MODE 0x0b = 'A' AM MODE LED 0x0a = 'F' FM MODE LED < 0x0a = Number.i */ typedef enum _leds { LED_NONE = 0x8f, LED_AM = 0x0b, LED_FM = 0x0a, LED_CD = 0x0e, LED_HD = 0x0d, } LED; /* Writing to Reg 0x07 does nothing, 0x08 = PLAY LED, 0x09 = PAUSE LED */ typedef enum _pp { PP_NONE = 0x07, PP_PLAY = 0x08, PP_PAUSE = 0x09 } PP; int find_i2c_sis96x(void); int oz263_write_byte_data(int file, char reg, char data); int oz263_write_byte(int file, char data); int oz263_read_byte(int file); void oz263_radio_control(int file, CONTROL control); void oz263_radio_mode(int file, RADIO_MODE radio_mode); void oz263_display(int file, char digits[6], LED led, PP pp, DOTS dots, BOOL reinit); int oz263_I2C_init(void); void print_error_msg(void); int sysfs_i2c_check(FILE *f); digitools/sndctrl.c0000644000175000017500000000565310463622255014474 0ustar calkinacalkina/* sndctrl.c - A simple user-space program to access an ALSA mixer device. Copyright (c) 2005 Andrew Calkin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include "sndctrl.h" int getvolume(long *vol) { snd_mixer_t *mixer; /* handle pointer for the mixer */ snd_mixer_selem_id_t *sid; /* stores simple id of control */ snd_mixer_elem_t *elem; /* used for master element */ snd_mixer_open(&mixer, 0); /* open up the mixer for card 0 */ snd_mixer_attach(mixer, "default" ); snd_mixer_selem_register(mixer, 0, 0 ); snd_mixer_load(mixer); snd_mixer_selem_id_alloca(&sid); /* gets address of control */ snd_mixer_selem_id_set_name(sid, "Master"); elem = snd_mixer_find_selem(mixer, sid); /* Only need one channel (left)- assume both the same */ snd_mixer_selem_get_playback_volume (elem, 0, vol); snd_mixer_close(mixer); return 0; } int setvolume(long newvol) { snd_mixer_t *mixer; /* handle pointer for the mixer */ snd_mixer_selem_id_t *sid; /* stores simple id of control */ snd_mixer_elem_t *elem; /* used for master element */ snd_mixer_open(&mixer, 0); /* open up the mixer for card 0 */ snd_mixer_attach(mixer, "default" ); snd_mixer_selem_register(mixer, 0, 0 ); snd_mixer_load(mixer); snd_mixer_selem_id_alloca(&sid); /* gets address of control */ snd_mixer_selem_id_set_name(sid, "Master"); elem = snd_mixer_find_selem(mixer, sid); /* left and then right channels */ snd_mixer_selem_set_playback_volume (elem, 0, newvol); snd_mixer_selem_set_playback_volume (elem, 1, newvol); snd_mixer_close(mixer); return 0; } int getvolrange(long *vmin, long *vmax) { snd_mixer_t *mixer; /* handle pointer for the mixer */ snd_mixer_selem_id_t *sid; /* stores simple id of control */ snd_mixer_elem_t *elem; /* used for master element */ snd_mixer_open(&mixer, 0); /* open up the mixer for card 0 */ snd_mixer_attach(mixer, "default" ); snd_mixer_selem_register(mixer, 0, 0 ); snd_mixer_load(mixer); snd_mixer_selem_id_alloca(&sid); /* gets address of control */ snd_mixer_selem_id_set_name(sid, "Master"); elem = snd_mixer_find_selem(mixer, sid); snd_mixer_selem_get_playback_volume_range (elem, vmin, vmax); snd_mixer_close(mixer); return 0; } digitools/digipanel.h0000644000175000017500000000377310463614232014761 0ustar calkinacalkina/* digipanel.h - A user-space program to write to the ASUS DigiMatrix front panel. Copyright (c) 2005 Richard Taylor This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Some info gathered about the registers: 00 - 1st Digit 01 - 2nd 02 - 3rd 03 - 4th 04 - 5th 05 - 6th 06 - Colon 1, 2, 3 (bottom, middle, both) 07 - Not sure... 08 - Show play symbol 09 - Show pause symbol 10 - 11 - HD Mode (HD Symbol) 12 - CD Mode (CD Symbol) 13 - FM Mode (FM + Radio on) 14 - AM Mode (AM + Radio on) 15 - Turns off Radio / Current mode? (Doesn't clear icon) 16 - Radio Next Preset 17 - Radio Prev Preset 18 - 19 - Radio Seek Up 21 - Store station (select number) 22 - Store station (cancel) 25 - Store station (store) 30 - Hour (Hex e.g. 0x23 = 11pm) 31 - Minute 33 - Reads back the value written... 34 - Displays temperature (hex value written). 35 - Go back to digit mode (resets to -- --:--) 36 - Volume control count (8-bit +/-) 37 - Radio: manual tune up (+0.5 MHz) 38 - Radio: manual tune down (-0.5 MHz) 39 - Radio: seek down 40 - 41 - Display time Don't go above 86 - the I2C bus freezes! */ /* Update intervals for temperature display and volume control in ms */ #define TEMP_UPDATE_INTERVAL_MS 500 #define VOL_UPDATE_INTERVAL_MS 150 int digipanel_main(int argc, char *argv[]); int digiradio_main(int argc, char *argv[]); digitools/Makefile0000644000175000017500000000444710500060261014300 0ustar calkinacalkina# Edit the line(s) below to change installation directory. PREFIX = $(DESTDIR)/usr/local SBINDIR = $(PREFIX)/sbin # Users should not need to edit anything below this line. LDFLAGS = -lasound CFLAGS = -Wall -Os LN = ln STRIP = strip TAR = tar VER = `sed -n "s/.*DIGI_VER.*\"\(.*\)\"/\1/p" digitools.h` BIN = digitools DIR = digitools SYMLINK_PANEL = digipanel SYMLINK_RADIO = digiradio SYMLINK_FAN = digifan SYMLINK_WAKE = digiwake SYMLINK_EDIT = ozedit SYMLINK_OLDPANEL = setpanel SYMLINK_OLDRADIO = setradio SYMLINK_OLDFAN = asusfan OBJS = ozedit.o digitools.o digiwake.o digifan.o it8705.o oz263.o digipanel.o sndctrl.o default: clean $(BIN) symlinks $(BIN): $(OBJS) .PHONY: strip strip: $(BIN) $(STRIP) $(BIN) .PHONY: symlinks symlinks: $(BIN) ln -s $(BIN) $(SYMLINK_PANEL) ln -s $(BIN) $(SYMLINK_RADIO) ln -s $(BIN) $(SYMLINK_FAN) ln -s $(BIN) $(SYMLINK_WAKE) ln -s $(BIN) $(SYMLINK_EDIT) .PHONY: oldsymlinks oldsymlinks: $(BIN) ln -s $(BIN) $(SYMLINK_OLDPANEL) ln -s $(BIN) $(SYMLINK_OLDRADIO) ln -s $(BIN) $(SYMLINK_OLDFAN) .PHONY: clean clean: rm -rf *.o *.tar.* $(BIN) $(SYMLINK_PANEL) $(SYMLINK_RADIO) \ $(SYMLINK_FAN) $(SYMLINK_WAKE) $(SYMLINK_EDIT) \ $(SYMLINK_OLDPANEL) $(SYMLINK_OLDRADIO) $(SYMLINK_OLDFAN) .PHONY: oldinstall oldinstall: $(BIN) install -d $(SBINDIR) install -m 755 $(BIN) $(SBINDIR) $(LN) -s $(BIN) $(SBINDIR)/$(SYMLINK_OLDPANEL) $(LN) -s $(BIN) $(SBINDIR)/$(SYMLINK_OLDFAN) .PHONY: install install: $(BIN) install -d $(SBINDIR) install -m 755 $(BIN) $(SBINDIR) $(LN) -s $(BIN) $(SBINDIR)/$(SYMLINK_PANEL) $(LN) -s $(BIN) $(SBINDIR)/$(SYMLINK_RADIO) $(LN) -s $(BIN) $(SBINDIR)/$(SYMLINK_FAN) $(LN) -s $(BIN) $(SBINDIR)/$(SYMLINK_WAKE) $(LN) -s $(BIN) $(SBINDIR)/$(SYMLINK_EDIT) .PHONY: uninstall uninstall: rm -f $(SBINDIR)/$(BIN) $(SBINDIR)/$(SYMLINK_PANEL) \ $(SBINDIR)/$(SYMLINK_RADIO) $(SBINDIR)/$(SYMLINK_FAN) \ $(SBINDIR)/$(SYMLINK_WAKE) $(SBINDIR)/$(SYMLINK_EDIT) .PHONY: olduninstall olduninstall: rm -f $(SBINDIR)/$(BIN) $(SBINDIR)/$(SYMLINK_OLDPANEL) \ $(SBINDIR)/$(SYMLINK_OLDFAN) .PHONY: dist dist: clean $(TAR) -zcf digitools-$(VER).tar.gz \ --exclude=.svn --exclude=digitools*.tar.* -C ../ $(DIR) $(TAR) -jcf digitools-$(VER).tar.bz2 \ --exclude=.svn --exclude=digitools*.tar.* -C ../ $(DIR) digitools/README0000644000175000017500000000673110463614232013531 0ustar calkinacalkinaPACKAGE OVERVIEW This is the readme file for the digitools package. This package is a combination of the previous programs asusfan and setpanel. Included in this package are the following tools: - digifan; allows fan speed control (formerly asusfan) - digipanel; allows control of the LED display, and volume knob controls the soundcard master mixer channel (formerly part of setpanel) - digiradio; allows control of the in-built radio (formerly part of setpanel) - digiwake; allows for Wake-On-CIR (wake on remote) with existing versions of LIRC that support the digimatrix. This program just needs to be run after lircd, and the digimatrix will power on when pressing the music/(on/off) button on the remote control. Some of these programs have slightly different parameter syntax than the previous ancestors, but all syntax can be found with: digipanel -h digifan -h digiradio -h digiwake -h so be mindful that your scripts using these programs may need to be updated from those that used the legacy ancestors. Note that all programs need to be run as root, since all access raw memory addresses. Notable inclusions from their ancestors include daemon-mode management, so that only one instance of the daemons will run at any time. This means that starting another instance of e.g. digifan will stop the previous instance, rather than compete with it. WARNING A final program, ozedit, replicates and extends the dangerous "hardware hacking" component of setpanel, that was accessible via the -m flag. Using this, it is quite possible to damage the oz263 chip, so consider yourself warned. BUILDING & INSTALLING INSTRUCTIONS To build, simply enter the directory and run the command: make which will build all the machine code, and make symlinks. If you wish to install, then you should edit the Makefile, and edit the first two lines that specify the installation location, which defaults to /usr/local/sbin. You should edit this to your preference, or accept the default. Then install by becoming root (if not already) and running the command: make install which will copy the executable and all symlinks to the desired location. If you wish to uninstall, type the command: make uninstall from within the source directory (assuming you keep any modifications to Makefile regarding the desired installation path the same) and the program will be removed. LEGACY BUILD & INSTALLING INSTRUCTIONS If for some reason you would like to make the program have the original package names, you can run the commands: make make oldsymlinks make oldinstall and it will create and install symlinks pointing to asusfan and setpanel as well as digiwake and digipanel. Note that this setpanel will only have the functionality of digipanel, not the original setpanel (which is split amongst the 3 programs digipanel, digiradio and ozedit). To uninstall from this configuration, simply type: make olduninstall and those legacy program symlinks will be removed. DISTRIBUTION INSTRUCTIONS To create tarballs for distribution, issue the command: make dist which assumes that tar is available, with the capability to create gzip and bzip2 archives with -z and -j flags respectively. AUTHOR'S NOTE This package was primarily written so that the ASUS Digimatrix could be fully supported automatically in the GeeXboX multimedia OS, and no warranty or guarantee of usability or warranty is offered or suggested. digitools/oz263.c0000644000175000017500000002727010463614232013701 0ustar calkinacalkina/* oz263.c: Functions for accessing the oz263 chip. Also, find and return the SiS96x i2c bus device for the digimatrix setpanel program, for both 2.4 and 2.6 kernels. Copyright (c) 2005 Andrew Calkin and Ben Potter Based heavily on the codebase for the header given directly below, and the original setpanel.c code, written by Richard Taylor, Ben Potter and Cyril Lacoux. Original header: i2cbusses: Print the installed i2c busses for both 2.4 and 2.6 kernels. Part of user-space programs to access for I2C devices. Copyright (c) 1999-2003 Frodo Looijaard and Mark D. Studebaker This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include "digitools.h" #include "i2c-dev.h" #include "it8705.h" #include "oz263.h" #define NAME_STR "SiS96x SMBus adapter" #define NAME_LEN 20 extern LED led; extern PP pp; extern DOTS dots; extern char digits[7]; extern int file; int oz263_write_byte_data(int file, char reg, char data) { int res; /* TODO: Implement kernel specific stuff here. */ res = i2c_smbus_write_byte_data(file, reg, data); usleep(I2C_TRANSACTION_DELAY_MS); return res; } int oz263_write_byte(int file, char data) { int res; /* TODO: Implement kernel specific stuff here. */ res = i2c_smbus_write_byte(file, data); usleep(I2C_TRANSACTION_DELAY_MS); return res; } int oz263_read_byte(int file) { int res; /* TODO: Implement kernel specific stuff here. */ res = i2c_smbus_read_byte(file); usleep(I2C_TRANSACTION_DELAY_MS); return res; } void oz263_radio_control(int file, CONTROL control) { switch (control) { case SEEK_DOWN: oz263_write_byte_data(file, 0x27, 0x00); break; case SEEK_UP: oz263_write_byte_data(file, 0x13, 0x00); break; case FINE_TUNE_DOWN: oz263_write_byte_data(file, 0x26, 0x00); break; case FINE_TUNE_UP: oz263_write_byte_data(file, 0x25, 0x00); break; case CHANNEL_PREV: oz263_write_byte_data(file, 0x11, 0x00); break; case CHANNEL_NEXT: oz263_write_byte_data(file, 0x10, 0x00); break; case STORE_START: oz263_write_byte_data(file, 0x15, 0x00); break; case STORE_CANCEL: oz263_write_byte_data(file, 0x16, 0x00); break; case STORE_COMMIT: oz263_write_byte_data(file, 0x19, 0x00); break; } } void oz263_radio_mode(int file, RADIO_MODE radio_mode) { oz263_write_byte_data(file, 0x23, 0x02); switch (radio_mode) { case OFF_MODE: /* Turns off the Radio */ oz263_write_byte_data(file, 0x0f, 0x00); break; case AM_RADIO: /* Turns on AM Radio */ oz263_write_byte_data(file, 0x0e, 0x00); break; case FM_RADIO: /* Turns on FM Radio */ oz263_write_byte_data(file, 0x0d, 0x00); break; case CD_MODE: /* Turns on CD mode */ oz263_write_byte_data(file, 0x0c, 0x00); break; case HD_MODE: /* Enables HD mode */ oz263_write_byte_data(file, 0x0b, 0x00); break; default: /* Turns off the Radio */ oz263_write_byte_data(file, 0x0f, 0x00); break; } } void oz263_display(int file, char digits[6], LED led, PP pp, DOTS dots, BOOL reinit) { int n; if (reinit) /* Set to digit mode (-- --:--) */ oz263_write_byte_data(file, 0x23, 0x02); /* Set up the Dots */ oz263_write_byte_data(file, 0x06, (unsigned char)dots); /* Set the Play / Pause LEDs */ oz263_write_byte_data(file, (unsigned char)pp, 0x01); /* Now set the mode LEDs: If a letter is used as the first digit next, the mode LED will be overridden */ if (led != LED_NONE) oz263_write_byte_data(file, 0x00, (unsigned char) led); /* Set the state of each digit */ for (n=0; n<6; n++) { if (digits[n] <= '9' && digits[n] >= '0') oz263_write_byte_data(file, n, digits[n] - '0'); else { switch (digits[n]) { case 'a': oz263_write_byte_data(file, n, 0x8b); break; case 'A': oz263_write_byte_data(file, n, 0x0b); break; case 'f': oz263_write_byte_data(file, n, 0x8a); break; case 'F': oz263_write_byte_data(file, n, 0x0a); break; case 'c': case 'd': oz263_write_byte_data(file, n, 0x8e); break; case 'C': case 'D': oz263_write_byte_data(file, n, 0x0e); break; case 'p': oz263_write_byte_data(file, n, 0x8d); break; case 'P': oz263_write_byte_data(file, n, 0x0d); break; case 'm': case 'M': oz263_write_byte_data(file, n, 0x0c); break; case '-': if (n == 1) oz263_write_byte_data(file, n, 0x0d); else oz263_write_byte_data(file, n, 0x0c); break; default: oz263_write_byte_data(file, n, 0x0f); break; } } } } int oz263_I2C_init(void) { int address = AUDIODJ_I2C_ADDRESS; int file_i2cbus; char filename1[20]; char filename2[20]; char filename3[20]; long funcs; if ( (int)getuid() != 0) { #ifndef SILENT fprintf(stderr,"Must be root to run this program!\n"); #endif exit(1); } int i2cbus=find_i2c_sis96x(); if ((i2cbus < 0) || (i2cbus > 0x3f)) { #ifndef SILENT fprintf(stderr,"Could not detect SiS96x i2c bus!\n"); #endif exit(1); } /* Try all three file location variants */ sprintf(filename1,"/dev/i2c-%d",i2cbus); sprintf(filename2,"/dev/i2c%d",i2cbus); sprintf(filename3,"/dev/i2c/%d",i2cbus); if ((file_i2cbus = open(filename1,O_RDWR)) < 0) if ((file_i2cbus = open(filename2,O_RDWR)) < 0) if ((file_i2cbus = open(filename3,O_RDWR)) < 0) { #ifndef SILENT fprintf(stderr,"Error: Could not open files: `%s', `%s', or `%s'\n", filename1,filename2,filename3); #endif exit(1); } /* check adapter functionality */ if (ioctl(file_i2cbus,I2C_FUNCS,&funcs) < 0) { #ifndef SILENT fprintf(stderr, "Error: Could not get the adapter functionality matrix: %s\n", strerror(errno)); #endif exit(1); } if (! (funcs & (I2C_FUNC_SMBUS_WRITE_BYTE_DATA | I2C_FUNC_SMBUS_READ_BYTE_DATA))) { #ifndef SILENT fprintf(stderr, "Error: Adapter for i2c bus %d" " does not have byte write capability\n", i2cbus); #endif exit(1); } /* use FORCE so that we can write registers even when a driver is also running */ if (ioctl(file_i2cbus,I2C_SLAVE_FORCE,address) < 0) { #ifndef SILENT fprintf(stderr,"Error: Could not set address to %d: %s\n",address, strerror(errno)); #endif exit(1); } if (file_i2cbus <= 0) { #ifndef SILENT fprintf(stderr,"Could not open i2c bus!\n"); #endif exit(1); } return file_i2cbus; } int find_i2c_sis96x(void) { FILE *fptr; char s[100]; struct dirent *de, *dde; DIR *dir, *ddir; char dev[NAME_MAX], fstype[NAME_MAX], sysfs[NAME_MAX], n[NAME_MAX]; int foundsysfs = 0; char *i2cdev; char *name_str; void print_error_msg(void); int sysfs_i2c_check(FILE *f); /* look in /proc/bus/i2c first (2.4 kernels) */ if((fptr = fopen("/proc/bus/i2c", "r"))) { while(fgets(s, 100, fptr)) { i2cdev=s; name_str=strchr(s,'\t'); /* Find 1st tab */ *name_str='\0'; /* Terminate string for i2cdev */ name_str=strchr((name_str+1),'\t'); /* Find 2nd tab */ if (!strncmp((name_str+1),NAME_STR, NAME_LEN)) { #ifndef SILENT printf("Found SiS96x SMBus adapter at i2c bus #%s\n", (i2cdev+4)); #endif fclose(fptr); return atoi((i2cdev+4)); } } } /* Now look in sysfs, since not in /proc First figure out where sysfs was mounted */ if ((fptr = fopen("/proc/mounts", "r")) == NULL) { /* proc not mounted, quit with error msg */ print_error_msg(); return -1; } while (fgets(n, NAME_MAX, fptr)) { sscanf(n, "%[^ ] %[^ ] %[^ ] %*s\n", dev, sysfs, fstype); if (strcasecmp(fstype, "sysfs") == 0) { foundsysfs++; break; } } fclose(fptr); if (foundsysfs == 0) { /* sysfs not mounted, quit with error msg */ print_error_msg(); return -1; } /* Bus numbers in i2c-adapter don't necessarily match those in i2c-dev and what we really care about are the i2c-dev numbers. Unfortunately the names are harder to get in i2c-dev */ strcat(sysfs, "/class/i2c-dev"); if((dir = opendir(sysfs)) == NULL) { print_error_msg(); return -1; } /* go through the busses */ while ((de = readdir(dir)) != NULL) { if (!strcmp(de->d_name, ".")) continue; if (!strcmp(de->d_name, "..")) continue; /* this should work for kernels 2.6.5 or higher and is preferred because is unambiguous */ sprintf(n, "%s/%s/name", sysfs, de->d_name); if((fptr = fopen(n, "r")) != NULL) if (!sysfs_i2c_check(fptr)) { fclose(fptr); #ifndef SILENT printf("Found SiS96x SMBus adapter at i2c bus #%s\n", (de->d_name+4)); #endif return atoi((de->d_name+4)); } /* this seems to work for ISA */ sprintf(n, "%s/%s/device/name", sysfs, de->d_name); if((fptr = fopen(n, "r")) != NULL) if (!sysfs_i2c_check(fptr)) { fclose(fptr); #ifndef SILENT printf("Found SiS96x SMBus adapter at i2c bus #%s\n", (de->d_name+4)); #endif return atoi((de->d_name+4)); } /* non-ISA is much harder and this won't find the correct bus name if a driver has more than one bus */ sprintf(n, "%s/%s/device", sysfs, de->d_name); if(!(ddir = opendir(n))) continue; while ((dde = readdir(ddir)) != NULL) { if (!strcmp(dde->d_name, ".")) continue; if (!strcmp(dde->d_name, "..")) continue; if ((!strncmp(dde->d_name, "i2c-", 4))) { sprintf(n, "%s/%s/device/%s/name", sysfs, de->d_name, dde->d_name); if((fptr = fopen(n, "r")) != NULL) if (!sysfs_i2c_check(fptr)) { fclose(fptr); #ifndef SILENT printf("Found SiS96x SMBus adapter at i2c bus #%s\n", (de->d_name+4)); #endif return atoi((dde->d_name+4)); } } } closedir(ddir); } closedir(dir); /* If it has reached this point, then all attempts have failed. Print error msg and exit. */ print_error_msg(); return -1; } void print_error_msg(void) { #ifndef SILENT fprintf(stderr,"Error: No I2C busses found!\n" "Be sure you have modprobed the i2c-dev and\n" "SiS96x modules. The proc (and sysfs, if using\n" "a 2.6.x kernel) filesystems must also be mounted.\n"); #endif } int sysfs_i2c_check(FILE *f) { char x[120]; fgets(x, 120, f); if(!strncmp(x, NAME_STR, NAME_LEN)) return 0; else return 1; } digitools/it8705.h0000644000175000017500000001334610463624247013771 0ustar calkinacalkina/* it8705.h - A user-space library to access the it8705 chip. Copyright (c) 2006 Andrew Calkin Copyright (c) 2005 Richard Taylor Heavily based on code for accessing/initializing it8712/it8705 written by (C) Copyright 2004 Wojtek Kaniewski This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define I2C_TRANSACTION_DELAY_MS 500 /* lirc_it87.h */ /* SECTION: Definitions */ /********************************* ITE IT87xx ************************/ /* based on the following documentation from ITE: a) IT8712F Preliminary CIR Programming Guide V0.1 b) IT8705F Simple LPC I/O Preliminary Specifiction V0.3 c) IT8712F EC-LPC I/O Preliminary Specification V0.5 */ /* IT8712/05 Ports: */ #define IT87_ACCESS_REG 0x2e #define IT87_RETURN_REG 0x2f #define IT87_INIT 0x87, 0x01, 0x55, 0x55 /* alternate Ports: */ /* #define IT87_ACCESS_REG 0x4e #define IT87_RETURN_REG 0x4f #define IT87_INIT 0x87, 0x01, 0x55, 0xaa */ #define IT8705_CFG_CTRL 0x2 #define IT8705_EC_ACCESS_REG 0x295 #define IT8705_EC_RETURN_REG 0x296 /*#define IT8705_TEMP_REG 0x28 */ /* MoBo Temp */ #define IT8705_TEMP_REG1 0x29 #define IT8705_TEMP_REG2 0x2b #define FAN1 0x15 #define FAN2 0x16 #define FAN3 0x17 #define PME_ENABLE 0xf0 #define BASE_ADDR 0x20 #define CHAR_MARK 0xff #define PME_INDX_REG 0xf5 #define PME_DATA_REG 0xf6 /* IT8712/05 Registers */ #define IT87_CHIP_ID1 0x20 #define IT87_CHIP_ID2 0x21 #define IT87_CFG_VERSION 0x22 #define IT87_SWSUSPEND 0x23 /* #define IT8712_CIR_LDN 0xa */ #define IT8705_CIR_LDN 0x7 #define IT8705_PME_LDN 0x4 #define IT8705_EC_LDN 0x4 /* CIR Configuration Registers: */ #define IT87_CIR_ACT 0x30 #define IT87_CIR_BASE_MSB 0x60 #define IT87_CIR_BASE_LSB 0x61 #define IT87_CIR_IRQ 0x70 #define IT87_CIR_CONFIG 0xf0 /* List of IT87_CIR registers: offset to BaseAddr */ #define IT87_CIR_DR 0 #define IT87_CIR_IER 1 #define IT87_CIR_RCR 2 #define IT87_CIR_TCR1 3 #define IT87_CIR_TCR2 4 #define IT87_CIR_TSR 5 #define IT87_CIR_RSR 6 #define IT87_CIR_BDLR 5 #define IT87_CIR_BDHR 6 #define IT87_CIR_IIR 7 /* Bit Definitionen */ /* IER: */ #define IT87_CIR_IER_TM_EN 0x80 #define IT87_CIR_IER_RESEVED 0x40 #define IT87_CIR_IER_RESET 0x20 #define IT87_CIR_IER_BR 0x10 #define IT87_CIR_IER_IEC 0x8 #define IT87_CIR_IER_RFOIE 0x4 #define IT87_CIR_IER_RDAIE 0x2 #define IT87_CIR_IER_TLDLIE 0x1 /* RCR: */ #define IT87_CIR_RCR_RDWOS 0x80 #define IT87_CIR_RCR_HCFS 0x40 #define IT87_CIR_RCR_RXEN 0x20 #define IT87_CIR_RCR_RXEND 0x10 #define IT87_CIR_RCR_RXACT 0x8 #define IT87_CIR_RCR_RXDCR 0x7 /* TCR1: */ #define IT87_CIR_TCR1_FIFOCLR 0x80 #define IT87_CIR_TCR1_ILE 0x40 #define IT87_CIR_TCR1_FIFOTL 0x30 #define IT87_CIR_TCR1_TXRLE 0x8 #define IT87_CIR_TCR1_TXENDF 0x4 #define IT87_CIR_TCR1_TXMPM 0x3 /* TCR2: */ #define IT87_CIR_TCR2_CFQ 0xf8 #define IT87_CIR_TCR2_TXMPW 0x7 /* TSR: */ #define IT87_CIR_TSR_RESERVED 0xc0 #define IT87_CIR_TSR_TXFBC 0x3f /* RSR: */ #define IT87_CIR_RSR_RXFTO 0x80 #define IT87_CIR_RSR_RESERVED 0x40 #define IT87_CIR_RSR_RXFBC 0x3f /* IIR: */ #define IT87_CIR_IIR_RESERVED 0xf8 #define IT87_CIR_IIR_IID 0x6 #define IT87_CIR_IIR_IIP 0x1 /* TM: */ #define IT87_CIR_TM_IL_SEL 0x80 #define IT87_CIR_TM_RESERVED 0x40 #define IT87_CIR_TM_TM_REG 0x3f #define IT87_CIR_FIFO_SIZE 32 /* Baudratedivisor for IT87: power of 2: only 1,2,4 or 8) */ #define IT87_CIR_BAUDRATE_DIVISOR 0x1 #define IT87_CIR_DEFAULT_IOBASE 0x310 #define IT87_CIR_DEFAULT_IRQ 0x7 #define IT87_CIR_SPACE 0x00 #define IT87_CIR_PULSE 0xff #define IT87_CIR_FREQ_MIN 27 #define IT87_CIR_FREQ_MAX 58 #define TIME_CONST (IT87_CIR_BAUDRATE_DIVISOR * 8000000ul / 115200ul) /********************************* ITE IT87xx ************************/ unsigned char it87_read_byte(unsigned char addr); unsigned char it87_read_ec_byte(unsigned char addr); int it87_write_byte (unsigned char addr, unsigned char data); int it87_write_ec_byte (unsigned char addr, unsigned char data); int it87_ec_port_open(void); void it87_ec_port_close(void); int it87_open(void); void it87_close(void); char it87_get_temp(void); int it87_write_ec_byte (unsigned char addr, unsigned char data); void it87_ldn_set(unsigned char ldn); unsigned char it87_read_cir_byte(unsigned char addr); int it87_write_cir_byte (unsigned char addr, unsigned char data); int it87_cir_port_open(void); void it87_cir_port_close(void); digitools/digitools.c0000664000175000017500000000734010430275462015013 0ustar calkinacalkina/* digitools.c - A user-space program to handle the ASUS DigiMatrix special capabilities. Copyright (c) 2006 Andrew Calkin and Ben Potter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include "digitools.h" #include "digipanel.h" #include "digifan.h" #include "digiwake.h" #include "oz263.h" #include "ozedit.h" LED led = LED_NONE; PP pp = PP_NONE; DOTS dots = DOTS_NONE; char digits[7]; int file=0; char *prog; void daemon_init(void) { pid_t pid_number; extern char *prog; char prog_full_name[20]; char * prog_name=prog_full_name; strncpy(prog_full_name,prog,sizeof(prog_full_name)); while (strstr(prog_name,"/")) prog_name=strstr(prog_name,"/")+1; char pid_file_name[20]="/tmp/"; strcat(strcat(pid_file_name,prog_name),".pid"); FILE * fpid; pid_number=fork(); if (pid_number < 0) { #ifndef SILENT fprintf(stderr,"Error: Could not fork() daemon!\n"); #endif exit(1); } else if (pid_number > 0) { /* parent */ fpid=fopen(pid_file_name,"w"); if (fpid == NULL) { #ifndef SILENT fprintf(stderr,"Error:Could not open %s for " "writing!\n",pid_file_name); #endif exit(1); } fprintf(fpid,"%d\n",pid_number); fclose(fpid); exit(0); } } void daemon_kill(void) { extern char *prog; FILE * fproc; char procfile_name[20]="/proc/"; char proc_contents[20]; char prog_full_name[20]; char * prog_name=prog_full_name; strncpy(prog_full_name,prog,sizeof(prog_full_name)); while (strstr(prog_name,"/")) prog_name=strstr(prog_name,"/")+1; char pid_file_name[20]="/tmp/"; strcat(strcat(pid_file_name,prog_name),".pid"); FILE * fpid; char pid_read[20]; fpid=fopen(pid_file_name,"r"); if (fpid) { fgets(pid_read,20,fpid); fclose(fpid); strcat(strcat(procfile_name,pid_read),"/stat"); fproc=fopen(procfile_name,"r"); if (fproc) { fgets(proc_contents,sizeof(proc_contents),fproc); fclose(fproc); if (strstr(proc_contents, prog_name)!=NULL) if(kill(atoi(pid_read),SIGTERM) == -1) kill(atoi(pid_read),SIGKILL); remove(pid_file_name); } } } int main (int argc, char **argv) { prog=argv[0]; if (strstr (argv[0], "digiradio")) return digiradio_main(argc, argv); if (strstr (argv[0], "setradio")) return digiradio_main(argc, argv); else if (strstr (argv[0], "digipanel")) return digipanel_main(argc, argv); else if (strstr (argv[0], "setpanel")) return digipanel_main(argc, argv); else if (strstr (argv[0], "digifan")) return digifan_main(argc, argv); else if (strstr (argv[0], "asusfan")) return digifan_main(argc, argv); else if (strstr (argv[0], "digiwake")) return digiwake_main(argc, argv); else if (strstr (argv[0], "ozedit")) return ozedit_main(argc, argv); else { #ifndef SILENT fprintf(stderr,"Unknown program name!\n"); #endif return -1; } } digitools/ozedit.h0000664000175000017500000000176410413531142014314 0ustar calkinacalkina/* ozedit.h - A user-space program to read/write to the oz263 chip in the ASUS Digimatrix. Copyright (c) 2006 Andrew Calkin Based heavily on code by Copyright (c) 2005 Richard Taylor This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ int ozedit_main(int argc, char *argv[]); digitools/ozedit.c0000644000175000017500000001330110463621155014304 0ustar calkinacalkina/* ozedit.c - A user-space program to read/write to the oz263 chip in the ASUS Digimatrix. Copyright (c) 2006 Andrew Calkin Based heavily on code by Copyright (c) 2005 Richard Taylor This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include "digitools.h" #include "oz263.h" static int axtoi(char *hexstg) { int n = 0; /* position in string */ int m = 0; /* position in digit[] to shift */ int count; /* loop index */ int intvalue = 0; /* integer value of hex string */ int digit[5]; /* hold values to convert */ while (n < 4) { if (hexstg[n]=='\0') break; if (hexstg[n] > 0x29 && hexstg[n] < 0x40 ) /*if 0 to 9 */ digit[n] = hexstg[n] & 0x0f; /* convert to int */ else if (hexstg[n] >='a' && hexstg[n] <= 'f') /* if a to f */ digit[n] = (hexstg[n] & 0x0f) + 9; /* convert to int */ else if (hexstg[n] >='A' && hexstg[n] <= 'F') /* if A to F */ digit[n] = (hexstg[n] & 0x0f) + 9; /* convert to int */ else break; n++; } count = n; m = n - 1; n = 0; while(n < count) { /* digit[n] is value of hex digit at position n (m << 2) is the number of positions to shift OR the bits into return value */ intvalue = intvalue | (digit[n] << (m << 2)); m--; /* adjust the position to set */ n++; /* next digit to process */ } return intvalue; } static void ozedit_help(char *argv0) { #ifndef SILENT printf( "\n" "Usage: %s [OPTIONS]\n" "\n" " WARNING!: This program affects the oz263 chip, which is\n" " yet to have any specifications released. Modifications made with\n" " this program may leave your chip in an unrecoverable state, or\n" " otherwise cause some hardware failure. Use at your own risk!\n\n" "\n" " This program needs to be run as root.\n" "\n" " -m, --manual Allows you to interactively change a register.\n" " -r, --read Allows you to interactively read a register.\n" "\n" " -v, --version Print version number.\n" " -h, --help Display this help message.\n" "\n", argv0); #endif } static struct option ozedit_longopts[] = { { "manual", 0, 0, 'm' }, { "read", 0, 0, 'r' }, { "version", 0, 0, 'v' }, { "help", 0, 0, 'h' }, { NULL, 0, 0, 0 } }; int ozedit_main(int argc, char *argv[]) { extern int file; int ch, longindex = 0; char buffer[20], *ptr; if ( (int)getuid() != 0) { #ifndef SILENT fprintf(stderr,"Must be root to run this program!\n"); #endif return -1; } if (argc == 1) { #ifndef SILENT printf("\nPlease supply some parameters.\n" "Use %s -h for list.\n\n", argv[0]); #endif return 1; } /* Parse input params */ for (;;) { if ((ch = getopt_long(argc, argv, "mrvh", ozedit_longopts, &longindex)) == -1) break; switch (ch) { case 'v': #ifndef SILENT printf("ASUS DigiMatrix ozedit oz263 R&D tool, from " "DigiTools Version %s\n", DIGI_VER); #endif break; case 'h': ozedit_help(argv[0]); return 0; break; case 'r': if (!file) file=oz263_I2C_init(); printf("Entering interactive read mode. Press enter to exit\n"); printf("Please enter \"REG\"\n"); printf("Where REG is a hexadecimal value (without 0x).\n"); while (buffer[0] != '\n') { /* Get at most 20 bytes from user */ if (fgets(buffer, 20, stdin)) { if (axtoi(buffer) > 0x45 ) printf("Write forbidden - the I2C bus will lock up!\n"); else { oz263_write_byte(file, axtoi(buffer)); printf("Read back: 0x%X = 0x%X\n", axtoi(buffer), oz263_read_byte(file)); } } } break; case 'm': if (!file) file=oz263_I2C_init(); printf("Entering interactive write mode. Press enter to exit\n"); printf("Please enter \"REG VALUE\"\n"); printf("Where REG and VALUE are hexadecimal values " "(without 0x).\n"); while (buffer[0] != '\n') { /* Get at most 20 bytes from user */ if (fgets(buffer, 20, stdin)) { if (axtoi(buffer) > 0x45) printf("Write forbidden - the I2C bus will lock up!\n"); else { /* Find the start of the data value */ ptr = strstr(buffer, " "); if (ptr) { printf("0x%X = 0x%X ", axtoi(buffer), axtoi(ptr)); oz263_write_byte_data(file, axtoi(buffer), axtoi(ptr)); printf("Read back: 0x%0X\n", oz263_read_byte(file)); } } } } break; default: ozedit_help(argv[0]); break; } } return 0; } digitools/digifan.c0000644000175000017500000002133710463614232014415 0ustar calkinacalkina/* digifan.c - Fan control program for the ASUS Digimatrix. * * (C) Copyright 2006 Andrew Calkin * (C) Copyright 2004 Richard Taylor * * based on code for accessing/initializing it8712/it8705 written by * * (C) Copyright 2004 Wojtek Kaniewski * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License Version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include "it8705.h" #include "digifan.h" #include "digitools.h" static double min = FAN_DEFAULT_MIN; /* minimum fan speed default (%) */ static double gradient = FAN_DEFAULT_GRADIENT; /* speed increase rate */ static double offset = FAN_DEFAULT_OFFSET; /* temp for minimum speed */ static struct option digifan_longopts[] = { { "min", 1, 0, 'm' }, { "gradient", 1, 0, 'g' }, { "offset", 1, 0, 'o' }, { "auto", 0, 0, 'a' }, { "intelligent", 0, 0, 'i' }, { "set", 1, 0, 's' }, { "read", 0, 0, 'r' }, { "kill", 0, 0, 'k' }, { "version", 0, 0, 'v' }, { "help", 0, 0, 'h' }, { NULL, 0, 0, 0 } }; static int set_fan (unsigned char state) { unsigned char speed, temp1, temp2; double percentage = 0; it87_ec_port_open(); daemon_kill(); temp1 = it87_read_ec_byte(IT8705_TEMP_REG1); temp2 = it87_read_ec_byte(IT8705_TEMP_REG2); switch (state) { case FAN_AUTO: #ifndef SILENT printf("Setting Fan to AUTO\n"); #endif it87_write_ec_byte(FAN1, AUTO); it87_write_ec_byte(FAN2, AUTO); it87_write_ec_byte(FAN3, AUTO); break; case FAN_OFF: it87_write_ec_byte(FAN1, OFF); it87_write_ec_byte(FAN2, OFF); it87_write_ec_byte(FAN3, OFF); break; case FAN_INTELLIGENT: #ifndef SILENT printf("Running in intelligent mode (update = 5s)\n"); #endif daemon_init(); while (1) { temp1 = it87_read_ec_byte(IT8705_TEMP_REG1); temp2 = it87_read_ec_byte(IT8705_TEMP_REG2); if (temp2 > temp1) { /* Go with the average of the two temperatures. (we need to cool down the mainboard too)*/ temp1 = (temp1 + temp2) / 2; } percentage = min + ( (temp1 - offset) * gradient); /* We can't go more than 100%! */ if (percentage > 100) percentage = 100; /* No slower than min */ if (percentage < min) percentage = min; speed = (unsigned char) ((percentage * (double)FAN_MAX_PWM) / 100); it87_write_ec_byte(FAN1, (speed&0x7f)); it87_write_ec_byte(FAN2, (speed&0x7f)); sleep(5); } /* end while*/ break; default: #ifndef SILENT printf("Setting fan speed to: %d%%\n", (100 *(state & 0x7f)) / 0x7f); #endif it87_write_ec_byte(FAN1, state); it87_write_ec_byte(FAN2, state); break; } /* end switch*/ it87_ec_port_close(); return 0; } static void digifan_help(const char *argv0) { #ifndef SILENT printf( "Usage: %s [OPTIONS]\n" "\n" " Program to control the fan speeds in the Asus Digimatrix.\n" " -v, --version Print version information\n" " -h, --help Display this help message\n" "\n" " Fan control is initiated via one of the following options:\n" " -r, --read Display the current fan speed (%%)\n" " Note: does not alter the fan setting\n" " -s, --set=VALUE Set the current fan speed (%%)\n" " -a, --auto Set to H/W monitoring (as in BIOS)\n" " -i, --intelligent Set the fan speed based on current temperature\n" " -k, --kill Stop the daemon (if running), and exit\n" "\n" " The -i option may also be used with any of the following options to\n" " override program defaults.\n" "\n" " -m, --min=VALUE Set the minimum Fan speed (Default: 30)\n" " -o, --offset=VALUE The temperature (deg C) for minimum fan speed \n" " (Default: 30)\n" " -g, --gradient=VALUE Set the rate at which speed increases with\n" " temperature (Default: 4)\n" " e.g. gradient = (100 - min) \n" " -------------------\n" " (max_temp - offset)\n" "\n", argv0); #endif } int digifan_main(int argc, char **argv) { unsigned char next_state = 0; if ( (int)getuid() != 0) { #ifndef SILENT fprintf(stderr,"Must be root to run this program!\n"); #endif return -1; } int ch, longindex = 0; if (argc == 1) { #ifndef SILENT printf("\nPlease supply some parameters.\n" "Use %s -h for list.\n\n", argv[0]); #endif return 1; } it87_open(); it87_ldn_set(IT8705_EC_LDN); it87_close(); for (;;) { if ((ch = getopt_long(argc, argv, "m:g:o:ais:rkvh", digifan_longopts, &longindex)) == -1) { break; } switch (ch) { case 'm': if (atof(optarg)<5) { #ifndef SILENT printf("Specified minimum too low! Using default.\n"); #endif } else { if (atof(optarg)>100) { #ifndef SILENT printf("Specified minimum too high! Using default.\n"); #endif } else min=atof(optarg); } #ifndef SILENT printf("Setting min to: %.02f%%\n", min); #endif break; case 'g': if (atof(optarg)<2) { #ifndef SILENT printf("Specified gradient too low! Using default.\n"); #endif } else { if (atof(optarg)>100) { #ifndef SILENT printf("Specified gradient too high! Using default.\n"); #endif } else gradient=atof(optarg); } #ifndef SILENT printf("Setting gradient to: %.02f\n", gradient); #endif break; case 'o': if (atof(optarg)<18) { #ifndef SILENT printf("Specified offset too low! Using default.\n"); #endif } else { if (atof(optarg)>55) { #ifndef SILENT printf("Specified offset too high! Using default.\n"); #endif } else offset=atof(optarg); } #ifndef SILENT printf("Setting offset to: %.02fDegC\n", offset); #endif break; case 'r': it87_ec_port_open(); printf("Current Fan setting is: %d%%\n", (100 *(it87_read_ec_byte(FAN1) & 0x7f)) / 0x7f); it87_ec_port_close(); return 0; break; case 's': if (atoi(optarg) < OFF) { #ifndef SILENT printf("Warning: Value provided (%d%%) too low!\n" "Minimum fan speed: %d%%\n", atoi(optarg),OFF); #endif next_state = ( OFF * 0x7f) / 100; } else if (atoi(optarg)>100) { #ifndef SILENT printf("Warning: Value provided (%d%%) too high!\n" "Maximum fan speed: 100%%\n", atoi(optarg)); #endif next_state = FAN_MAX_PWM; } else { next_state = ( atoi(optarg) * 0x7f) / 100; } break; case 'a': next_state = FAN_AUTO; break; case 'i': next_state = FAN_INTELLIGENT; break; case 'k': #ifndef SILENT printf("Stopping the %s daemon\n",argv[0]); #endif daemon_kill(); exit(0); case 'v': #ifndef SILENT printf("ASUS DigiMatrix Fan Controller, from DigiTools Version " "%s\n",DIGI_VER); #endif /* Exit program after giving version info */ return 0; break; case 'h': digifan_help(argv[0]); /* Exit program after giving help info */ return 0; break; default: #ifndef SILENT printf("Undefined input parameter(s) provided\n"); #endif /* Impossible to get here (unless programming error?) */ return 1; break; } /* end switch */ } /* end for loop */ if (next_state != 0) set_fan(next_state); else { #ifndef SILENT printf("No fan mode selected!\n"); #endif } return 0; }