usbled.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * USB LED driver - 1.1
  3. *
  4. * Copyright (C) 2004 Greg Kroah-Hartman (greg@kroah.com)
  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/kernel.h>
  12. #include <linux/errno.h>
  13. #include <linux/init.h>
  14. #include <linux/slab.h>
  15. #include <linux/module.h>
  16. #include <linux/usb.h>
  17. #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com"
  18. #define DRIVER_DESC "USB LED Driver"
  19. #define VENDOR_ID 0x0fc5
  20. #define PRODUCT_ID 0x1223
  21. /* table of devices that work with this driver */
  22. static struct usb_device_id id_table [] = {
  23. { USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
  24. { },
  25. };
  26. MODULE_DEVICE_TABLE (usb, id_table);
  27. struct usb_led {
  28. struct usb_device * udev;
  29. unsigned char blue;
  30. unsigned char red;
  31. unsigned char green;
  32. };
  33. #define BLUE 0x04
  34. #define RED 0x02
  35. #define GREEN 0x01
  36. static void change_color(struct usb_led *led)
  37. {
  38. int retval;
  39. unsigned char color = 0x07;
  40. unsigned char *buffer;
  41. buffer = kmalloc(8, GFP_KERNEL);
  42. if (!buffer) {
  43. dev_err(&led->udev->dev, "out of memory\n");
  44. return;
  45. }
  46. if (led->blue)
  47. color &= ~(BLUE);
  48. if (led->red)
  49. color &= ~(RED);
  50. if (led->green)
  51. color &= ~(GREEN);
  52. dev_dbg(&led->udev->dev,
  53. "blue = %d, red = %d, green = %d, color = %.2x\n",
  54. led->blue, led->red, led->green, color);
  55. retval = usb_control_msg(led->udev,
  56. usb_sndctrlpipe(led->udev, 0),
  57. 0x12,
  58. 0xc8,
  59. (0x02 * 0x100) + 0x0a,
  60. (0x00 * 0x100) + color,
  61. buffer,
  62. 8,
  63. 2000);
  64. if (retval)
  65. dev_dbg(&led->udev->dev, "retval = %d\n", retval);
  66. kfree(buffer);
  67. }
  68. #define show_set(value) \
  69. static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
  70. { \
  71. struct usb_interface *intf = to_usb_interface(dev); \
  72. struct usb_led *led = usb_get_intfdata(intf); \
  73. \
  74. return sprintf(buf, "%d\n", led->value); \
  75. } \
  76. static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
  77. { \
  78. struct usb_interface *intf = to_usb_interface(dev); \
  79. struct usb_led *led = usb_get_intfdata(intf); \
  80. int temp = simple_strtoul(buf, NULL, 10); \
  81. \
  82. led->value = temp; \
  83. change_color(led); \
  84. return count; \
  85. } \
  86. static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
  87. show_set(blue);
  88. show_set(red);
  89. show_set(green);
  90. static int led_probe(struct usb_interface *interface, const struct usb_device_id *id)
  91. {
  92. struct usb_device *udev = interface_to_usbdev(interface);
  93. struct usb_led *dev = NULL;
  94. int retval = -ENOMEM;
  95. dev = kzalloc(sizeof(struct usb_led), GFP_KERNEL);
  96. if (dev == NULL) {
  97. dev_err(&interface->dev, "Out of memory\n");
  98. goto error_mem;
  99. }
  100. dev->udev = usb_get_dev(udev);
  101. usb_set_intfdata (interface, dev);
  102. retval = device_create_file(&interface->dev, &dev_attr_blue);
  103. if (retval)
  104. goto error;
  105. retval = device_create_file(&interface->dev, &dev_attr_red);
  106. if (retval)
  107. goto error;
  108. retval = device_create_file(&interface->dev, &dev_attr_green);
  109. if (retval)
  110. goto error;
  111. dev_info(&interface->dev, "USB LED device now attached\n");
  112. return 0;
  113. error:
  114. device_remove_file(&interface->dev, &dev_attr_blue);
  115. device_remove_file(&interface->dev, &dev_attr_red);
  116. device_remove_file(&interface->dev, &dev_attr_green);
  117. usb_set_intfdata (interface, NULL);
  118. usb_put_dev(dev->udev);
  119. kfree(dev);
  120. error_mem:
  121. return retval;
  122. }
  123. static void led_disconnect(struct usb_interface *interface)
  124. {
  125. struct usb_led *dev;
  126. dev = usb_get_intfdata (interface);
  127. device_remove_file(&interface->dev, &dev_attr_blue);
  128. device_remove_file(&interface->dev, &dev_attr_red);
  129. device_remove_file(&interface->dev, &dev_attr_green);
  130. /* first remove the files, then set the pointer to NULL */
  131. usb_set_intfdata (interface, NULL);
  132. usb_put_dev(dev->udev);
  133. kfree(dev);
  134. dev_info(&interface->dev, "USB LED now disconnected\n");
  135. }
  136. static struct usb_driver led_driver = {
  137. .name = "usbled",
  138. .probe = led_probe,
  139. .disconnect = led_disconnect,
  140. .id_table = id_table,
  141. };
  142. static int __init usb_led_init(void)
  143. {
  144. int retval = 0;
  145. retval = usb_register(&led_driver);
  146. if (retval)
  147. err("usb_register failed. Error number %d", retval);
  148. return retval;
  149. }
  150. static void __exit usb_led_exit(void)
  151. {
  152. usb_deregister(&led_driver);
  153. }
  154. module_init (usb_led_init);
  155. module_exit (usb_led_exit);
  156. MODULE_AUTHOR(DRIVER_AUTHOR);
  157. MODULE_DESCRIPTION(DRIVER_DESC);
  158. MODULE_LICENSE("GPL");