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.

ecm.c 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. /*
  2. * Copyright (C) 2014 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. * You can also choose to distribute this program under the terms of
  20. * the Unmodified Binary Distribution Licence (as given in the file
  21. * COPYING.UBDL), provided that you have satisfied its requirements.
  22. */
  23. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  24. #include <stdint.h>
  25. #include <errno.h>
  26. #include <ipxe/netdevice.h>
  27. #include <ipxe/ethernet.h>
  28. #include <ipxe/if_ether.h>
  29. #include <ipxe/base16.h>
  30. #include <ipxe/profile.h>
  31. #include <ipxe/usb.h>
  32. #include "ecm.h"
  33. /** @file
  34. *
  35. * CDC-ECM USB Ethernet driver
  36. *
  37. */
  38. /** Interrupt completion profiler */
  39. static struct profiler ecm_intr_profiler __profiler =
  40. { .name = "ecm.intr" };
  41. /** Bulk IN completion profiler */
  42. static struct profiler ecm_in_profiler __profiler =
  43. { .name = "ecm.in" };
  44. /** Bulk OUT profiler */
  45. static struct profiler ecm_out_profiler __profiler =
  46. { .name = "ecm.out" };
  47. /******************************************************************************
  48. *
  49. * Ethernet functional descriptor
  50. *
  51. ******************************************************************************
  52. */
  53. /**
  54. * Locate Ethernet functional descriptor
  55. *
  56. * @v config Configuration descriptor
  57. * @v interface Interface descriptor
  58. * @ret desc Descriptor, or NULL if not found
  59. */
  60. struct ecm_ethernet_descriptor *
  61. ecm_ethernet_descriptor ( struct usb_configuration_descriptor *config,
  62. struct usb_interface_descriptor *interface ) {
  63. struct ecm_ethernet_descriptor *desc;
  64. for_each_interface_descriptor ( desc, config, interface ) {
  65. if ( ( desc->header.type == USB_CS_INTERFACE_DESCRIPTOR ) &&
  66. ( desc->subtype == CDC_SUBTYPE_ETHERNET ) )
  67. return desc;
  68. }
  69. return NULL;
  70. }
  71. /**
  72. * Get hardware MAC address
  73. *
  74. * @v usb USB device
  75. * @v desc Ethernet functional descriptor
  76. * @v hw_addr Hardware address to fill in
  77. * @ret rc Return status code
  78. */
  79. int ecm_fetch_mac ( struct usb_device *usb,
  80. struct ecm_ethernet_descriptor *desc, uint8_t *hw_addr ) {
  81. char buf[ base16_encoded_len ( ETH_ALEN ) + 1 /* NUL */ ];
  82. int len;
  83. int rc;
  84. /* Fetch MAC address string */
  85. len = usb_get_string_descriptor ( usb, desc->mac, 0, buf,
  86. sizeof ( buf ) );
  87. if ( len < 0 ) {
  88. rc = len;
  89. return rc;
  90. }
  91. /* Sanity check */
  92. if ( len != ( ( int ) ( sizeof ( buf ) - 1 /* NUL */ ) ) ) {
  93. DBGC ( usb, "USB %s has invalid ECM MAC \"%s\"\n",
  94. usb->name, buf );
  95. return -EINVAL;
  96. }
  97. /* Decode MAC address */
  98. len = base16_decode ( buf, hw_addr, ETH_ALEN );
  99. if ( len < 0 ) {
  100. rc = len;
  101. DBGC ( usb, "USB %s could not decode ECM MAC \"%s\": %s\n",
  102. usb->name, buf, strerror ( rc ) );
  103. return rc;
  104. }
  105. return 0;
  106. }
  107. /******************************************************************************
  108. *
  109. * CDC-ECM communications interface
  110. *
  111. ******************************************************************************
  112. */
  113. /**
  114. * Complete interrupt transfer
  115. *
  116. * @v ep USB endpoint
  117. * @v iobuf I/O buffer
  118. * @v rc Completion status code
  119. */
  120. static void ecm_intr_complete ( struct usb_endpoint *ep,
  121. struct io_buffer *iobuf, int rc ) {
  122. struct ecm_device *ecm = container_of ( ep, struct ecm_device,
  123. usbnet.intr );
  124. struct net_device *netdev = ecm->netdev;
  125. struct usb_setup_packet *message;
  126. size_t len = iob_len ( iobuf );
  127. /* Profile completions */
  128. profile_start ( &ecm_intr_profiler );
  129. /* Ignore packets cancelled when the endpoint closes */
  130. if ( ! ep->open )
  131. goto ignore;
  132. /* Drop packets with errors */
  133. if ( rc != 0 ) {
  134. DBGC ( ecm, "ECM %p interrupt failed: %s\n",
  135. ecm, strerror ( rc ) );
  136. DBGC_HDA ( ecm, 0, iobuf->data, iob_len ( iobuf ) );
  137. goto error;
  138. }
  139. /* Extract message header */
  140. if ( len < sizeof ( *message ) ) {
  141. DBGC ( ecm, "ECM %p underlength interrupt:\n", ecm );
  142. DBGC_HDA ( ecm, 0, iobuf->data, iob_len ( iobuf ) );
  143. rc = -EINVAL;
  144. goto error;
  145. }
  146. message = iobuf->data;
  147. /* Parse message header */
  148. switch ( message->request ) {
  149. case cpu_to_le16 ( CDC_NETWORK_CONNECTION ) :
  150. if ( message->value && ! netdev_link_ok ( netdev ) ) {
  151. DBGC ( ecm, "ECM %p link up\n", ecm );
  152. netdev_link_up ( netdev );
  153. } else if ( netdev_link_ok ( netdev ) && ! message->value ) {
  154. DBGC ( ecm, "ECM %p link down\n", ecm );
  155. netdev_link_down ( netdev );
  156. }
  157. break;
  158. case cpu_to_le16 ( CDC_CONNECTION_SPEED_CHANGE ) :
  159. /* Ignore */
  160. break;
  161. default:
  162. DBGC ( ecm, "ECM %p unrecognised interrupt:\n", ecm );
  163. DBGC_HDA ( ecm, 0, iobuf->data, iob_len ( iobuf ) );
  164. rc = -ENOTSUP;
  165. goto error;
  166. }
  167. /* Free I/O buffer */
  168. free_iob ( iobuf );
  169. profile_stop ( &ecm_intr_profiler );
  170. return;
  171. error:
  172. netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
  173. ignore:
  174. free_iob ( iobuf );
  175. return;
  176. }
  177. /** Interrupt endpoint operations */
  178. static struct usb_endpoint_driver_operations ecm_intr_operations = {
  179. .complete = ecm_intr_complete,
  180. };
  181. /******************************************************************************
  182. *
  183. * CDC-ECM data interface
  184. *
  185. ******************************************************************************
  186. */
  187. /**
  188. * Complete bulk IN transfer
  189. *
  190. * @v ep USB endpoint
  191. * @v iobuf I/O buffer
  192. * @v rc Completion status code
  193. */
  194. static void ecm_in_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
  195. int rc ) {
  196. struct ecm_device *ecm = container_of ( ep, struct ecm_device,
  197. usbnet.in );
  198. struct net_device *netdev = ecm->netdev;
  199. /* Profile receive completions */
  200. profile_start ( &ecm_in_profiler );
  201. /* Ignore packets cancelled when the endpoint closes */
  202. if ( ! ep->open )
  203. goto ignore;
  204. /* Record USB errors against the network device */
  205. if ( rc != 0 ) {
  206. DBGC ( ecm, "ECM %p bulk IN failed: %s\n",
  207. ecm, strerror ( rc ) );
  208. goto error;
  209. }
  210. /* Hand off to network stack */
  211. netdev_rx ( netdev, iob_disown ( iobuf ) );
  212. profile_stop ( &ecm_in_profiler );
  213. return;
  214. error:
  215. netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
  216. ignore:
  217. free_iob ( iobuf );
  218. }
  219. /** Bulk IN endpoint operations */
  220. static struct usb_endpoint_driver_operations ecm_in_operations = {
  221. .complete = ecm_in_complete,
  222. };
  223. /**
  224. * Transmit packet
  225. *
  226. * @v ecm CDC-ECM device
  227. * @v iobuf I/O buffer
  228. * @ret rc Return status code
  229. */
  230. static int ecm_out_transmit ( struct ecm_device *ecm,
  231. struct io_buffer *iobuf ) {
  232. int rc;
  233. /* Profile transmissions */
  234. profile_start ( &ecm_out_profiler );
  235. /* Enqueue I/O buffer */
  236. if ( ( rc = usb_stream ( &ecm->usbnet.out, iobuf, 1 ) ) != 0 )
  237. return rc;
  238. profile_stop ( &ecm_out_profiler );
  239. return 0;
  240. }
  241. /**
  242. * Complete bulk OUT transfer
  243. *
  244. * @v ep USB endpoint
  245. * @v iobuf I/O buffer
  246. * @v rc Completion status code
  247. */
  248. static void ecm_out_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
  249. int rc ) {
  250. struct ecm_device *ecm = container_of ( ep, struct ecm_device,
  251. usbnet.out );
  252. struct net_device *netdev = ecm->netdev;
  253. /* Report TX completion */
  254. netdev_tx_complete_err ( netdev, iobuf, rc );
  255. }
  256. /** Bulk OUT endpoint operations */
  257. static struct usb_endpoint_driver_operations ecm_out_operations = {
  258. .complete = ecm_out_complete,
  259. };
  260. /******************************************************************************
  261. *
  262. * Network device interface
  263. *
  264. ******************************************************************************
  265. */
  266. /**
  267. * Open network device
  268. *
  269. * @v netdev Network device
  270. * @ret rc Return status code
  271. */
  272. static int ecm_open ( struct net_device *netdev ) {
  273. struct ecm_device *ecm = netdev->priv;
  274. struct usb_device *usb = ecm->usb;
  275. unsigned int filter;
  276. int rc;
  277. /* Open USB network device */
  278. if ( ( rc = usbnet_open ( &ecm->usbnet ) ) != 0 ) {
  279. DBGC ( ecm, "ECM %p could not open: %s\n",
  280. ecm, strerror ( rc ) );
  281. goto err_open;
  282. }
  283. /* Set packet filter */
  284. filter = ( ECM_PACKET_TYPE_PROMISCUOUS |
  285. ECM_PACKET_TYPE_ALL_MULTICAST |
  286. ECM_PACKET_TYPE_DIRECTED |
  287. ECM_PACKET_TYPE_BROADCAST );
  288. if ( ( rc = usb_control ( usb, ECM_SET_ETHERNET_PACKET_FILTER,
  289. filter, ecm->usbnet.comms, NULL, 0 ) ) != 0 ){
  290. DBGC ( ecm, "ECM %p could not set packet filter: %s\n",
  291. ecm, strerror ( rc ) );
  292. goto err_set_filter;
  293. }
  294. return 0;
  295. err_set_filter:
  296. usbnet_close ( &ecm->usbnet );
  297. err_open:
  298. return rc;
  299. }
  300. /**
  301. * Close network device
  302. *
  303. * @v netdev Network device
  304. */
  305. static void ecm_close ( struct net_device *netdev ) {
  306. struct ecm_device *ecm = netdev->priv;
  307. /* Close USB network device */
  308. usbnet_close ( &ecm->usbnet );
  309. }
  310. /**
  311. * Transmit packet
  312. *
  313. * @v netdev Network device
  314. * @v iobuf I/O buffer
  315. * @ret rc Return status code
  316. */
  317. static int ecm_transmit ( struct net_device *netdev,
  318. struct io_buffer *iobuf ) {
  319. struct ecm_device *ecm = netdev->priv;
  320. int rc;
  321. /* Transmit packet */
  322. if ( ( rc = ecm_out_transmit ( ecm, iobuf ) ) != 0 )
  323. return rc;
  324. return 0;
  325. }
  326. /**
  327. * Poll for completed and received packets
  328. *
  329. * @v netdev Network device
  330. */
  331. static void ecm_poll ( struct net_device *netdev ) {
  332. struct ecm_device *ecm = netdev->priv;
  333. int rc;
  334. /* Poll USB bus */
  335. usb_poll ( ecm->bus );
  336. /* Refill endpoints */
  337. if ( ( rc = usbnet_refill ( &ecm->usbnet ) ) != 0 )
  338. netdev_rx_err ( netdev, NULL, rc );
  339. }
  340. /** CDC-ECM network device operations */
  341. static struct net_device_operations ecm_operations = {
  342. .open = ecm_open,
  343. .close = ecm_close,
  344. .transmit = ecm_transmit,
  345. .poll = ecm_poll,
  346. };
  347. /******************************************************************************
  348. *
  349. * USB interface
  350. *
  351. ******************************************************************************
  352. */
  353. /**
  354. * Probe device
  355. *
  356. * @v func USB function
  357. * @v config Configuration descriptor
  358. * @ret rc Return status code
  359. */
  360. static int ecm_probe ( struct usb_function *func,
  361. struct usb_configuration_descriptor *config ) {
  362. struct usb_device *usb = func->usb;
  363. struct net_device *netdev;
  364. struct ecm_device *ecm;
  365. struct usb_interface_descriptor *comms;
  366. struct ecm_ethernet_descriptor *ethernet;
  367. int rc;
  368. /* Allocate and initialise structure */
  369. netdev = alloc_etherdev ( sizeof ( *ecm ) );
  370. if ( ! netdev ) {
  371. rc = -ENOMEM;
  372. goto err_alloc;
  373. }
  374. netdev_init ( netdev, &ecm_operations );
  375. netdev->dev = &func->dev;
  376. ecm = netdev->priv;
  377. memset ( ecm, 0, sizeof ( *ecm ) );
  378. ecm->usb = usb;
  379. ecm->bus = usb->port->hub->bus;
  380. ecm->netdev = netdev;
  381. usbnet_init ( &ecm->usbnet, func, &ecm_intr_operations,
  382. &ecm_in_operations, &ecm_out_operations );
  383. usb_refill_init ( &ecm->usbnet.intr, 0, 0, ECM_INTR_MAX_FILL );
  384. usb_refill_init ( &ecm->usbnet.in, 0, ECM_IN_MTU, ECM_IN_MAX_FILL );
  385. DBGC ( ecm, "ECM %p on %s\n", ecm, func->name );
  386. /* Describe USB network device */
  387. if ( ( rc = usbnet_describe ( &ecm->usbnet, config ) ) != 0 ) {
  388. DBGC ( ecm, "ECM %p could not describe: %s\n",
  389. ecm, strerror ( rc ) );
  390. goto err_describe;
  391. }
  392. /* Locate Ethernet descriptor */
  393. comms = usb_interface_descriptor ( config, ecm->usbnet.comms, 0 );
  394. assert ( comms != NULL );
  395. ethernet = ecm_ethernet_descriptor ( config, comms );
  396. if ( ! ethernet ) {
  397. DBGC ( ecm, "ECM %p has no Ethernet descriptor\n", ecm );
  398. rc = -EINVAL;
  399. goto err_ethernet;
  400. }
  401. /* Fetch MAC address */
  402. if ( ( rc = ecm_fetch_mac ( usb, ethernet, netdev->hw_addr ) ) != 0 ) {
  403. DBGC ( ecm, "ECM %p could not fetch MAC address: %s\n",
  404. ecm, strerror ( rc ) );
  405. goto err_fetch_mac;
  406. }
  407. /* Register network device */
  408. if ( ( rc = register_netdev ( netdev ) ) != 0 )
  409. goto err_register;
  410. usb_func_set_drvdata ( func, ecm );
  411. return 0;
  412. unregister_netdev ( netdev );
  413. err_register:
  414. err_fetch_mac:
  415. err_ethernet:
  416. err_describe:
  417. netdev_nullify ( netdev );
  418. netdev_put ( netdev );
  419. err_alloc:
  420. return rc;
  421. }
  422. /**
  423. * Remove device
  424. *
  425. * @v func USB function
  426. */
  427. static void ecm_remove ( struct usb_function *func ) {
  428. struct ecm_device *ecm = usb_func_get_drvdata ( func );
  429. struct net_device *netdev = ecm->netdev;
  430. unregister_netdev ( netdev );
  431. netdev_nullify ( netdev );
  432. netdev_put ( netdev );
  433. }
  434. /** CDC-ECM device IDs */
  435. static struct usb_device_id ecm_ids[] = {
  436. {
  437. .name = "cdc-ecm",
  438. .vendor = USB_ANY_ID,
  439. .product = USB_ANY_ID,
  440. },
  441. };
  442. /** CDC-ECM driver */
  443. struct usb_driver ecm_driver __usb_driver = {
  444. .ids = ecm_ids,
  445. .id_count = ( sizeof ( ecm_ids ) / sizeof ( ecm_ids[0] ) ),
  446. .class = USB_CLASS_ID ( USB_CLASS_CDC, USB_SUBCLASS_CDC_ECM, 0 ),
  447. .score = USB_SCORE_NORMAL,
  448. .probe = ecm_probe,
  449. .remove = ecm_remove,
  450. };