Pages

Sunday, April 15, 2012

Before I go to bed, I want to share a linux device driver I wrote sometime back for an old Zichuan ZCC210N I2C compass. Unfortunately, it stopped working before I could test the driver. I don't have the tools to debug the module, but the driver compiles and loads fine. Since, this was one of the early compass modules available in hobby stores, I thought someone out there might find this code useful.


#include 
#include 
#include 
#include 

#define ZCC210_I2C_ADDRESS   0x60
#define ZCC210_DIRECTION_COMMAND 0X77
#define ZCC210_DRIVER_NAME   "zcc210"

/* Addresses to scan */
static const unsigned short normal_i2c[] = {ZCC210_I2C_ADDRESS, I2C_CLIENT_END};

/*Device interface functions*/
static s32 zcc210_read_direction(struct i2c_client *client)
{
    /* Read direction bytes*/
    return i2c_smbus_read_word_data(client, ZCC210_DIRECTION_COMMAND);
}

/*sysfs callback functions*/
static ssize_t show_values(struct device *dev, struct device_attribute *attr, char *buf)
{
 struct i2c_client *client = to_i2c_client(dev);

    s32 result = zcc210_read_direction(client);

    if(result > 0){
        return sprintf(buf, "%d\n",
                (s32)swab32((u32)result));
    }
    return result;
}

static DEVICE_ATTR(values, S_IRUGO, show_values, NULL);

//static struct i2c_board_info zcc210_i2c_board_info = {  
//   I2C_BOARD_INFO(ZCC210_DRIVER_NAME, ZCC210_I2C_ADDRESS),      
// };

static struct attribute *zcc210_attributes[] = {
 &dev_attr_values.attr, 
 NULL
};
 
static const struct attribute_group zcc210_attr_group = {
.attrs = zcc210_attributes,
};

static const struct i2c_device_id zcc210_id[] = {
    { ZCC210_DRIVER_NAME, 0},
    {}
};

static int zcc210_detect(struct i2c_client *client, struct i2c_board_info *info)
{ 
 if (client->addr != ZCC210_I2C_ADDRESS)
 return -ENODEV;
  
 strlcpy(info->type, ZCC210_DRIVER_NAME, I2C_NAME_SIZE);
 return 0;
}

static int zcc210_probe(struct i2c_client *client, const struct i2c_device_id *id)
{  
 int err;
 
    printk(KERN_INFO "%s: new instance found!\n", ZCC210_DRIVER_NAME);

 /* Register sysfs hooks */
 err = sysfs_create_group(&client->dev.kobj, &zcc210_attr_group);
 if (err)
 {
  return err;
 }

 return 0;
}

static int zcc210_remove(struct i2c_client *client)
{
 sysfs_remove_group(&client->dev.kobj, &zcc210_attr_group); 
    return 0;
}

static struct i2c_driver zcc210_driver ={
    .driver.name = ZCC210_DRIVER_NAME,
    .id_table = zcc210_id,
    .probe = zcc210_probe,
    .remove = zcc210_remove,

 .class = I2C_CLASS_HWMON,
 .detect = zcc210_detect,
 .address_list = normal_i2c,
};

static int __init zcc210_init(void)
{
    printk(KERN_INFO "%s: init!", ZCC210_DRIVER_NAME ); 
 return i2c_add_driver(&zcc210_driver);
}

static void __exit zcc210_exit(void)
{
    printk(KERN_INFO "%s: exit!", ZCC210_DRIVER_NAME );
 i2c_del_driver(&zcc210_driver);
}

MODULE_AUTHOR("Karthik S Prakash <karthik.s.prakash@yahoo.com");
MODULE_DESCRIPTION("Zhichuan ZCC210 I2C Compass driver");
MODULE_LICENSE("GPL");

module_init(zcc210_init);
module_exit(zcc210_exit);


RichToolTip in C#

I wanted to display some important test results on Datagrid cells. But the default cell tooltip displays only plain texts. A rich text box would allow me to format my results in a easy to read form highlight PASS/FAIL etc.

I found a couple of useful links:
  1. MFC based: RichText Tool-tip Control
  2. An awesome HTML tooltip A Professional HTML Renderer You Will Use
Then I came across this - How to print the content of a RichTextBox control by using Visual C# - a printable rich text box. I remembered that while investigating the C# ToolTip class methods earlier, I had figured out it could display images... voila!

Below is the tool tip implementation I came with using the printable rich text box control above:

public class RichToolTip : ToolTip
    {
        Size toolTipSize = new Size();

        /// 
        /// Gets or sets the RichTextBoxPrintCtrl to show as tool tip
        /// 
        public RichTextBoxPrintCtrl RtbPCtrl { get; set; }

        public RichToolTip()
        {
            OwnerDraw = true;
            Popup += new PopupEventHandler(RichToolTip_Popup);
            Draw += new DrawToolTipEventHandler(RichToolTip_Draw);
            RtbPCtrl = new RichTextBoxPrintCtrl();
        }

        void RichToolTip_Draw(object sender, DrawToolTipEventArgs e)
        {
            e.Graphics.Clear(Color.White);

            using (Image image = new Bitmap(toolTipSize.Width, toolTipSize.Height))
            {
                using (Graphics g = Graphics.FromImage(image))
                {
                    RtbPCtrl.Print(0, RtbPCtrl.Text.Length, g, new Rectangle(RtbPCtrl.Location, toolTipSize));
                }
                e.Graphics.DrawImageUnscaled(image, e.Bounds);
            }
        }

        //Fires before the draw event. So set the tooltip size here.
        void RichToolTip_Popup(object sender, PopupEventArgs e)
        {
            using (Graphics g = RtbPCtrl.CreateGraphics())
            {
                toolTipSize = g.MeasureString(RtbPCtrl.Rtf.Trim(), RtbPCtrl.Font).ToSize();                
                e.ToolTipSize = toolTipSize;
            }
        }
    }