You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

usbnet.c 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*
  2. * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. */
  19. FILE_LICENCE ( GPL2_OR_LATER );
  20. #include <string.h>
  21. #include <errno.h>
  22. #include <ipxe/usb.h>
  23. #include <ipxe/usbnet.h>
  24. /** @file
  25. *
  26. * USB network devices
  27. *
  28. * USB network devices use a variety of packet formats and interface
  29. * descriptors, but tend to have several features in common:
  30. *
  31. * - a single interrupt endpoint using the generic refill mechanism
  32. *
  33. * - a single bulk IN endpoint using the generic refill mechanism
  34. *
  35. * - a single bulk OUT endpoint
  36. *
  37. * - optional use of an alternate setting to enable the data interface
  38. *
  39. */
  40. /**
  41. * Open USB network device
  42. *
  43. * @v usbnet USB network device
  44. * @ret rc Return status code
  45. */
  46. int usbnet_open ( struct usbnet_device *usbnet ) {
  47. struct usb_device *usb = usbnet->func->usb;
  48. int rc;
  49. /* Open interrupt endpoint */
  50. if ( ( rc = usb_endpoint_open ( &usbnet->intr ) ) != 0 ) {
  51. DBGC ( usbnet, "USBNET %s could not open interrupt: %s\n",
  52. usbnet->func->name, strerror ( rc ) );
  53. goto err_open_intr;
  54. }
  55. /* Refill interrupt endpoint */
  56. if ( ( rc = usb_refill ( &usbnet->intr ) ) != 0 ) {
  57. DBGC ( usbnet, "USBNET %s could not refill interrupt: %s\n",
  58. usbnet->func->name, strerror ( rc ) );
  59. goto err_refill_intr;
  60. }
  61. /* Select alternate setting for data interface, if applicable */
  62. if ( usbnet->alternate &&
  63. ( ( rc = usb_set_interface ( usb, usbnet->data,
  64. usbnet->alternate ) ) != 0 ) ) {
  65. DBGC ( usbnet, "USBNET %s could not set alternate interface "
  66. "%d: %s\n", usbnet->func->name, usbnet->alternate,
  67. strerror ( rc ) );
  68. goto err_set_interface;
  69. }
  70. /* Open bulk IN endpoint */
  71. if ( ( rc = usb_endpoint_open ( &usbnet->in ) ) != 0 ) {
  72. DBGC ( usbnet, "USBNET %s could not open bulk IN: %s\n",
  73. usbnet->func->name, strerror ( rc ) );
  74. goto err_open_in;
  75. }
  76. /* Open bulk OUT endpoint */
  77. if ( ( rc = usb_endpoint_open ( &usbnet->out ) ) != 0 ) {
  78. DBGC ( usbnet, "USBNET %s could not open bulk OUT: %s\n",
  79. usbnet->func->name, strerror ( rc ) );
  80. goto err_open_out;
  81. }
  82. /* Refill bulk IN endpoint */
  83. if ( ( rc = usb_refill ( &usbnet->in ) ) != 0 ) {
  84. DBGC ( usbnet, "USBNET %s could not refill bulk IN: %s\n",
  85. usbnet->func->name, strerror ( rc ) );
  86. goto err_refill_in;
  87. }
  88. return 0;
  89. err_refill_in:
  90. usb_endpoint_close ( &usbnet->out );
  91. err_open_out:
  92. usb_endpoint_close ( &usbnet->in );
  93. err_open_in:
  94. if ( usbnet->alternate )
  95. usb_set_interface ( usb, usbnet->data, 0 );
  96. err_set_interface:
  97. err_refill_intr:
  98. usb_endpoint_close ( &usbnet->intr );
  99. err_open_intr:
  100. return rc;
  101. }
  102. /**
  103. * Close USB network device
  104. *
  105. * @v usbnet USB network device
  106. */
  107. void usbnet_close ( struct usbnet_device *usbnet ) {
  108. struct usb_device *usb = usbnet->func->usb;
  109. /* Close bulk OUT endpoint */
  110. usb_endpoint_close ( &usbnet->out );
  111. /* Close bulk IN endpoint */
  112. usb_endpoint_close ( &usbnet->in );
  113. /* Reset alternate setting for data interface, if applicable */
  114. if ( usbnet->alternate )
  115. usb_set_interface ( usb, usbnet->data, 0 );
  116. /* Close interrupt endpoint */
  117. usb_endpoint_close ( &usbnet->intr );
  118. }
  119. /**
  120. * Refill USB network device bulk IN and interrupt endpoints
  121. *
  122. * @v usbnet USB network device
  123. * @ret rc Return status code
  124. */
  125. int usbnet_refill ( struct usbnet_device *usbnet ) {
  126. int rc;
  127. /* Refill bulk IN endpoint */
  128. if ( ( rc = usb_refill ( &usbnet->in ) ) != 0 )
  129. return rc;
  130. /* Refill interrupt endpoint */
  131. if ( ( rc = usb_refill ( &usbnet->intr ) ) != 0 )
  132. return rc;
  133. return 0;
  134. }
  135. /**
  136. * Describe communications interface and interrupt endpoint
  137. *
  138. * @v usbnet USB network device
  139. * @v config Configuration descriptor
  140. * @ret rc Return status code
  141. */
  142. static int usbnet_comms_describe ( struct usbnet_device *usbnet,
  143. struct usb_configuration_descriptor *config){
  144. struct usb_interface_descriptor *desc;
  145. unsigned int comms;
  146. unsigned int i;
  147. int rc;
  148. /* Iterate over all available interfaces */
  149. for ( i = 0 ; i < usbnet->func->count ; i++ ) {
  150. /* Get interface number */
  151. comms = usbnet->func->interface[i];
  152. /* Locate interface descriptor */
  153. desc = usb_interface_descriptor ( config, comms, 0 );
  154. if ( ! desc )
  155. continue;
  156. /* Describe interrupt endpoint */
  157. if ( ( rc = usb_endpoint_described ( &usbnet->intr, config,
  158. desc, USB_INTERRUPT,
  159. 0 ) ) != 0 )
  160. continue;
  161. /* Record communications interface */
  162. usbnet->comms = comms;
  163. DBGC ( usbnet, "USBNET %s found communications interface %d\n",
  164. usbnet->func->name, comms );
  165. return 0;
  166. }
  167. DBGC ( usbnet, "USBNET %s found no communications interface\n",
  168. usbnet->func->name );
  169. return -ENOENT;
  170. }
  171. /**
  172. * Describe data interface and bulk endpoints
  173. *
  174. * @v usbnet USB network device
  175. * @v config Configuration descriptor
  176. * @ret rc Return status code
  177. */
  178. static int usbnet_data_describe ( struct usbnet_device *usbnet,
  179. struct usb_configuration_descriptor *config ){
  180. struct usb_interface_descriptor *desc;
  181. unsigned int data;
  182. unsigned int alt;
  183. unsigned int i;
  184. int rc;
  185. /* Iterate over all available interfaces */
  186. for ( i = 0 ; i < usbnet->func->count ; i++ ) {
  187. /* Get interface number */
  188. data = usbnet->func->interface[i];
  189. /* Iterate over all existent alternate settings */
  190. for ( alt = 0 ; ; alt++ ) {
  191. /* Locate interface descriptor */
  192. desc = usb_interface_descriptor ( config, data, alt );
  193. if ( ! desc )
  194. break;
  195. /* Describe bulk IN endpoint */
  196. if ( ( rc = usb_endpoint_described ( &usbnet->in,
  197. config, desc,
  198. USB_BULK_IN,
  199. 0 ) ) != 0 )
  200. continue;
  201. /* Describe bulk OUT endpoint */
  202. if ( ( rc = usb_endpoint_described ( &usbnet->out,
  203. config, desc,
  204. USB_BULK_OUT,
  205. 0 ) ) != 0 )
  206. continue;
  207. /* Record data interface and alternate setting */
  208. usbnet->data = data;
  209. usbnet->alternate = alt;
  210. DBGC ( usbnet, "USBNET %s found data interface %d",
  211. usbnet->func->name, data );
  212. if ( alt )
  213. DBGC ( usbnet, " using alternate %d", alt );
  214. DBGC ( usbnet, "\n" );
  215. return 0;
  216. }
  217. }
  218. DBGC ( usbnet, "USBNET %s found no data interface\n",
  219. usbnet->func->name );
  220. return -ENOENT;
  221. }
  222. /**
  223. * Describe USB network device interfaces
  224. *
  225. * @v usbnet USB network device
  226. * @v config Configuration descriptor
  227. * @ret rc Return status code
  228. */
  229. int usbnet_describe ( struct usbnet_device *usbnet,
  230. struct usb_configuration_descriptor *config ) {
  231. int rc;
  232. /* Describe communications interface */
  233. if ( ( rc = usbnet_comms_describe ( usbnet, config ) ) != 0 )
  234. return rc;
  235. /* Describe data interface */
  236. if ( ( rc = usbnet_data_describe ( usbnet, config ) ) != 0 )
  237. return rc;
  238. return 0;
  239. }