Board index » Codeka » iMON LCD All times are UTC + 10 hours [ DST ]
Previous topicNext topic
New iMON device
Search for:
Jump to:  
Page 1 of 7 [ 69 posts ]
Post 29-Jan-2008 23:52, New iMON device, by Carcassonne
Hi,

I recently bought a new Silverstone GD-01MX case. However, the LCD and remote come up with a different USB ID to the standard one:

Bus 003 Device 002: ID 15c2:0038 SoundGraph Inc.

The usual ID seems to be 15c2:ffdc.

My system is Ubuntu 7.10 with lirc 0.8.2-0ubuntu8. I haven't tried any patches yet. Out of the box, I have pretty much the same symptoms as this post to lirc-lists:

http://www.nabble.com/New-iMon-device-td14177941.html

Seems like this guy is working on it as well:
http://www.nabble.com/Mysterious-USB-LC ... 60411.html

I just looked at cvs lirc, and the USB ID does not appear there, so I guess its not supported in CVS lirc yet.

My time is limited, so I doubt I'll get to hack on the driver. Is there progress out there?

Thanks for any info,
Ben.


Carcassonne

Joined: 29-Jan-2008 23:14
Posts: 1
Post 30-Jan-2008 11:53, Re: New iMON device, by dean
Hmm, it certainly looks the same as the other LCD devices, but they've obviously done something funky. Soundgraph have never been very forthcoming with technical specifications... the USB protocol for the LCD device had to be reverse engineered (not by me, some guys working on MediaPortal for Windows managed it :D ). And I believe the same is true of the original VFD patches that Venky Raju made.

So methinks unless you've got the inclination to reverse engineer the protocol yourself, you might have to wait for somebody else to do it. You can possibly try emailing Silverstone. I found when I was trying to get my LCD working, the Antec people were rather more "supportive" of my efforts than the Soundgraph people.

Soundgraph do have a forum (here) but it seems they don't respond :)


User avatar
dean
Site Admin

Joined: 18-Sep-2007 22:55
Posts: 50
Post 24-Feb-2008 21:49, Re: New iMON device, by madCoder
Has there been any update on this 0038 device? I have the same device in my Silverstone GD01B-MXR case.

I was able to run the provided software in XP via VirtualBox, and it can control the LCD fine even from a virtual machine. Running Snoopy, I was able to capture a few traces of the USB communication with the device, and many of the commands appear to be the same as the ffdc device, except the Snoopy log looks like it reverses the order of the bytes (or perhaps reversing the order is what changed in this device revision?) If anyone knows whether Snoopy does in fact reverse the bytes, that would be helpful to know...

Here's a few examples:
<payloadbytes>0000000000000001</payloadbytes>
<payloadbytes>00000000ffffff10</payloadbytes>
<payloadbytes>ffffffffff000011</payloadbytes>
<payloadbytes>0000000000000012</payloadbytes>


That matches up with part of the startup sequence as explained here: http://imonapi.tripod.com/#_Toc169965084 except with the payload bytes in reverse order.

The other problem is that I can't seem to figure out how to write to the device, even if I wanted to test protocol bytes. I tried using libusb, using another person's test for the original imonlcd devices, but I can't seem to locate a valid USB OUT endpoint that allows writing:

$ lsusb -d 15c2:0038
Bus 002 Device 005: ID 15c2:0038 SoundGraph Inc.
$ lsusb -d 15c2:0038 -v | grep bEndpoint
        bEndpointAddress     0x81  EP 1 IN
        bEndpointAddress     0x82  EP 2 IN


Notice that it shows two IN endpoints, but no OUT endpoints. Therefore my libusb tests are all failing, because I'm not allowed to write to either of those endpoints.

Any suggestions? I do know C, but I'd need a little direction to get me started with writing a patch.


madCoder

Joined: 24-Feb-2008 21:36
Posts: 12
Post 25-Feb-2008 14:47, Re: New iMON device, by RXM307
I've just bought a Silverstone LC16M and it looks like I've got the same device

Bus 001 Device 002: ID 15c2:0036 SoundGraph Inc.

The remote seems to get detected as a usb keyboard and mouse so I could do keyboard remapping to get it working, the exception being the arrow keys wont work until .21 is released which should allow mouse input for the menus.

I'd really like to get the VFD working on this though, please let me know if theres any testing I can do

Cheers,
Anthony


RXM307

Joined: 25-Feb-2008 12:51
Posts: 14
Post 25-Feb-2008 15:46, Re: New iMON device, by madCoder
So, using the usbmon kernel module, and usbmon userland tool, I started sniffing USB traffic, and then launched VirtualBox and started up my XP VM.

This seems to be a little bit easier than using USB Snoopy in the XP VM itself. And it confirmed a few things I was already suspecting:

Earlier versions seem to use an OUT endpoint to communicate with the LCD, whereas this version does virtually all of its communication with the control endpoint instead. I was able to modify the code from this blog: http://martian.org/marty/2007/12/14/imo ... tems-case/ so that it works with the 0x0038 device. RXM307, can you try this code, modifying the Product ID to be 0x0036 instead, and see if it works for you?

This code simply blanks the screen, sets the contrast, and displays the top and bottom horizontal lines:

/* 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);
}

int config = 1;
int iface = 0;
int ep = 0x81;

#define DEV_VENDOR_ID 0x15c2
#define DEV_PRODUCT_ID 0x0038

#define try(something) if((erc = something) < 0) { printf(#something " failed: [%i] %s\n", erc, usb_strerror()); exit(1); }

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

    dh = usb_open(dev);
    if (!dh) die("cannot open device\n");
   
    try(usb_claim_interface(dh, iface));
    try(usb_clear_halt(dh, ep));

    for(i = 0; i < size; i+=8)
    {
        try(usb_control_msg(dh, 0x21, 0x09, 0x0200, 0x0001, packet + i, 8, 1000));
        if (erc < 0)
        {
          printf("Err = %i\n", erc);
          die("write failed\n");
        }
        usleep(50000);
    }

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

struct usb_device *find_device(void)
{
    usb_init();
    usb_find_busses();
    usb_find_devices();
    struct usb_bus * bus;
    struct usb_device *dev;
    for (bus = usb_busses; bus; bus = bus->next) {
        for (dev = bus->devices; dev; dev = dev->next) {
            if (dev->descriptor.idVendor == DEV_VENDOR_ID && dev->descriptor.idProduct == DEV_PRODUCT_ID) {
                return dev;
            }
        }
    }
}
#define SIZE 64

int main(int argc, char **argv)
{
    struct usb_device *dev;
    int i;
    char packet[SIZE] = {
        0x40, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x88, // initialize  (disable clock, blank?)
        0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x8a, // initialize contd
        0x12, 0x00, 0x00, 0x00,  0xe8, 0x70, 0x08, 0x03, // contrast? time?
        0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x86, // ???
        0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x01, // ???
        0x00, 0x00, 0x00, 0x00,  0xff, 0xff, 0xff, 0x10, // 0x10, 0x11, 0x12 -> lines
        0xff, 0xff, 0xff, 0xff,  0xff, 0x00, 0x00, 0x11, // "
        0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x12, // "
    };


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

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

    poke_device(dev, packet, SIZE);

    return 0;
}


--edit--
Further testing shows that this is the line that draws the top/bottom horizontal lines. So, what do the 0x10, 0x11, and 0x12 blocks do?
0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x01,


From http://imonapi.tripod.com/#_Toc169965084 it indicates that the 0x01 byte is used to set/clear the icons. But in my case, 0x01 with all 0's seems to draw the horizontal lines.

--edit--
So I was mistaken... Testing more shows that the 0x01 command tells it to draw the "progress indicator" bars. The 0x10, 0x11, and 0x12 commands tell it what progress to draw. So the 0xff's in those lines instruct it to draw all the way across the screen, for the thinner of the two progress lines. If you set the rest to 0xff, you get both the thin and the thick progress bars drawn on the top and bottom.


madCoder

Joined: 24-Feb-2008 21:36
Posts: 12
Post 25-Feb-2008 17:30, Re: New iMON device, by madCoder
I'm now able to control everything, like turning the device on/off, setting icons, etc. But I'm having some trouble getting my modifications to your lcdproc patch to work. It patches and compiles fine, but I can't seem to figure out how it actually communicates with the device.

The comments mention a /dev/usb/lcd device, which I don't have. The config also mentions /dev/lcd0, which I don't have either. The lirc_imon module is loaded. So, how do I get it to create the lcd0 device node?

Is that in the lirc code? Where would I modify that, so that it creates the lcd device node correctly?


madCoder

Joined: 24-Feb-2008 21:36
Posts: 12
Post 25-Feb-2008 22:45, Re: New iMON device, by madCoder
My LCD device is now working properly with lcdproc, and even mythlcdserver! :D

Below are my patches for a 15c2:0038 iMON LCD device. Note that if you don't have a 0038 device, this won't work for you.

Also, it's worth noting that these patches are against lcdproc-0.5.2, and the latest (2008-02-25) CVS version of lirc. This might not apply cleanly to lirc-0.8.3pre1 or lirc-0.8.2 (patched with dean's patch). But with the CVS version, you don't need to apply Dean's patch.

The lirc patch allows lirc_imon to determine whether it should use the current/default method of communicating with the device (interrupt transfers to the IN endpoint), or use control messages to the control endpoint (0x00). The latter is required for the 0038 device.

The lcdproc patch changes two command prefixes: 0x50 becomes 0x88 and 0x51 becomes 0x8a. It accomplishes that via a defined macro, so it also modifies the Makefile. So if you re-run the ./configure script, you will have to readd the -DIS_LCD_0038 back to the Makefile. If you have a better way of accomplishing that, please feel free.

lirc-imon_0038.patch:
--- lirc.org/drivers/lirc_imon/lirc_imon.c      2008-02-25 04:48:41.883792756 -0500
+++ lirc/drivers/lirc_imon/lirc_imon.c  2008-02-25 04:48:23.074984848 -0500
@@ -87,6 +87,8 @@

#define BIT_DURATION   250     /* each bit received is 250us */

+#define IMON_LCD_NEXTGEN 0x0038 /* The 0x0038 device requires control urbs */
+
#define SUCCESS                0
#define        TRUE            1
#define FALSE          0
@@ -162,6 +164,7 @@
        struct usb_endpoint_descriptor *tx_endpoint;
        struct urb *rx_urb;
        struct urb *tx_urb;
+       int tx_control;                 /* if 1, will use a control msg urb */
        unsigned char usb_rx_buf[8];
        unsigned char usb_tx_buf[8];

@@ -196,6 +199,7 @@
        { USB_DEVICE(0x0aa8, 0x8001) },         /* IR only     */
        { USB_DEVICE(0x15c2, 0xffda) },         /* IR & VFD    */
        { USB_DEVICE(0x15c2, 0xffdc) },         /* IR & VFD    */
+       { USB_DEVICE(0x15c2, 0x0038) },         /* IR & LCD    */
        { USB_DEVICE(0x04e8, 0xff30) },         /* ext IR only */
        {}
};
@@ -212,6 +216,7 @@
static unsigned short ir_onboard_decode_product_list[] = {
                        /* terminate this list with a 0 */
                        0xffdc,
+                       0x0038,
                        0 };

/* USB Device data */
@@ -431,17 +436,31 @@
        int interval = 0;
        int retval = SUCCESS;

-       pipe = usb_sndintpipe(context->dev,
+       /* Check if we need to use control or interrupt urb */
+       if ( context->tx_control == 0 )
+       {
+               pipe = usb_sndintpipe(context->dev,
                        context->tx_endpoint->bEndpointAddress);
#ifdef KERNEL_2_5
-       interval = context->tx_endpoint->bInterval;
+               interval = context->tx_endpoint->bInterval;
#endif /* Use 0 for 2.4 kernels */

-       usb_fill_int_urb(context->tx_urb, context->dev, pipe,
-               context->usb_tx_buf, sizeof(context->usb_tx_buf),
-               usb_tx_callback, context, interval);
-
-       context->tx_urb->actual_length = 0;
+               usb_fill_int_urb(context->tx_urb, context->dev, pipe,
+                       context->usb_tx_buf, sizeof(context->usb_tx_buf),
+                       usb_tx_callback, context, interval);
+
+               context->tx_urb->actual_length = 0;
+       } else {
+               /* setup packet is '21 09 0200 0001 0008' */
+               unsigned char setup_packet[8] = { 0x21, 0x09, 0x02, 0x00, 0x00, 0x01, 0x00, 0x08 };
+               /* control pipe is endpoint 0x00 */
+               pipe = usb_sndctrlpipe(context->dev, 0);
+               /* build the control urb */
+               usb_fill_control_urb(context->tx_urb, context->dev, pipe, setup_packet,
+                       context->usb_tx_buf, sizeof(context->usb_tx_buf),
+                       usb_tx_callback, context);
+               context->tx_urb->actual_length = 0;
+       }

        init_completion(&context->tx.finished);
        atomic_set(&(context->tx.busy), 1);
@@ -1036,6 +1055,7 @@
        int alloc_status;
        int vfd_proto_6p = FALSE;
        int ir_onboard_decode = FALSE;
+       int tx_control = 0;
        struct imon_context *context = NULL;
        int i;

@@ -1110,6 +1130,17 @@
                                info("%s: found VFD endpoint", __FUNCTION__);
                }
        }
+
+       /* If we didn't find a vfd endpoint, and we have a next-gen LCD,
+        * use control urb instead of interrupt
+        */
+       if (! vfd_ep_found && cpu_to_le16(dev->descriptor.idProduct) == IMON_LCD_NEXTGEN )
+       {
+               tx_control = 1;
+               vfd_ep_found = TRUE;
+               if (debug)
+                       info("%s: guessing that LCD (0x0038) device uses control endpoint, not interface OUT endpoint", __FUNCTION__);
+       }

        /* Input endpoint is mandatory */
        if (!ir_ep_found) {
@@ -1272,6 +1303,7 @@
                context->vfd_supported = TRUE;
                context->tx_endpoint = tx_endpoint;
                context->tx_urb = tx_urb;
+               context->tx_control = tx_control;
        }
        context->plugin = plugin;


lcdproc-imon_0038.patch:
diff -ruN lcdproc-0.5.2-orig/server/drivers/Makefile lcdproc-0.5.2/server/drivers/Makefile
--- lcdproc-0.5.2-orig/server/drivers/Makefile       2008-02-25 06:25:37.448073128 -0500
+++ lcdproc-0.5.2/server/drivers/Makefile   2008-02-25 05:06:30.565910827 -0500
@@ -255,7 +255,7 @@
CYGPATH_W = echo
DARWIN_FALSE =
DARWIN_TRUE = #
-DEFS = -DHAVE_CONFIG_H
+DEFS = -DHAVE_CONFIG_H -DIS_LCD_0038
DEPDIR = .deps
DOT =
DOXYGEN =
diff -ruN lcdproc-0.5.2-orig/server/drivers/imonlcd.c lcdproc-0.5.2/server/drivers/imonlcd.c
--- lcdproc-0.5.2-orig/server/drivers/imonlcd.c      2008-02-25 06:24:16.603903431 -0500
+++ lcdproc-0.5.2/server/drivers/imonlcd.c  2008-02-25 05:20:15.907470511 -0500
@@ -87,12 +87,23 @@
/**
  * Just for convenience and to have the commands at one place.
  */
+
#define COMMANDS_SET_ICONS      (uint64_t) 0x0100000000000000
#define COMMANDS_SET_CONTRAST   (uint64_t) 0x0300000000000000
-#define COMMANDS_DISPLAY        (uint64_t) 0x5000000000000000
-#define COMMANDS_SHUTDOWN       (uint64_t) 0x5000000000000008
-#define COMMANDS_DISPLAY_ON     (uint64_t) 0x5000000000000040
-#define COMMANDS_CLEAR_ALARM    (uint64_t) 0x5100000000000000
+
+#ifdef IS_LCD_0038
+#define COMMANDS_DISPLAY_BYTE   (uint64_t) 0x8800000000000000
+#define COMMANDS_ALARM_BYTE     (uint64_t) 0x8a00000000000000
+#else
+#define COMMANDS_DISPLAY_BYTE   (uint64_t) 0x5000000000000000
+#define COMMANDS_ALARM_BYTE     (uint64_t) 0x5100000000000000
+#endif
+
+#define COMMANDS_DISPLAY        (uint64_t) (0x0000000000000000 | COMMANDS_DISPLAY_BYTE)
+#define COMMANDS_SHUTDOWN       (uint64_t) (0x0000000000000008 | COMMANDS_DISPLAY_BYTE)
+#define COMMANDS_DISPLAY_ON     (uint64_t) (0x0000000000000040 | COMMANDS_DISPLAY_BYTE)
+#define COMMANDS_CLEAR_ALARM    (uint64_t) (0x0000000000000000 | COMMANDS_ALARM_BYTE)
+
#define COMMANDS_SET_LINES0     (uint64_t) 0x1000000000000000
#define COMMANDS_SET_LINES1     (uint64_t) 0x1100000000000000
#define COMMANDS_SET_LINES2     (uint64_t) 0x1200000000000000
@@ -1074,7 +1085,7 @@
  */
static void send_command_data( uint64_t commandData, int fd )
{
-    if ((commandData & 0xFF00000000000000L) == 0x5000000000000000L) {
+    if ((commandData & 0xFF00000000000000L) == COMMANDS_DISPLAY_BYTE) {
            printf("%s: sending command: %lX\n", "imonlcd", commandData);
     }


madCoder

Joined: 24-Feb-2008 21:36
Posts: 12
Post 25-Feb-2008 22:47, Re: New iMON device, by RXM307
madCoder wrote:
RXM307, can you try this code, modifying the Product ID to be 0x0036 instead, and see if it works for you?


I gave this ago and tried running

./imon-poke 0x02 0x1c 0x02

But I get the error

usb_claim_interface(dh, iface) failed: [-16] could not claim interface 0: Device or resource busy


Is this because its already detecting the remote as a HID device (usb keyboard/mouse)?

Bus 001 Device 002: ID 15c2:0036 SoundGraph Inc.
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0         8
  idVendor           0x15c2 SoundGraph Inc.
  idProduct          0x0036
  bcdDevice            0.01
  iManufacturer           0
  iProduct                0
  iSerial                 0
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           59
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Devices
      bInterfaceSubClass      0 No Subclass
      bInterfaceProtocol      2 Mouse
      iInterface              0
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.01
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength     121
         Report Descriptors:
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval              10
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Devices
      bInterfaceSubClass      0 No Subclass
      bInterfaceProtocol      0 None
      iInterface              0
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.00
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      50
         Report Descriptors:
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval              10
Device Status:     0x0000
  (Bus Powered)


RXM307

Joined: 25-Feb-2008 12:51
Posts: 14
Post 25-Feb-2008 23:02, Re: New iMON device, by SeiKeinFrosch
Hello everybody,

you see me ... completely puzzled. Yesterday I gave finally up to make the LCD device in my new GD01MXR work and decided to send back the case to the dealer. After the complete disassembly of the case and re-packaging, I just wanted to confirm if the VFD/LCD in a new case would finally work and stumbled over this new messages. And it seems that you have it working! I just wanted to bring the package to the parcel service...

So just to verify it before I re-re-pack the case and start assembling again: The device is now working properly for the 15c2:0038 when applying the patches? (Sorry, I cannot believe it...)

madCoder wrote:
My LCD device is now working properly with lcdproc, and even mythlcdserver! :D

Below are my patches for a 15c2:0038 iMON LCD device. Note that if you don't have a 0038 device, this won't work for you.


Did I mention things like "hero", "perfect" or "stunning"? :D

Bye,

Christoph


SeiKeinFrosch

Joined: 23-Feb-2008 22:53
Posts: 3
Post 26-Feb-2008 14:17, Re: New iMON device, by madCoder
RXM307 wrote:
But I get the error
usb_claim_interface(dh, iface) failed: [-16] could not claim interface 0: Device or resource busy
Is this because its already detecting the remote as a HID device (usb keyboard/mouse)?

Yeah, you'll need to have usbhid ignore it for that to work. If usbhid is compiled in as a module, add a quirks option line to your modules.conf. If it's compiled into the kernel, you can add the device ID to hid-quirks.c and recompile your kernel. Just google for: usbhid quirks hid_quirk_ignore.

Once that's no longer loading, cat /proc/bus/usb/devices and make sure the 15c2 device shows "driver=(none)", and then you can try the imon-poke program.


madCoder

Joined: 24-Feb-2008 21:36
Posts: 12
Display posts from previous:  Sort by  
Page 1 of 7 [ 69 posts ]
Post ReplyNew TopicPrint view
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum
cron

Search
Who is online
In total there is 1 user online:
  • 0 registered
  • 0 hidden
  • 1 guest
Users browsing this forum: No registered users and 1 guest
Statistics