Share Pastebin
Guest
Public paste!

Untitled

By: a guest | Sep 8th, 2010 | Syntax: None | Size: 8.88 KB | Hits: 37 | Expires: Never
Copy text to clipboard
  1. /*
  2.     microp-ksc.c - i2c chip driver for microp-key
  3.  
  4.     Joe Hansche <madcoder@gmail.com>
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; version 2 of the License.
  9. */
  10.  
  11. #include <linux/module.h>
  12. #include <linux/init.h>
  13. #include <linux/slab.h>
  14. #include <linux/i2c.h>
  15. #include <linux/delay.h>
  16. #include <linux/mutex.h>
  17. #include <asm/io.h>
  18. #include <asm/gpio.h>
  19. #include <asm/mach-types.h>
  20. #include <linux/workqueue.h> /* for keyboard LED worker */
  21. #include <linux/microp-ksc.h>
  22.  
  23. static int micropksc_read(struct i2c_client *, uint8_t, uint8_t *, int);
  24. static int micropksc_write(struct i2c_client *, uint8_t *, int);
  25. static int micropksc_probe(struct i2c_client *, const struct i2c_device_id *id);
  26. static int __devexit micropksc_remove(struct i2c_client *);
  27.  
  28. #define MODULE_NAME "microp-ksc"
  29.  
  30. #define I2C_READ_RETRY_TIMES 10
  31. #define I2C_WRITE_RETRY_TIMES 10
  32.  
  33. #if 0
  34.  #define D(fmt, arg...) printk(KERN_DEBUG "[KSC] %s: " fmt "\n", __FUNCTION__, ## arg);
  35. #else
  36.  #define D(fmt, arg...) do {} while(0)
  37. #endif
  38.  
  39. static struct microp_ksc {
  40.         struct i2c_client *client;
  41.         struct mutex lock;
  42.         unsigned short version;
  43.         unsigned led_state:2;
  44.         struct work_struct work;
  45. } *micropksc_t = 0;
  46.  
  47. int micropksc_read_scancode(unsigned char *outkey, unsigned char *outdown)
  48. {
  49.         struct microp_ksc *data;
  50.         struct i2c_client *client;
  51.         unsigned char key, isdown;
  52.         uint8_t buffer[3] = "\0\0\0";
  53.  
  54.         if (!micropksc_t) {
  55.                 if (outkey)
  56.                         *outkey = -1;
  57.                 return -EAGAIN;
  58.         }
  59.  
  60.         data = micropksc_t;
  61.  
  62.         client = data->client;
  63.         key = 0;
  64.  
  65.         micropksc_read(client, MICROP_KSC_ID_SCANCODE, buffer, 2);
  66.  
  67.         key = buffer[0] & MICROP_KSC_SCANCODE_MASK;
  68.         isdown = (buffer[0] & MICROP_KSC_RELEASED_BIT) == 0;
  69.  
  70.         //TODO: Find out what channel 0x11 is for
  71.         //micropksc_read(client, MICROP_KSC_ID_MODIFIER, buffer, 2);
  72.         if (outkey)
  73.                 *outkey = key;
  74.         if (outdown)
  75.                 *outdown = isdown;
  76.  
  77.         return 0;
  78. }
  79. EXPORT_SYMBOL(micropksc_read_scancode);
  80.  
  81. int micropksc_read_scancode_kovsky(unsigned char *outkey, unsigned char *outdown, unsigned char *outclamshell)
  82. {
  83.         struct microp_ksc *data;
  84.         struct i2c_client *client;
  85.         unsigned char key, isdown, clamshell;
  86.         uint8_t buffer[3] = "\0\0\0";
  87.  
  88.         if (!micropksc_t) {
  89.                 if (outkey)
  90.                         *outkey = -1;
  91.                 return -EAGAIN;
  92.         }
  93.  
  94.         data = micropksc_t;
  95.  
  96.         client = data->client;
  97.         key = 0;
  98.  
  99.         micropksc_read(client, MICROP_KSC_ID_SCANCODE, buffer, 2);
  100.  
  101.         key = buffer[0] & MICROP_KSC_SCANCODE_MASK;
  102.         isdown = (buffer[0] & MICROP_KSC_RELEASED_BIT) == 0;
  103.  
  104.         micropksc_read(client, MICROP_KSC_ID_MODIFIER, buffer, 2);
  105.         clamshell = (buffer[1] & MICROP_KSC_RELEASED_BIT) == 0;
  106.  
  107.         if (outkey)
  108.                 *outkey = key;
  109.         if (outdown)
  110.                 *outdown = isdown;
  111.         if (outclamshell)
  112.                 *outclamshell = clamshell;
  113.  
  114.         return 0;
  115. }
  116. EXPORT_SYMBOL(micropksc_read_scancode_kovsky);
  117.  
  118. void micropksc_init_cam()
  119. {
  120.         struct microp_ksc *data;
  121.         struct i2c_client *client;
  122.         uint8_t buf[2] = { 0x14,0};
  123.  
  124.         data = micropksc_t;
  125.         if (!data) return;
  126.         client = data->client;
  127.  
  128.         printk(KERN_INFO MODULE_NAME ": Sending cam init\n");
  129.  
  130.         micropksc_write(client, buf, 2);
  131. }
  132.  
  133. int micropksc_set_led(unsigned int led, int on)
  134. {
  135.         struct microp_ksc *data;
  136.         struct i2c_client *client;
  137.         uint8_t buffer[3] = { MICROP_KSC_ID_LED, 0, 0 };
  138.  
  139.         if (!micropksc_t)
  140.                 return -EAGAIN;
  141.         if (led >= MICROP_KSC_LED_MAX)
  142.                 return -EINVAL;
  143.  
  144.         data = micropksc_t;
  145.         client = data->client;
  146.  
  147.         if (led == MICROP_KSC_LED_RESET)
  148.                 data->led_state = 0;
  149.         else if (on)
  150.                 data->led_state |= led;
  151.         else
  152.                 data->led_state &= ~led;
  153.  
  154.         buffer[1] = 0x16 - (data->led_state << 1);
  155.  
  156.         micropksc_write(client, buffer, 2);
  157.  
  158.         return 0;
  159. }
  160. EXPORT_SYMBOL(micropksc_set_led);
  161.  
  162. int micropksc_set_kbd_led_state(int on)
  163. {
  164.         printk(KERN_INFO MODULE_NAME ": micropksc_set_kbd_led_state (%d)\n", on);
  165.         struct microp_ksc *data;
  166.         struct i2c_client *client;
  167.  
  168.         data = micropksc_t;
  169.         client = data->client;
  170.  
  171.         uint8_t buffer_qwerty[10]={MICROP_KSC_ID_QWERTY_BRIGHTNESS_KOVS, on ? 0x60 : 0, on ? 0x40 : 0xFF, on ? 0x60 : 0,0,0,0,0,0,0};
  172.         micropksc_write(client, buffer_qwerty, 10);
  173.  
  174.         uint8_t buffer[3];
  175.         buffer[0]=MICROP_KSC_ID_QWERTY_ENABLE_KOVS;
  176.         buffer[1]=0;
  177.         buffer[2]=(uint8_t)on;
  178.         micropksc_write(client, buffer, 3);
  179.         return 0;
  180. };
  181. EXPORT_SYMBOL(micropksc_set_kbd_led_state);
  182.  
  183.  
  184. /**
  185.  * The i2c buffer holds all the keys that are pressed,
  186.  * even when microp-ksc isn't listening. It's safe to assume
  187.  * we don't care about those bytes, so we need to flush
  188.  * the i2c buffer by reading scancodes until it's empty.
  189.  */
  190. int micropksc_flush_buffer(void)
  191. {
  192.         unsigned char key;
  193.         int r, i;
  194.  
  195.         i = 0;
  196.  
  197.         if (!micropksc_t) {
  198.                 printk(KERN_WARNING MODULE_NAME ": not initialized yet..\n");
  199.                 return -EAGAIN;
  200.         }
  201.         if (machine_is_htckovsky()) {
  202.                 r = micropksc_read_scancode_kovsky(&key, 0, 0);
  203.         } else {
  204.                 r = micropksc_read_scancode(&key, 0);
  205.         }
  206.  
  207.         if (key != 0) {
  208.                 do {
  209.                         mdelay(5);
  210.                         if (machine_is_htckovsky()) {
  211.                                 r = micropksc_read_scancode_kovsky(&key, 0, 0);
  212.                         } else {
  213.                                 r = micropksc_read_scancode(&key, 0);
  214.                         }
  215.                 } while (++i < 50 && key != 0);
  216.                 printk(KERN_INFO MODULE_NAME ": Keyboard buffer was dirty! "
  217.                                       "Flushed %d byte(s) from buffer\n", i);
  218.         }
  219.         return i;
  220. }
  221. EXPORT_SYMBOL(micropksc_flush_buffer);
  222.  
  223. static int micropksc_remove(struct i2c_client *client)
  224. {
  225.         struct microp_ksc *data;
  226.  
  227.         data = i2c_get_clientdata(client);
  228.  
  229.         kfree(data);
  230.         return 0;
  231. }
  232.  
  233. static int micropksc_probe(struct i2c_client *client, const struct i2c_device_id *id)
  234. {
  235.         struct microp_ksc *data;
  236.         uint8_t buf[3] = { 0, 0, 0 };
  237.  
  238.         printk(KERN_INFO MODULE_NAME ": Initializing MicroP-KEY chip driver at addr: 0x%02x\n", client->addr);
  239.  
  240.         if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
  241.                 printk(KERN_ERR MODULE_NAME ": i2c bus not supported\n");
  242.                 return -EINVAL;
  243.         }
  244.  
  245.         data = kzalloc(sizeof *data, GFP_KERNEL);
  246.         if (data < 0) {
  247.                 printk(KERN_ERR MODULE_NAME ": Not enough memory\n");
  248.                 return -ENOMEM;
  249.         }
  250.  
  251.         micropksc_t = data;
  252.         data->client = client;
  253.         i2c_set_clientdata(client, data);
  254.  
  255.         // Read version
  256.         micropksc_read(client, MICROP_KSC_ID_VERSION, buf, 2);
  257.         data->version = buf[0] << 8 | buf[1];
  258.         //TODO: Check version against known good revisions, and fail if it's not supported
  259.  
  260.         micropksc_flush_buffer();
  261.  
  262.         printk(MODULE_NAME ": Initialized MicroP-KEY chip revision v%04x\n", data->version);
  263.         return 0;
  264. #if 0 // See TODO above
  265. fail:
  266.         kfree(data);
  267.         return -ENOSYS;
  268. #endif
  269. }
  270.  
  271. static int micropksc_write(struct i2c_client *client, uint8_t *sendbuf, int len)
  272. {
  273.         int rc;
  274.         int retry;
  275.  
  276.         struct i2c_msg msg[] = {
  277.                 {
  278.                         .addr = client->addr,
  279.                         .flags = 0,
  280.                         .len = len,
  281.                         .buf = sendbuf,
  282.                 },
  283.         };
  284.  
  285.         for (retry = 0; retry <= I2C_WRITE_RETRY_TIMES; retry++) {
  286.                 rc = i2c_transfer(client->adapter, msg, 1);
  287.                 if (rc == 1)
  288.                         return 0;
  289.                 msleep(10);
  290.                 printk(KERN_WARNING "micropksc, i2c write retry\n");
  291.         }
  292.         printk(KERN_ERR "micropksc_write, i2c_write_block retry over %d\n",
  293.                         I2C_WRITE_RETRY_TIMES);
  294.         return rc;
  295. }
  296.  
  297. static int micropksc_read(struct i2c_client *client, uint8_t id,
  298.                                                 uint8_t *recvbuf, int len)
  299. {
  300.         int retry;
  301.         int ret;
  302.         struct i2c_msg msgs[] = {
  303.                 {
  304.                         .addr = client->addr,
  305.                         .flags = 0,
  306.                         .len = 1,
  307.                         .buf = &id,
  308.                 },
  309.                 {
  310.                         .addr = client->addr,
  311.                         .flags = I2C_M_RD,
  312.                         .len = len,
  313.                         .buf = recvbuf,
  314.                 }
  315.         };
  316.         for (retry = 0; retry <= I2C_READ_RETRY_TIMES; retry++) {
  317.                 ret = i2c_transfer(client->adapter, msgs, 2);
  318.                 if (ret == 2)
  319.                         return 0;
  320.                 msleep(10);
  321.                 printk(KERN_WARNING "micropksc, i2c read retry\n");
  322.         }
  323.         dev_err(&client->dev, "i2c_read_block retry over %d\n",
  324.                         I2C_READ_RETRY_TIMES);
  325.         return -EIO;
  326. }
  327.  
  328. #if CONFIG_PM
  329. static int micropksc_suspend(struct i2c_client *client, pm_message_t mesg)
  330. {
  331.         D("suspending device...");
  332.         return 0;
  333. }
  334.  
  335. static int micropksc_resume(struct i2c_client *client)
  336. {
  337.         D("resuming device...");
  338.         return 0;
  339. }
  340. #else
  341.  #define micropksc_suspend NULL
  342.  #define micropksc_resume NULL
  343. #endif
  344.  
  345. static const struct i2c_device_id microp_ksc_ids[] = {
  346.         { "microp-ksc", 0 },
  347.         { }
  348. };
  349.  
  350. static struct i2c_driver micropksc_driver = {
  351.         .driver = {
  352.                 .name   = MODULE_NAME,
  353.                 .owner  = THIS_MODULE,
  354.         },
  355.         .id_table = microp_ksc_ids,
  356.         .probe = micropksc_probe,
  357.         .remove = micropksc_remove,
  358.         .suspend = micropksc_suspend,
  359.         .resume = micropksc_resume,
  360. };
  361.  
  362. static int __init micropksc_init(void)
  363. {
  364.         micropksc_t = NULL;
  365.         printk(KERN_INFO "microp-ksc: Registering MicroP-KEY driver\n");
  366.  
  367.         return i2c_add_driver(&micropksc_driver);
  368. }
  369.  
  370. static void __exit micropksc_exit(void)
  371. {
  372.         printk(KERN_INFO "microp-ksc: Unregistered MicroP-KEY driver\n");
  373.         i2c_del_driver(&micropksc_driver);
  374. }
  375.  
  376. MODULE_AUTHOR("Joe Hansche <madcoder@gmail.com>");
  377. MODULE_DESCRIPTION("MicroP-KEY chip driver");
  378. MODULE_LICENSE("GPL");
  379. MODULE_VERSION("0.1");
  380.  
  381. module_init(micropksc_init);
  382. module_exit(micropksc_exit);