endpoint.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*
  2. * drivers/usb/core/endpoint.c
  3. *
  4. * (C) Copyright 2002,2004,2006 Greg Kroah-Hartman
  5. * (C) Copyright 2002,2004 IBM Corp.
  6. * (C) Copyright 2006 Novell Inc.
  7. *
  8. * Endpoint sysfs stuff
  9. *
  10. */
  11. #include <linux/kernel.h>
  12. #include <linux/usb.h>
  13. #include "usb.h"
  14. /* endpoint stuff */
  15. struct ep_object {
  16. struct usb_endpoint_descriptor *desc;
  17. struct usb_device *udev;
  18. struct kobject kobj;
  19. };
  20. #define to_ep_object(_kobj) \
  21. container_of(_kobj, struct ep_object, kobj)
  22. struct ep_attribute {
  23. struct attribute attr;
  24. ssize_t (*show)(struct usb_device *,
  25. struct usb_endpoint_descriptor *, char *);
  26. };
  27. #define to_ep_attribute(_attr) \
  28. container_of(_attr, struct ep_attribute, attr)
  29. #define EP_ATTR(_name) \
  30. struct ep_attribute ep_##_name = { \
  31. .attr = {.name = #_name, .owner = THIS_MODULE, \
  32. .mode = S_IRUGO}, \
  33. .show = show_ep_##_name}
  34. #define usb_ep_attr(field, format_string) \
  35. static ssize_t show_ep_##field(struct usb_device *udev, \
  36. struct usb_endpoint_descriptor *desc, \
  37. char *buf) \
  38. { \
  39. return sprintf(buf, format_string, desc->field); \
  40. } \
  41. static EP_ATTR(field);
  42. usb_ep_attr(bLength, "%02x\n")
  43. usb_ep_attr(bEndpointAddress, "%02x\n")
  44. usb_ep_attr(bmAttributes, "%02x\n")
  45. usb_ep_attr(bInterval, "%02x\n")
  46. static ssize_t show_ep_wMaxPacketSize(struct usb_device *udev,
  47. struct usb_endpoint_descriptor *desc, char *buf)
  48. {
  49. return sprintf(buf, "%04x\n",
  50. le16_to_cpu(desc->wMaxPacketSize) & 0x07ff);
  51. }
  52. static EP_ATTR(wMaxPacketSize);
  53. static ssize_t show_ep_type(struct usb_device *udev,
  54. struct usb_endpoint_descriptor *desc, char *buf)
  55. {
  56. char *type = "unknown";
  57. switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
  58. case USB_ENDPOINT_XFER_CONTROL:
  59. type = "Control";
  60. break;
  61. case USB_ENDPOINT_XFER_ISOC:
  62. type = "Isoc";
  63. break;
  64. case USB_ENDPOINT_XFER_BULK:
  65. type = "Bulk";
  66. break;
  67. case USB_ENDPOINT_XFER_INT:
  68. type = "Interrupt";
  69. break;
  70. }
  71. return sprintf(buf, "%s\n", type);
  72. }
  73. static EP_ATTR(type);
  74. static ssize_t show_ep_interval(struct usb_device *udev,
  75. struct usb_endpoint_descriptor *desc, char *buf)
  76. {
  77. char unit;
  78. unsigned interval = 0;
  79. unsigned in;
  80. in = (desc->bEndpointAddress & USB_DIR_IN);
  81. switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
  82. case USB_ENDPOINT_XFER_CONTROL:
  83. if (udev->speed == USB_SPEED_HIGH) /* uframes per NAK */
  84. interval = desc->bInterval;
  85. break;
  86. case USB_ENDPOINT_XFER_ISOC:
  87. interval = 1 << (desc->bInterval - 1);
  88. break;
  89. case USB_ENDPOINT_XFER_BULK:
  90. if (udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */
  91. interval = desc->bInterval;
  92. break;
  93. case USB_ENDPOINT_XFER_INT:
  94. if (udev->speed == USB_SPEED_HIGH)
  95. interval = 1 << (desc->bInterval - 1);
  96. else
  97. interval = desc->bInterval;
  98. break;
  99. }
  100. interval *= (udev->speed == USB_SPEED_HIGH) ? 125 : 1000;
  101. if (interval % 1000)
  102. unit = 'u';
  103. else {
  104. unit = 'm';
  105. interval /= 1000;
  106. }
  107. return sprintf(buf, "%d%cs\n", interval, unit);
  108. }
  109. static EP_ATTR(interval);
  110. static ssize_t show_ep_direction(struct usb_device *udev,
  111. struct usb_endpoint_descriptor *desc, char *buf)
  112. {
  113. char *direction;
  114. if ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
  115. USB_ENDPOINT_XFER_CONTROL)
  116. direction = "both";
  117. else if (desc->bEndpointAddress & USB_DIR_IN)
  118. direction = "in";
  119. else
  120. direction = "out";
  121. return sprintf(buf, "%s\n", direction);
  122. }
  123. static EP_ATTR(direction);
  124. static struct attribute *ep_attrs[] = {
  125. &ep_bLength.attr,
  126. &ep_bEndpointAddress.attr,
  127. &ep_bmAttributes.attr,
  128. &ep_bInterval.attr,
  129. &ep_wMaxPacketSize.attr,
  130. &ep_type.attr,
  131. &ep_interval.attr,
  132. &ep_direction.attr,
  133. NULL,
  134. };
  135. static void ep_object_release(struct kobject *kobj)
  136. {
  137. kfree(to_ep_object(kobj));
  138. }
  139. static ssize_t ep_object_show(struct kobject *kobj, struct attribute *attr,
  140. char *buf)
  141. {
  142. struct ep_object *ep_obj = to_ep_object(kobj);
  143. struct ep_attribute *ep_attr = to_ep_attribute(attr);
  144. return (ep_attr->show)(ep_obj->udev, ep_obj->desc, buf);
  145. }
  146. static struct sysfs_ops ep_object_sysfs_ops = {
  147. .show = ep_object_show,
  148. };
  149. static struct kobj_type ep_object_ktype = {
  150. .release = ep_object_release,
  151. .sysfs_ops = &ep_object_sysfs_ops,
  152. .default_attrs = ep_attrs,
  153. };
  154. void usb_create_ep_files(struct device *parent,
  155. struct usb_host_endpoint *endpoint,
  156. struct usb_device *udev)
  157. {
  158. struct ep_object *ep_obj;
  159. struct kobject *kobj;
  160. ep_obj = kzalloc(sizeof(struct ep_object), GFP_KERNEL);
  161. if (!ep_obj)
  162. return;
  163. ep_obj->desc = &endpoint->desc;
  164. ep_obj->udev = udev;
  165. kobj = &ep_obj->kobj;
  166. kobject_set_name(kobj, "ep_%02x", endpoint->desc.bEndpointAddress);
  167. kobj->parent = &parent->kobj;
  168. kobj->ktype = &ep_object_ktype;
  169. /* Don't use kobject_register, because it generates a hotplug event */
  170. kobject_init(kobj);
  171. if (kobject_add(kobj) == 0)
  172. endpoint->kobj = kobj;
  173. else
  174. kobject_put(kobj);
  175. }
  176. void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
  177. {
  178. if (endpoint->kobj) {
  179. kobject_del(endpoint->kobj);
  180. kobject_put(endpoint->kobj);
  181. endpoint->kobj = NULL;
  182. }
  183. }