/* imon-poke: send 16 byte commands to your imon LCD device.
 *
 *  Copyright (C) 2007 Marty Pauley
 *
 *  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 3 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.
 *
 * I compile this with on GNU/Linux with:
 *   gcc -std=gnu99 imon-poke.c -lusb -o imon-poke
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <usb.h>

void die(const char *msg)
{
    fprintf(stderr, msg);
    exit(1);
}

#define try(something) if((something) < 0) die(#something " failed\n")

void poke_device(struct usb_device *dev, char *packet)
{
    int erc;
    usb_dev_handle *dh;

    dh = usb_open(dev);
    if (!dh) die("cannot open device\n");

    try(usb_claim_interface(dh, 0));
    try(usb_clear_halt(dh, 2));

    for(int i = 0; i < 16; i+=8) {
        erc = usb_interrupt_write(dh, 2, packet+i, 8, 500);
        if (erc < 0) die("write failed\n");
        usleep(50000);
    }

    try(usb_release_interface(dh, 0));
    try(usb_close(dh));
}

struct usb_device *find_device(void)
{
    usb_init();
    usb_find_busses();
    usb_find_devices();
    for (struct usb_bus * bus = usb_busses; bus; bus = bus->next) {
        for (struct usb_device *dev = bus->devices; dev; dev = dev->next) {
            if (dev->descriptor.idVendor == 0x15c2 && dev->descriptor.idProduct == 0xffdc) {
                return dev;
            }
        }
    }
}

int main(int argc, char **argv)
{
    struct usb_device *dev;
    char packet[16] = {
        0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
    };


    dev = find_device();
    if (!dev) die("cannot find device\n");

    ++argv; /* skip the program name */

    for (int i=0; i<16 && *argv; ++i, ++argv) {
        int n = strtol(*argv, 0, 0);
        packet[i] = (char)(n&0xff);
    }

    /* very basic safety check */
    packet[7] = (char)0x00;
    packet[15] = (char)0x02;

    poke_device(dev, packet);

    return 0;
}


