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.

ncm.c 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  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. FILE_LICENCE ( GPL2_OR_LATER );
  20. #include <string.h>
  21. #include <errno.h>
  22. #include <ipxe/netdevice.h>
  23. #include <ipxe/ethernet.h>
  24. #include <ipxe/if_ether.h>
  25. #include <ipxe/profile.h>
  26. #include <ipxe/usb.h>
  27. #include "ecm.h"
  28. #include "ncm.h"
  29. /** @file
  30. *
  31. * CDC-NCM USB Ethernet driver
  32. *
  33. */
  34. /** Interrupt completion profiler */
  35. static struct profiler ncm_intr_profiler __profiler =
  36. { .name = "ncm.intr" };
  37. /** Bulk IN completion profiler */
  38. static struct profiler ncm_in_profiler __profiler =
  39. { .name = "ncm.in" };
  40. /** Bulk IN per-datagram profiler */
  41. static struct profiler ncm_in_datagram_profiler __profiler =
  42. { .name = "ncm.in_dgram" };
  43. /** Bulk OUT profiler */
  44. static struct profiler ncm_out_profiler __profiler =
  45. { .name = "ncm.out" };
  46. /******************************************************************************
  47. *
  48. * CDC-NCM communications interface
  49. *
  50. ******************************************************************************
  51. */
  52. /**
  53. * Complete interrupt transfer
  54. *
  55. * @v ep USB endpoint
  56. * @v iobuf I/O buffer
  57. * @v rc Completion status code
  58. */
  59. static void ncm_intr_complete ( struct usb_endpoint *ep,
  60. struct io_buffer *iobuf, int rc ) {
  61. struct ncm_device *ncm = container_of ( ep, struct ncm_device, intr );
  62. struct net_device *netdev = ncm->netdev;
  63. struct usb_setup_packet *message;
  64. size_t len = iob_len ( iobuf );
  65. /* Profile completions */
  66. profile_start ( &ncm_intr_profiler );
  67. /* Ignore packets cancelled when the endpoint closes */
  68. if ( ! ep->open )
  69. goto ignore;
  70. /* Ignore packets with errors */
  71. if ( rc != 0 ) {
  72. DBGC ( ncm, "NCM %p interrupt failed: %s\n",
  73. ncm, strerror ( rc ) );
  74. DBGC_HDA ( ncm, 0, iobuf->data, iob_len ( iobuf ) );
  75. goto error;
  76. }
  77. /* Extract message header */
  78. if ( len < sizeof ( *message ) ) {
  79. DBGC ( ncm, "NCM %p underlength interrupt:\n", ncm );
  80. DBGC_HDA ( ncm, 0, iobuf->data, iob_len ( iobuf ) );
  81. rc = -EINVAL;
  82. goto error;
  83. }
  84. message = iobuf->data;
  85. /* Parse message header */
  86. switch ( message->request ) {
  87. case cpu_to_le16 ( CDC_NETWORK_CONNECTION ) :
  88. if ( message->value ) {
  89. DBGC ( ncm, "NCM %p link up\n", ncm );
  90. netdev_link_up ( netdev );
  91. } else {
  92. DBGC ( ncm, "NCM %p link down\n", ncm );
  93. netdev_link_down ( netdev );
  94. }
  95. break;
  96. case cpu_to_le16 ( CDC_CONNECTION_SPEED_CHANGE ) :
  97. /* Ignore */
  98. break;
  99. default:
  100. DBGC ( ncm, "NCM %p unrecognised interrupt:\n", ncm );
  101. DBGC_HDA ( ncm, 0, iobuf->data, iob_len ( iobuf ) );
  102. goto error;
  103. }
  104. /* Free I/O buffer */
  105. free_iob ( iobuf );
  106. profile_stop ( &ncm_intr_profiler );
  107. return;
  108. error:
  109. netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
  110. ignore:
  111. free_iob ( iobuf );
  112. return;
  113. }
  114. /** Interrupt endpoint operations */
  115. static struct usb_endpoint_driver_operations ncm_intr_operations = {
  116. .complete = ncm_intr_complete,
  117. };
  118. /**
  119. * Open communications interface
  120. *
  121. * @v ncm CDC-NCM device
  122. * @ret rc Return status code
  123. */
  124. static int ncm_comms_open ( struct ncm_device *ncm ) {
  125. int rc;
  126. /* Open interrupt endpoint */
  127. if ( ( rc = usb_endpoint_open ( &ncm->intr ) ) != 0 ) {
  128. DBGC ( ncm, "NCM %p could not open interrupt: %s\n",
  129. ncm, strerror ( rc ) );
  130. goto err_open;
  131. }
  132. /* Refill interrupt endpoint */
  133. usb_refill ( &ncm->intr );
  134. return 0;
  135. usb_endpoint_close ( &ncm->intr );
  136. err_open:
  137. return rc;
  138. }
  139. /**
  140. * Close communications interface
  141. *
  142. * @v ncm CDC-NCM device
  143. */
  144. static void ncm_comms_close ( struct ncm_device *ncm ) {
  145. /* Close interrupt endpoint */
  146. usb_endpoint_close ( &ncm->intr );
  147. }
  148. /******************************************************************************
  149. *
  150. * CDC-NCM data interface
  151. *
  152. ******************************************************************************
  153. */
  154. /**
  155. * Prefill bulk IN endpoint
  156. *
  157. * @v ncm CDC-NCM device
  158. * @ret rc Return status code
  159. */
  160. static int ncm_in_prefill ( struct ncm_device *ncm ) {
  161. size_t mtu;
  162. unsigned int count;
  163. int rc;
  164. /* Some devices have a very small number of internal buffers,
  165. * and rely on being able to pack multiple packets into each
  166. * buffer. We therefore want to use large buffers if
  167. * possible. However, large allocations have a reasonable
  168. * chance of failure, especially if this is not the first or
  169. * only device to be opened.
  170. *
  171. * We therefore attempt to find a usable buffer size, starting
  172. * large and working downwards until allocation succeeds.
  173. * Smaller buffers will still work, albeit with a higher
  174. * chance of packet loss and so lower overall throughput.
  175. */
  176. for ( mtu = ncm->mtu ; mtu >= NCM_MIN_NTB_INPUT_SIZE ; mtu >>= 1 ) {
  177. /* Attempt allocation at this MTU */
  178. if ( mtu > NCM_MAX_NTB_INPUT_SIZE )
  179. continue;
  180. count = ( NCM_IN_MIN_SIZE / mtu );
  181. if ( count < NCM_IN_MIN_COUNT )
  182. count = NCM_IN_MIN_COUNT;
  183. if ( ( count * mtu ) > NCM_IN_MAX_SIZE )
  184. continue;
  185. usb_refill_init ( &ncm->in, mtu, count );
  186. if ( ( rc = usb_prefill ( &ncm->in ) ) != 0 ) {
  187. DBGC ( ncm, "NCM %p could not prefill %dx %zd-byte "
  188. "buffers for bulk IN\n", ncm, count, mtu );
  189. continue;
  190. }
  191. DBGC ( ncm, "NCM %p using %dx %zd-byte buffers for bulk IN\n",
  192. ncm, count, mtu );
  193. return 0;
  194. }
  195. DBGC ( ncm, "NCM %p could not prefill bulk IN endpoint\n", ncm );
  196. return -ENOMEM;
  197. }
  198. /**
  199. * Complete bulk IN transfer
  200. *
  201. * @v ep USB endpoint
  202. * @v iobuf I/O buffer
  203. * @v rc Completion status code
  204. */
  205. static void ncm_in_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
  206. int rc ) {
  207. struct ncm_device *ncm = container_of ( ep, struct ncm_device, in );
  208. struct net_device *netdev = ncm->netdev;
  209. struct ncm_transfer_header *nth;
  210. struct ncm_datagram_pointer *ndp;
  211. struct ncm_datagram_descriptor *desc;
  212. struct io_buffer *pkt;
  213. unsigned int remaining;
  214. size_t ndp_offset;
  215. size_t ndp_len;
  216. size_t pkt_offset;
  217. size_t pkt_len;
  218. size_t headroom;
  219. size_t len;
  220. /* Profile overall bulk IN completion */
  221. profile_start ( &ncm_in_profiler );
  222. /* Ignore packets cancelled when the endpoint closes */
  223. if ( ! ep->open )
  224. goto ignore;
  225. /* Record USB errors against the network device */
  226. if ( rc != 0 ) {
  227. DBGC ( ncm, "NCM %p bulk IN failed: %s\n",
  228. ncm, strerror ( rc ) );
  229. goto error;
  230. }
  231. /* Locate transfer header */
  232. len = iob_len ( iobuf );
  233. if ( sizeof ( *nth ) > len ) {
  234. DBGC ( ncm, "NCM %p packet too short for NTH:\n", ncm );
  235. rc = -EINVAL;
  236. goto error;
  237. }
  238. nth = iobuf->data;
  239. /* Locate datagram pointer */
  240. ndp_offset = le16_to_cpu ( nth->offset );
  241. if ( ( ndp_offset + sizeof ( *ndp ) ) > len ) {
  242. DBGC ( ncm, "NCM %p packet too short for NDP:\n", ncm );
  243. rc = -EINVAL;
  244. goto error;
  245. }
  246. ndp = ( iobuf->data + ndp_offset );
  247. ndp_len = le16_to_cpu ( ndp->header_len );
  248. if ( ndp_len < offsetof ( typeof ( *ndp ), desc ) ) {
  249. DBGC ( ncm, "NCM %p NDP header length too short:\n", ncm );
  250. rc = -EINVAL;
  251. goto error;
  252. }
  253. if ( ( ndp_offset + ndp_len ) > len ) {
  254. DBGC ( ncm, "NCM %p packet too short for NDP:\n", ncm );
  255. rc = -EINVAL;
  256. goto error;
  257. }
  258. /* Process datagrams */
  259. remaining = ( ( ndp_len - offsetof ( typeof ( *ndp ), desc ) ) /
  260. sizeof ( ndp->desc[0] ) );
  261. for ( desc = ndp->desc ; remaining && desc->offset ; remaining-- ) {
  262. /* Profile individual datagrams */
  263. profile_start ( &ncm_in_datagram_profiler );
  264. /* Locate datagram */
  265. pkt_offset = le16_to_cpu ( desc->offset );
  266. pkt_len = le16_to_cpu ( desc->len );
  267. if ( pkt_len < ETH_HLEN ) {
  268. DBGC ( ncm, "NCM %p underlength datagram:\n", ncm );
  269. rc = -EINVAL;
  270. goto error;
  271. }
  272. if ( ( pkt_offset + pkt_len ) > len ) {
  273. DBGC ( ncm, "NCM %p datagram exceeds packet:\n", ncm );
  274. rc = -EINVAL;
  275. goto error;
  276. }
  277. /* Move to next descriptor */
  278. desc++;
  279. /* Copy data to a new I/O buffer. Our USB buffers may
  280. * be very large and so we choose to recycle the
  281. * buffers directly rather than attempt reallocation
  282. * while the device is running. We therefore copy the
  283. * data to a new I/O buffer even if this is the only
  284. * (or last) packet within the buffer.
  285. *
  286. * We reserve enough space at the start of each buffer
  287. * to allow for our own transmission header, to
  288. * support protocols such as ARP which may modify the
  289. * received packet and reuse the same I/O buffer for
  290. * transmission.
  291. */
  292. headroom = ( sizeof ( struct ncm_ntb_header ) + ncm->padding );
  293. pkt = alloc_iob ( headroom + pkt_len );
  294. if ( ! pkt ) {
  295. /* Record error and continue */
  296. netdev_rx_err ( netdev, NULL, -ENOMEM );
  297. continue;
  298. }
  299. iob_reserve ( pkt, headroom );
  300. memcpy ( iob_put ( pkt, pkt_len ),
  301. ( iobuf->data + pkt_offset ), pkt_len );
  302. /* Strip CRC, if present */
  303. if ( ndp->magic & cpu_to_le32 ( NCM_DATAGRAM_POINTER_MAGIC_CRC))
  304. iob_unput ( pkt, 4 /* CRC32 */ );
  305. /* Hand off to network stack */
  306. netdev_rx ( netdev, pkt );
  307. profile_stop ( &ncm_in_datagram_profiler );
  308. }
  309. /* Recycle I/O buffer */
  310. usb_recycle ( &ncm->in, iobuf );
  311. profile_stop ( &ncm_in_profiler );
  312. return;
  313. error:
  314. /* Record error against network device */
  315. DBGC_HDA ( ncm, 0, iobuf->data, iob_len ( iobuf ) );
  316. netdev_rx_err ( netdev, NULL, rc );
  317. ignore:
  318. usb_recycle ( &ncm->in, iobuf );
  319. }
  320. /** Bulk IN endpoint operations */
  321. static struct usb_endpoint_driver_operations ncm_in_operations = {
  322. .complete = ncm_in_complete,
  323. };
  324. /**
  325. * Transmit packet
  326. *
  327. * @v ncm CDC-NCM device
  328. * @v iobuf I/O buffer
  329. * @ret rc Return status code
  330. */
  331. static int ncm_out_transmit ( struct ncm_device *ncm,
  332. struct io_buffer *iobuf ) {
  333. struct ncm_ntb_header *header;
  334. size_t len = iob_len ( iobuf );
  335. size_t header_len = ( sizeof ( *header ) + ncm->padding );
  336. int rc;
  337. /* Profile transmissions */
  338. profile_start ( &ncm_out_profiler );
  339. /* Prepend header */
  340. if ( ( rc = iob_ensure_headroom ( iobuf, header_len ) ) != 0 )
  341. return rc;
  342. header = iob_push ( iobuf, header_len );
  343. /* Populate header */
  344. header->nth.magic = cpu_to_le32 ( NCM_TRANSFER_HEADER_MAGIC );
  345. header->nth.header_len = cpu_to_le16 ( sizeof ( header->nth ) );
  346. header->nth.sequence = cpu_to_le16 ( ncm->sequence );
  347. header->nth.len = cpu_to_le16 ( iob_len ( iobuf ) );
  348. header->nth.offset =
  349. cpu_to_le16 ( offsetof ( typeof ( *header ), ndp ) );
  350. header->ndp.magic = cpu_to_le32 ( NCM_DATAGRAM_POINTER_MAGIC );
  351. header->ndp.header_len = cpu_to_le16 ( sizeof ( header->ndp ) +
  352. sizeof ( header->desc ) );
  353. header->ndp.offset = cpu_to_le16 ( 0 );
  354. header->desc[0].offset = cpu_to_le16 ( header_len );
  355. header->desc[0].len = cpu_to_le16 ( len );
  356. memset ( &header->desc[1], 0, sizeof ( header->desc[1] ) );
  357. /* Enqueue I/O buffer */
  358. if ( ( rc = usb_stream ( &ncm->out, iobuf, 0 ) ) != 0 )
  359. return rc;
  360. /* Increment sequence number */
  361. ncm->sequence++;
  362. profile_stop ( &ncm_out_profiler );
  363. return 0;
  364. }
  365. /**
  366. * Complete bulk OUT transfer
  367. *
  368. * @v ep USB endpoint
  369. * @v iobuf I/O buffer
  370. * @v rc Completion status code
  371. */
  372. static void ncm_out_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
  373. int rc ) {
  374. struct ncm_device *ncm = container_of ( ep, struct ncm_device, out );
  375. struct net_device *netdev = ncm->netdev;
  376. /* Report TX completion */
  377. netdev_tx_complete_err ( netdev, iobuf, rc );
  378. }
  379. /** Bulk OUT endpoint operations */
  380. static struct usb_endpoint_driver_operations ncm_out_operations = {
  381. .complete = ncm_out_complete,
  382. };
  383. /**
  384. * Open data interface
  385. *
  386. * @v ncm CDC-NCM device
  387. * @ret rc Return status code
  388. */
  389. static int ncm_data_open ( struct ncm_device *ncm ) {
  390. struct usb_device *usb = ncm->usb;
  391. struct ncm_set_ntb_input_size size;
  392. int rc;
  393. /* Prefill I/O buffers */
  394. if ( ( rc = ncm_in_prefill ( ncm ) ) != 0 )
  395. goto err_prefill;
  396. /* Set maximum input size */
  397. memset ( &size, 0, sizeof ( size ) );
  398. size.mtu = cpu_to_le32 ( ncm->in.len );
  399. if ( ( rc = usb_control ( usb, NCM_SET_NTB_INPUT_SIZE, 0, ncm->comms,
  400. &size, sizeof ( size ) ) ) != 0 ) {
  401. DBGC ( ncm, "NCM %p could not set input size to %zd: %s\n",
  402. ncm, ncm->in.mtu, strerror ( rc ) );
  403. goto err_set_ntb_input_size;
  404. }
  405. /* Select alternate setting for data interface */
  406. if ( ( rc = usb_set_interface ( usb, ncm->data,
  407. NCM_DATA_ALTERNATE ) ) != 0 ) {
  408. DBGC ( ncm, "NCM %p could not set alternate interface: %s\n",
  409. ncm, strerror ( rc ) );
  410. goto err_set_interface;
  411. }
  412. /* Open bulk IN endpoint */
  413. if ( ( rc = usb_endpoint_open ( &ncm->in ) ) != 0 ) {
  414. DBGC ( ncm, "NCM %p could not open bulk IN: %s\n",
  415. ncm, strerror ( rc ) );
  416. goto err_open_in;
  417. }
  418. /* Open bulk OUT endpoint */
  419. if ( ( rc = usb_endpoint_open ( &ncm->out ) ) != 0 ) {
  420. DBGC ( ncm, "NCM %p could not open bulk OUT: %s\n",
  421. ncm, strerror ( rc ) );
  422. goto err_open_out;
  423. }
  424. /* Refill bulk IN endpoint */
  425. if ( ( rc = usb_refill ( &ncm->in ) ) != 0 ) {
  426. DBGC ( ncm, "NCM %p could not refill bulk IN: %s\n",
  427. ncm, strerror ( rc ) );
  428. goto err_refill;
  429. }
  430. return 0;
  431. err_refill:
  432. usb_endpoint_close ( &ncm->out );
  433. err_open_out:
  434. usb_endpoint_close ( &ncm->in );
  435. err_open_in:
  436. usb_set_interface ( usb, ncm->data, 0 );
  437. err_set_interface:
  438. err_set_ntb_input_size:
  439. usb_flush ( &ncm->in );
  440. err_prefill:
  441. return rc;
  442. }
  443. /**
  444. * Close data interface
  445. *
  446. * @v ncm CDC-NCM device
  447. */
  448. static void ncm_data_close ( struct ncm_device *ncm ) {
  449. struct usb_device *usb = ncm->usb;
  450. /* Close endpoints */
  451. usb_endpoint_close ( &ncm->out );
  452. usb_endpoint_close ( &ncm->in );
  453. /* Reset data interface */
  454. usb_set_interface ( usb, ncm->data, 0 );
  455. }
  456. /******************************************************************************
  457. *
  458. * Network device interface
  459. *
  460. ******************************************************************************
  461. */
  462. /**
  463. * Open network device
  464. *
  465. * @v netdev Network device
  466. * @ret rc Return status code
  467. */
  468. static int ncm_open ( struct net_device *netdev ) {
  469. struct ncm_device *ncm = netdev->priv;
  470. int rc;
  471. /* Reset sequence number */
  472. ncm->sequence = 0;
  473. /* Open communications interface */
  474. if ( ( rc = ncm_comms_open ( ncm ) ) != 0 )
  475. goto err_comms_open;
  476. /* Open data interface */
  477. if ( ( rc = ncm_data_open ( ncm ) ) != 0 )
  478. goto err_data_open;
  479. return 0;
  480. ncm_data_close ( ncm );
  481. err_data_open:
  482. ncm_comms_close ( ncm );
  483. err_comms_open:
  484. return rc;
  485. }
  486. /**
  487. * Close network device
  488. *
  489. * @v netdev Network device
  490. */
  491. static void ncm_close ( struct net_device *netdev ) {
  492. struct ncm_device *ncm = netdev->priv;
  493. /* Close data interface */
  494. ncm_data_close ( ncm );
  495. /* Close communications interface */
  496. ncm_comms_close ( ncm );
  497. }
  498. /**
  499. * Transmit packet
  500. *
  501. * @v netdev Network device
  502. * @v iobuf I/O buffer
  503. * @ret rc Return status code
  504. */
  505. static int ncm_transmit ( struct net_device *netdev,
  506. struct io_buffer *iobuf ) {
  507. struct ncm_device *ncm = netdev->priv;
  508. int rc;
  509. /* Transmit packet */
  510. if ( ( rc = ncm_out_transmit ( ncm, iobuf ) ) != 0 )
  511. return rc;
  512. return 0;
  513. }
  514. /**
  515. * Poll for completed and received packets
  516. *
  517. * @v netdev Network device
  518. */
  519. static void ncm_poll ( struct net_device *netdev ) {
  520. struct ncm_device *ncm = netdev->priv;
  521. int rc;
  522. /* Poll USB bus */
  523. usb_poll ( ncm->bus );
  524. /* Refill interrupt endpoint */
  525. if ( ( rc = usb_refill ( &ncm->intr ) ) != 0 )
  526. netdev_rx_err ( netdev, NULL, rc );
  527. /* Refill bulk IN endpoint */
  528. if ( ( rc = usb_refill ( &ncm->in ) ) != 0 )
  529. netdev_rx_err ( netdev, NULL, rc );
  530. }
  531. /** CDC-NCM network device operations */
  532. static struct net_device_operations ncm_operations = {
  533. .open = ncm_open,
  534. .close = ncm_close,
  535. .transmit = ncm_transmit,
  536. .poll = ncm_poll,
  537. };
  538. /******************************************************************************
  539. *
  540. * USB interface
  541. *
  542. ******************************************************************************
  543. */
  544. /**
  545. * Probe device
  546. *
  547. * @v func USB function
  548. * @v config Configuration descriptor
  549. * @ret rc Return status code
  550. */
  551. static int ncm_probe ( struct usb_function *func,
  552. struct usb_configuration_descriptor *config ) {
  553. struct usb_device *usb = func->usb;
  554. struct net_device *netdev;
  555. struct ncm_device *ncm;
  556. struct usb_interface_descriptor *comms;
  557. struct usb_interface_descriptor *data;
  558. struct ecm_ethernet_descriptor *ethernet;
  559. struct ncm_ntb_parameters params;
  560. int rc;
  561. /* Allocate and initialise structure */
  562. netdev = alloc_etherdev ( sizeof ( *ncm ) );
  563. if ( ! netdev ) {
  564. rc = -ENOMEM;
  565. goto err_alloc;
  566. }
  567. netdev_init ( netdev, &ncm_operations );
  568. netdev->dev = &func->dev;
  569. ncm = netdev->priv;
  570. memset ( ncm, 0, sizeof ( *ncm ) );
  571. ncm->usb = usb;
  572. ncm->bus = usb->port->hub->bus;
  573. ncm->netdev = netdev;
  574. usb_endpoint_init ( &ncm->intr, usb, &ncm_intr_operations );
  575. usb_endpoint_init ( &ncm->in, usb, &ncm_in_operations );
  576. usb_endpoint_init ( &ncm->out, usb, &ncm_out_operations );
  577. usb_refill_init ( &ncm->intr, 0, NCM_INTR_COUNT );
  578. DBGC ( ncm, "NCM %p on %s\n", ncm, func->name );
  579. /* Identify interfaces */
  580. if ( func->count < NCM_INTERFACE_COUNT ) {
  581. DBGC ( ncm, "NCM %p has only %d interfaces\n",
  582. ncm, func->count );
  583. rc = -EINVAL;
  584. goto err_count;
  585. }
  586. ncm->comms = func->interface[NCM_INTERFACE_COMMS];
  587. ncm->data = func->interface[NCM_INTERFACE_DATA];
  588. /* Locate communications interface descriptor */
  589. comms = usb_interface_descriptor ( config, ncm->comms, 0 );
  590. if ( ! comms ) {
  591. DBGC ( ncm, "NCM %p has no communications interface\n", ncm );
  592. rc = -EINVAL;
  593. goto err_comms;
  594. }
  595. /* Locate data interface descriptor */
  596. data = usb_interface_descriptor ( config, ncm->data,
  597. NCM_DATA_ALTERNATE );
  598. if ( ! data ) {
  599. DBGC ( ncm, "NCM %p has no data interface\n", ncm );
  600. rc = -EINVAL;
  601. goto err_data;
  602. }
  603. /* Describe interrupt endpoint */
  604. if ( ( rc = usb_endpoint_described ( &ncm->intr, config, comms,
  605. USB_INTERRUPT, 0 ) ) != 0 ) {
  606. DBGC ( ncm, "NCM %p could not describe interrupt endpoint: "
  607. "%s\n", ncm, strerror ( rc ) );
  608. goto err_interrupt;
  609. }
  610. /* Describe bulk IN endpoint */
  611. if ( ( rc = usb_endpoint_described ( &ncm->in, config, data,
  612. USB_BULK_IN, 0 ) ) != 0 ) {
  613. DBGC ( ncm, "NCM %p could not describe bulk IN endpoint: "
  614. "%s\n", ncm, strerror ( rc ) );
  615. goto err_bulk_in;
  616. }
  617. /* Describe bulk OUT endpoint */
  618. if ( ( rc = usb_endpoint_described ( &ncm->out, config, data,
  619. USB_BULK_OUT, 0 ) ) != 0 ) {
  620. DBGC ( ncm, "NCM %p could not describe bulk OUT endpoint: "
  621. "%s\n", ncm, strerror ( rc ) );
  622. goto err_bulk_out;
  623. }
  624. /* Locate Ethernet descriptor */
  625. ethernet = ecm_ethernet_descriptor ( config, comms );
  626. if ( ! ethernet ) {
  627. DBGC ( ncm, "NCM %p has no Ethernet descriptor\n", ncm );
  628. rc = -EINVAL;
  629. goto err_ethernet;
  630. }
  631. /* Fetch MAC address */
  632. if ( ( rc = ecm_fetch_mac ( usb, ethernet, netdev->hw_addr ) ) != 0 ) {
  633. DBGC ( ncm, "NCM %p could not fetch MAC address: %s\n",
  634. ncm, strerror ( rc ) );
  635. goto err_fetch_mac;
  636. }
  637. /* Get NTB parameters */
  638. if ( ( rc = usb_control ( usb, NCM_GET_NTB_PARAMETERS, 0, ncm->comms,
  639. &params, sizeof ( params ) ) ) != 0 ) {
  640. DBGC ( ncm, "NCM %p could not get NTB parameters: %s\n",
  641. ncm, strerror ( rc ) );
  642. goto err_ntb_parameters;
  643. }
  644. /* Get maximum supported input size */
  645. ncm->mtu = le32_to_cpu ( params.in.mtu );
  646. DBGC2 ( ncm, "NCM %p maximum IN size is %zd bytes\n", ncm, ncm->mtu );
  647. /* Calculate transmit padding */
  648. ncm->padding = ( ( le16_to_cpu ( params.out.remainder ) -
  649. sizeof ( struct ncm_ntb_header ) - ETH_HLEN ) &
  650. ( le16_to_cpu ( params.out.divisor ) - 1 ) );
  651. DBGC2 ( ncm, "NCM %p using %zd-byte transmit padding\n",
  652. ncm, ncm->padding );
  653. assert ( ( ( sizeof ( struct ncm_ntb_header ) + ncm->padding +
  654. ETH_HLEN ) % le16_to_cpu ( params.out.divisor ) ) ==
  655. le16_to_cpu ( params.out.remainder ) );
  656. /* Register network device */
  657. if ( ( rc = register_netdev ( netdev ) ) != 0 )
  658. goto err_register;
  659. usb_func_set_drvdata ( func, ncm );
  660. return 0;
  661. unregister_netdev ( netdev );
  662. err_register:
  663. err_ntb_parameters:
  664. err_fetch_mac:
  665. err_ethernet:
  666. err_bulk_out:
  667. err_bulk_in:
  668. err_interrupt:
  669. err_data:
  670. err_comms:
  671. err_count:
  672. netdev_nullify ( netdev );
  673. netdev_put ( netdev );
  674. err_alloc:
  675. return rc;
  676. }
  677. /**
  678. * Remove device
  679. *
  680. * @v func USB function
  681. */
  682. static void ncm_remove ( struct usb_function *func ) {
  683. struct ncm_device *ncm = usb_func_get_drvdata ( func );
  684. struct net_device *netdev = ncm->netdev;
  685. unregister_netdev ( netdev );
  686. netdev_nullify ( netdev );
  687. netdev_put ( netdev );
  688. }
  689. /** CDC-NCM device IDs */
  690. static struct usb_device_id ncm_ids[] = {
  691. {
  692. .name = "cdc-ncm",
  693. .vendor = USB_ANY_ID,
  694. .product = USB_ANY_ID,
  695. .class = {
  696. .class = USB_CLASS_CDC,
  697. .subclass = USB_SUBCLASS_CDC_NCM,
  698. .protocol = 0,
  699. },
  700. },
  701. };
  702. /** CDC-NCM driver */
  703. struct usb_driver ncm_driver __usb_driver = {
  704. .ids = ncm_ids,
  705. .id_count = ( sizeof ( ncm_ids ) / sizeof ( ncm_ids[0] ) ),
  706. .probe = ncm_probe,
  707. .remove = ncm_remove,
  708. };