/drivers/media/video/hdpvr/hdpvr-i2c.c

https://bitbucket.org/abioy/linux · C · 145 lines · 103 code · 32 blank · 10 comment · 18 complexity · 30203acb58aa1f42f1bf0eba159c7b6a MD5 · raw file

  1. /*
  2. * Hauppauge HD PVR USB driver
  3. *
  4. * Copyright (C) 2008 Janne Grunau (j@jannau.net)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation, version 2.
  9. *
  10. */
  11. #include <linux/i2c.h>
  12. #include <linux/slab.h>
  13. #include "hdpvr.h"
  14. #define CTRL_READ_REQUEST 0xb8
  15. #define CTRL_WRITE_REQUEST 0x38
  16. #define REQTYPE_I2C_READ 0xb1
  17. #define REQTYPE_I2C_WRITE 0xb0
  18. #define REQTYPE_I2C_WRITE_STATT 0xd0
  19. static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr,
  20. char *data, int len)
  21. {
  22. int ret;
  23. char *buf = kmalloc(len, GFP_KERNEL);
  24. if (!buf)
  25. return -ENOMEM;
  26. ret = usb_control_msg(dev->udev,
  27. usb_rcvctrlpipe(dev->udev, 0),
  28. REQTYPE_I2C_READ, CTRL_READ_REQUEST,
  29. 0x100|addr, 0, buf, len, 1000);
  30. if (ret == len) {
  31. memcpy(data, buf, len);
  32. ret = 0;
  33. } else if (ret >= 0)
  34. ret = -EIO;
  35. kfree(buf);
  36. return ret;
  37. }
  38. static int hdpvr_i2c_write(struct hdpvr_device *dev, unsigned char addr,
  39. char *data, int len)
  40. {
  41. int ret;
  42. char *buf = kmalloc(len, GFP_KERNEL);
  43. if (!buf)
  44. return -ENOMEM;
  45. memcpy(buf, data, len);
  46. ret = usb_control_msg(dev->udev,
  47. usb_sndctrlpipe(dev->udev, 0),
  48. REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
  49. 0x100|addr, 0, buf, len, 1000);
  50. if (ret < 0)
  51. goto error;
  52. ret = usb_control_msg(dev->udev,
  53. usb_rcvctrlpipe(dev->udev, 0),
  54. REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST,
  55. 0, 0, buf, 2, 1000);
  56. if (ret == 2)
  57. ret = 0;
  58. else if (ret >= 0)
  59. ret = -EIO;
  60. error:
  61. kfree(buf);
  62. return ret;
  63. }
  64. static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs,
  65. int num)
  66. {
  67. struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter);
  68. int retval = 0, i, addr;
  69. if (num <= 0)
  70. return 0;
  71. mutex_lock(&dev->i2c_mutex);
  72. for (i = 0; i < num && !retval; i++) {
  73. addr = msgs[i].addr << 1;
  74. if (msgs[i].flags & I2C_M_RD)
  75. retval = hdpvr_i2c_read(dev, addr, msgs[i].buf,
  76. msgs[i].len);
  77. else
  78. retval = hdpvr_i2c_write(dev, addr, msgs[i].buf,
  79. msgs[i].len);
  80. }
  81. mutex_unlock(&dev->i2c_mutex);
  82. return retval ? retval : num;
  83. }
  84. static u32 hdpvr_functionality(struct i2c_adapter *adapter)
  85. {
  86. return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
  87. }
  88. static struct i2c_algorithm hdpvr_algo = {
  89. .master_xfer = hdpvr_transfer,
  90. .functionality = hdpvr_functionality,
  91. };
  92. int hdpvr_register_i2c_adapter(struct hdpvr_device *dev)
  93. {
  94. struct i2c_adapter *i2c_adap;
  95. int retval = -ENOMEM;
  96. i2c_adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
  97. if (i2c_adap == NULL)
  98. goto error;
  99. strlcpy(i2c_adap->name, "Hauppauge HD PVR I2C",
  100. sizeof(i2c_adap->name));
  101. i2c_adap->algo = &hdpvr_algo;
  102. i2c_adap->class = I2C_CLASS_TV_ANALOG;
  103. i2c_adap->owner = THIS_MODULE;
  104. i2c_adap->dev.parent = &dev->udev->dev;
  105. i2c_set_adapdata(i2c_adap, dev);
  106. retval = i2c_add_adapter(i2c_adap);
  107. if (!retval)
  108. dev->i2c_adapter = i2c_adap;
  109. else
  110. kfree(i2c_adap);
  111. error:
  112. return retval;
  113. }