diff options
Diffstat (limited to 'modules/temper/temper.c')
-rw-r--r-- | modules/temper/temper.c | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/modules/temper/temper.c b/modules/temper/temper.c new file mode 100644 index 00000000..e591c9fa --- /dev/null +++ b/modules/temper/temper.c @@ -0,0 +1,301 @@ +#include <stdio.h> +#include <string.h> +#include <usb.h> +#include <errno.h> + +/* + * Temper.c by Robert Kavaler (c) 2009 (relavak.com) + * All rights reserved. + * + * Temper driver for linux. This program can be compiled either as a library + * or as a standalone program (-DUNIT_TEST). The driver will work with some + * TEMPer usb devices from RDing (www.PCsensor.com). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY Robert Kavaler ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Robert kavaler BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "temper.h" + +#define VENDOR_ID 0x1130 +#define PRODUCT_ID 0x660c +#define DEBUG_MODE 0 +#define SLEEP_TIMEOUT 10 + +struct Temper { + struct usb_device *device; + usb_dev_handle *handle; + int debug; + int timeout; +}; + +Temper * +TemperCreate(struct usb_device *dev, int timeout, int debug) +{ + Temper *t; + int ret; + + t = calloc(1, sizeof(*t)); + t->device = dev; + t->debug = debug; + t->timeout = timeout; + t->handle = usb_open(t->device); + if(!t->handle) { + free(t); + return NULL; + } + if(t->debug) { + printf("Trying to detach kernel driver\n"); + } + + ret = usb_detach_kernel_driver_np(t->handle, 0); + if(ret) { + if(errno == ENODATA) { + if(t->debug) { + printf("Device already detached\n"); + } + } else { + if(t->debug) { + printf("Detach failed: %s[%d]\n", + strerror(errno), errno); + printf("Continuing anyway\n"); + } + } + } else { + if(t->debug) { + printf("detach successful\n"); + } + } + ret = usb_detach_kernel_driver_np(t->handle, 1); + if(ret) { + if(errno == ENODATA) { + if(t->debug) + printf("Device already detached\n"); + } else { + if(t->debug) { + printf("Detach failed: %s[%d]\n", + strerror(errno), errno); + printf("Continuing anyway\n"); + } + } + } else { + if(t->debug) { + printf("detach successful\n"); + } + } + + if(usb_set_configuration(t->handle, 1) < 0 || + usb_claim_interface(t->handle, 0) < 0 || + usb_claim_interface(t->handle, 1)) { + usb_close(t->handle); + free(t); + return NULL; + } + return t; +} + +Temper * +TemperCreateFromDeviceNumber(int deviceNum, int timeout, int debug) +{ + struct usb_bus *bus; + int n; + + n = 0; + for(bus=usb_get_busses(); bus; bus=bus->next) { + struct usb_device *dev; + + for(dev=bus->devices; dev; dev=dev->next) { + if(debug) { + printf("Found device: %04x:%04x\n", + dev->descriptor.idVendor, + dev->descriptor.idProduct); + } + if(dev->descriptor.idVendor == VENDOR_ID && + dev->descriptor.idProduct == PRODUCT_ID) { + if(debug) { + printf("Found deviceNum %d\n", n); + } + if(n == deviceNum) { + return TemperCreate(dev, timeout, debug); + } + n++; + } + } + } + return NULL; +} + +void +TemperFree(Temper *t) +{ + if(t) { + if(t->handle) { + usb_close(t->handle); + } + free(t); + } +} + +static int +TemperSendCommand(Temper *t, int a, int b, int c, int d, int e, int f, int g, int h) +{ + unsigned char buf[32]; + int ret; + + bzero(buf, 32); + buf[0] = a; + buf[1] = b; + buf[2] = c; + buf[3] = d; + buf[4] = e; + buf[5] = f; + buf[6] = g; + buf[7] = h; + + if(t->debug) { + printf("sending bytes %d, %d, %d, %d, %d, %d, %d, %d\n", + a, b, c, d, e, f, g, h); + } + + ret = usb_control_msg(t->handle, 0x21, 9, 0x200, 0x01, + (char *) buf, 32, t->timeout); + if(ret != 32) { + perror("usb_control_msg failed"); + return -1; + } + return 0; +} + +static int +TemperGetData(Temper *t, char *buf, int len) +{ + int ret; + + return usb_control_msg(t->handle, 0xa1, 1, 0x300, 0x01, + (char *) buf, len, t->timeout); +} + +int +TemperGetTemperatureInC(Temper *t, float *tempC) +{ + char buf[256]; + int ret, temperature, i; + + TemperSendCommand(t, 10, 11, 12, 13, 0, 0, 2, 0); + TemperSendCommand(t, 0x54, 0, 0, 0, 0, 0, 0, 0); + for(i = 0; i < 7; i++) { + TemperSendCommand(t, 0, 0, 0, 0, 0, 0, 0, 0); + } + TemperSendCommand(t, 10, 11, 12, 13, 0, 0, 1, 0); + ret = TemperGetData(t, buf, 256); + if(ret < 2) { + return -1; + } + + temperature = (buf[1] & 0xFF) + (buf[0] << 8); + temperature += 1152; // calibration value + *tempC = temperature * (125.0 / 32000.0); + return 0; +} + +int +TemperGetOtherStuff(Temper *t, char *buf, int length) +{ + TemperSendCommand(t, 10, 11, 12, 13, 0, 0, 2, 0); + TemperSendCommand(t, 0x52, 0, 0, 0, 0, 0, 0, 0); + TemperSendCommand(t, 10, 11, 12, 13, 0, 0, 1, 0); + return TemperGetData(t, buf, length); +} + + +#ifdef UNIT_TEST + +#define USB_TIMEOUT 1000 /* milliseconds */ + +int +main(int argv,char** args) +{ + + + Temper *t; + char buf[256]; + int i, ret,oneshot=0; + if (argv == 2 && (args[1][1] == 'h' || args[1][0] == 'h')) + { + printf("Temper, does the right thing\n"); + printf("use %s -1 to do one-shot\n"); + printf("recompile with DEBUG_MODE = 1 for all the debug printing\n"); + printf("recompile with SLEEP_TIMEOUT = XX for a different polling interval\n"); + exit(0); + } + + if (argv == 2 && (args[1][0] == '1' || args[1][1] == '1')) + oneshot = 1; + + usb_set_debug(DEBUG_MODE); + usb_init(); + usb_find_busses(); + usb_find_devices(); + + t = TemperCreateFromDeviceNumber(0, USB_TIMEOUT, DEBUG_MODE); + if(!t) { + perror("TemperCreate"); + exit(-1); + } + +/* + TemperSendCommand(t, 10, 11, 12, 13, 0, 0, 2, 0); + TemperSendCommand(t, 0x43, 0, 0, 0, 0, 0, 0, 0); + TemperSendCommand(t, 0, 0, 0, 0, 0, 0, 0, 0); + TemperSendCommand(t, 0, 0, 0, 0, 0, 0, 0, 0); + TemperSendCommand(t, 0, 0, 0, 0, 0, 0, 0, 0); + TemperSendCommand(t, 0, 0, 0, 0, 0, 0, 0, 0); + TemperSendCommand(t, 0, 0, 0, 0, 0, 0, 0, 0); + TemperSendCommand(t, 0, 0, 0, 0, 0, 0, 0, 0); +*/ + + bzero(buf, 256); + ret = TemperGetOtherStuff(t, buf, 256); + if (DEBUG_MODE){ + printf("Other Stuff (%d bytes):\n", ret); + for(i = 0; i < ret; i++) { + printf(" %02x", buf[i] & 0xFF); + if(i % 16 == 15) { + printf("\n"); + } + } + printf("\n"); + } + + for(;;) { + float tempc; + + if(TemperGetTemperatureInC(t, &tempc) < 0) { + perror("TemperGetTemperatureInC"); + exit(1); + } + printf("%.2fF %.2fC\n", (9.0 / 5.0 * tempc + 32.0), + tempc); + if (oneshot) + exit(0); + + sleep(SLEEP_TIMEOUT); + } + return 0; +} + +#endif |