/*************************************************************************** * Copyright (C) 09/2007 by Olaf Rempel * * razzor@kopf-tisch.de * * * * 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; version 2 of the License, * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include "gtk2-gui.h" #include "i2c.h" /* TWIBOOT commands */ #define CMD_GET_INFO 0x10 #define CMD_GET_SIGNATURE 0x11 #define CMD_WRITE_FLASH 0x12 #define CMD_READ_FLASH 0x13 #define CMD_WRITE_EEPROM 0x14 #define CMD_READ_EEPROM 0x15 #define CMD_BOOT_APPLICATION 0x1F #define COOKIE 0x4711 #define WRITE_COOKIE COOKIE #define FLASH_BLKSIZE 0x40 /* blctrl commands */ //#define CMD_GET_INFO 0x10 #define CMD_SET_PWM 0x21 #define CMD_GET_STATUS 0x22 #define CMD_SET_PARAM 0x23 #define CMD_GET_PARAM 0x24 #define CMD_BOOT_LOADER 0x2F static int i2c_connected; void i2c_enumerate_interfaces(void) { gui_flush_i2c_interfaces(); char path[64]; strcpy(path, "/dev"); DIR *dp = opendir(path); if (dp == NULL) { perror("opendir()"); return; } char *ptr = path + strlen(path); *ptr = '/'; struct dirent *dentry; while ((dentry = readdir(dp)) != NULL) { if (!strcmp(dentry->d_name, ".")) continue; if (!strcmp(dentry->d_name, "..")) continue; if (strncmp(dentry->d_name, "i2c-", 4) != 0) continue; strcpy(ptr +1, dentry->d_name); struct stat statbuf; if (stat(path, &statbuf) == -1) { perror("stat()"); continue; } if (!S_ISCHR(statbuf.st_mode)) continue; /* TODO: check permissions */ gui_add_i2c_interface(path); } closedir(dp); } void i2c_close(int fd) { i2c_connected = 0; i2c_close(fd); } int i2c_open(const char *path) { int fd = open(path, O_RDWR); if (fd < 0) { perror("open()"); return -1; } unsigned long funcs; if (ioctl(fd, I2C_FUNCS, &funcs)) { perror("ioctl(I2C_FUNCS)"); i2c_close(fd); return -1; } if (!(funcs & I2C_FUNC_I2C)) { fprintf(stderr, "I2C_FUNC_I2C not supported!\n"); i2c_close(fd); return -1; } i2c_connected = 1; return fd; } void i2c_set_address(int fd, int address) { if (ioctl(fd, I2C_SLAVE, address) < 0) { perror("ioctl(I2C_SLAVE)"); i2c_close(fd); } } int i2c_isconnected(void) { return i2c_connected; } void i2c_cmd_bootloader(int fd) { char cmd[] = { CMD_BOOT_LOADER }; write(fd, cmd, 1); } void i2c_cmd_application(int fd) { char cmd[] = { CMD_BOOT_APPLICATION }; write(fd, cmd, 1); } void i2c_cmd_getinfo(int fd, char *buf, int size) { char cmd[] = { CMD_GET_INFO }; write(fd, cmd, 1); size = MIN(16, size); memset(buf, 0, size); read(fd, buf, size); int i; for (i = 0; i < size; i++) buf[i] &= ~0x80; } void i2c_cmd_getsignature(int fd, unsigned char *buf, int size) { char cmd[] = { CMD_GET_SIGNATURE }; write(fd, cmd, 1); memset(buf, 0, size); read(fd, buf, MIN(4, size)); } void i2c_cmd_getparameters(int fd, struct blmc_parameter *blmc) { char cmd[] = { CMD_GET_PARAM }; write(fd, cmd, 1); memset(blmc, 0, sizeof(struct blmc_parameter)); read(fd, blmc, sizeof(struct blmc_parameter)); } void i2c_cmd_setparameters(int fd, struct blmc_parameter *blmc, int persistent) { char cmd[sizeof(struct blmc_parameter) +1]; cmd[0] = CMD_SET_PARAM; memcpy(cmd +1, blmc, sizeof(struct blmc_parameter)); write(fd, cmd, sizeof(struct blmc_parameter) + (persistent ? 1 : -1)); } int i2c_write_flash(int fd, char *data, int size, void (*progress_cb)(int pos, int size)) { int pos = 0; while (pos < size) { progress_cb(pos, size); char buf[FLASH_BLKSIZE +5]; buf[0] = CMD_WRITE_FLASH; buf[1] = (pos >> 8) & 0xFF; buf[2] = pos & 0xFF; buf[3] = (COOKIE >> 8) & 0xFF; buf[4] = COOKIE & 0xFF; /* copy data and pad with 0xFF */ int len = MIN(FLASH_BLKSIZE, size - pos); memcpy(buf +5, &data[pos], len); memset(buf +5 +len, 0xFF, FLASH_BLKSIZE - len); write(fd, buf, sizeof(buf)); pos += len; } progress_cb(pos, size); return pos; } int i2c_read_flash(int fd, char *data, int size, void (*progress_cb)(int pos, int size)) { int pos = 0; while (pos < size) { progress_cb(pos, size); char cmd[3]; cmd[0] = CMD_READ_FLASH; cmd[1] = (pos >> 8) & 0xFF; cmd[2] = pos & 0xFF; write(fd, cmd, 3); int len = MIN(FLASH_BLKSIZE, size - pos); read(fd, data + pos, len); pos += len; } progress_cb(pos, size); return pos; } int i2c_verify_flash(int fd, char *data, int size, void (*progress_cb)(int pos, int size)) { int pos = 0; while (pos < size) { progress_cb(pos, size); char cmd[3]; cmd[0] = CMD_READ_FLASH; cmd[1] = (pos >> 8) & 0xFF; cmd[2] = pos & 0xFF; write(fd, cmd, 3); char buf2[FLASH_BLKSIZE]; int len = MIN(FLASH_BLKSIZE, size - pos); read(fd, buf2, len); if (memcmp(data + pos, buf2, len) != 0) break; pos += len; } progress_cb(pos, size); return pos; } void i2c_cmd_setpwm(int fd, int pwm) { char cmd[] = { CMD_SET_PWM, pwm }; write(fd, cmd, 2); } void i2c_cmd_getstatus(int fd, struct blmc_status *status) { char cmd[] = { CMD_GET_STATUS }; write(fd, cmd, 1); memset(status, 0, sizeof(struct blmc_status)); read(fd, status, sizeof(struct blmc_status)); }