mac802154_netdev.c 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451
  1. /****************************************************************************
  2. * wireless/ieee802154/mac802154_netdev.c
  3. *
  4. * Copyright (C) 2017-2018 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <stdint.h>
  40. #include <stdbool.h>
  41. #include <time.h>
  42. #include <string.h>
  43. #include <errno.h>
  44. #include <assert.h>
  45. #include <debug.h>
  46. #include <arpa/inet.h>
  47. #include <nuttx/arch.h>
  48. #include <nuttx/irq.h>
  49. #include <nuttx/kmalloc.h>
  50. #include <nuttx/signal.h>
  51. #include <nuttx/wdog.h>
  52. #include <nuttx/wqueue.h>
  53. #include <nuttx/mm/iob.h>
  54. #include <nuttx/net/arp.h>
  55. #include <nuttx/net/netdev.h>
  56. #include <nuttx/net/radiodev.h>
  57. #include <nuttx/net/ieee802154.h>
  58. #include <nuttx/net/sixlowpan.h>
  59. #include <nuttx/wireless/ieee802154/ieee802154_mac.h>
  60. #include "mac802154.h"
  61. #if defined(CONFIG_NET_6LOWPAN) || defined(CONFIG_NET_IEEE802154)
  62. /****************************************************************************
  63. * Pre-processor Definitions
  64. ****************************************************************************/
  65. /* If processing is not done at the interrupt level, then work queue support
  66. * is required.
  67. */
  68. #if !defined(CONFIG_SCHED_WORKQUEUE)
  69. # error Work queue support is required in this configuration (CONFIG_SCHED_WORKQUEUE)
  70. #endif
  71. /* The low priority work queue is preferred. If it is not enabled, LPWORK
  72. * will be the same as HPWORK.
  73. *
  74. * NOTE: However, the network should NEVER run on the high priority work
  75. * queue! That queue is intended only to service short back end interrupt
  76. * processing that never suspends. Suspending the high priority work queue
  77. * may bring the system to its knees!
  78. */
  79. #define WPANWORK LPWORK
  80. /* CONFIG_IEEE802154_NETDEV_NINTERFACES determines the number of physical interfaces
  81. * that will be supported.
  82. */
  83. #ifndef CONFIG_IEEE802154_NETDEV_NINTERFACES
  84. # define CONFIG_IEEE802154_NETDEV_NINTERFACES 1
  85. #endif
  86. /* Preferred address size */
  87. #ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR
  88. # define MACNET_ADDRSIZE IEEE802154_EADDRSIZE
  89. #else
  90. # define MACNET_ADDRSIZE IEEE802154_SADDRSIZE
  91. #endif
  92. /* Frame size */
  93. #if defined(CONFIG_NET_IEEE802154_FRAMELEN)
  94. # define MACNET_FRAMELEN CONFIG_NET_IEEE802154_FRAMELEN
  95. #else
  96. # define MACNET_FRAMELEN IEEE802154_MAX_PHY_PACKET_SIZE
  97. #endif
  98. #if (CONFIG_MAC802154_NTXDESC < CONFIG_IOB_NBUFFERS)
  99. # warning "CONFIG_MAC802154_NTXDESC should probably be equal to" \
  100. "CONFIG_IOB_NBUFFERS to avoid waiting on req_data"
  101. #endif
  102. /* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per second */
  103. #define TXPOLL_WDDELAY (1*CLK_TCK)
  104. /****************************************************************************
  105. * Private Types
  106. ****************************************************************************/
  107. /* This is our private version of the MAC callback structure */
  108. struct macnet_callback_s
  109. {
  110. /* This holds the information visible to the MAC layer */
  111. struct mac802154_maccb_s mc_cb; /* Interface understood by the MAC layer */
  112. FAR struct macnet_driver_s *mc_priv; /* Our priv data */
  113. };
  114. /* The macnet_driver_s encapsulates all state information for a single
  115. * IEEE802.15.4 MAC interface.
  116. */
  117. struct macnet_driver_s
  118. {
  119. /* This holds the information visible to the NuttX network */
  120. struct radio_driver_s md_dev; /* Interface understood by the network */
  121. /* Cast compatible with struct macnet_driver_s */
  122. /* For internal use by this driver */
  123. sem_t md_exclsem; /* Exclusive access to struct */
  124. struct macnet_callback_s md_cb; /* Callback information */
  125. MACHANDLE md_mac; /* Contained MAC interface */
  126. bool md_bifup; /* true:ifup false:ifdown */
  127. WDOG_ID md_txpoll; /* TX poll timer */
  128. struct work_s md_pollwork; /* Defer poll work to the work queue */
  129. /* Hold a list of events */
  130. bool md_enableevents : 1; /* Are events enabled? */
  131. bool md_eventpending : 1; /* Is there a get event using the semaphore? */
  132. sem_t md_eventsem; /* Signaling semaphore for waiting get event */
  133. sq_queue_t primitive_queue; /* For holding primitives to pass along */
  134. /* MAC Service notification information */
  135. bool md_notify_registered;
  136. pid_t md_notify_pid;
  137. struct sigevent md_notify_event;
  138. struct sigwork_s md_notify_work;
  139. #ifdef CONFIG_NET_6LOWPAN
  140. struct sixlowpan_reassbuf_s md_iobuffer;
  141. #endif
  142. };
  143. /****************************************************************************
  144. * Private Function Prototypes
  145. ****************************************************************************/
  146. /* Utility functions ********************************************************/
  147. static int macnet_update_nvaddr(FAR struct net_driver_s *dev);
  148. static inline void macnet_netmask(FAR struct net_driver_s *dev);
  149. /* IEE802.15.4 MAC callback functions ***************************************/
  150. static int macnet_notify(FAR struct mac802154_maccb_s *maccb,
  151. FAR struct ieee802154_primitive_s *primitive);
  152. static int macnet_rxframe(FAR struct macnet_driver_s *maccb,
  153. FAR struct ieee802154_data_ind_s *ind);
  154. /* Network interface support ************************************************/
  155. /* Common TX logic */
  156. static int macnet_txpoll_callback(FAR struct net_driver_s *dev);
  157. static void macnet_txpoll_work(FAR void *arg);
  158. static void macnet_txpoll_expiry(int argc, wdparm_t arg, ...);
  159. /* IOCTL support */
  160. #ifdef CONFIG_NET_STARPOINT
  161. #ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR
  162. static int macnet_coord_eaddr(FAR struct radio_driver_s *radio,
  163. FAR uint8_t *eaddr);
  164. #else
  165. static int macnet_coord_saddr(FAR struct radio_driver_s *radio,
  166. FAR uint8_t *saddr);
  167. #endif
  168. #endif
  169. /* NuttX callback functions */
  170. static int macnet_ifup(FAR struct net_driver_s *dev);
  171. static int macnet_ifdown(FAR struct net_driver_s *dev);
  172. static void macnet_txavail_work(FAR void *arg);
  173. static int macnet_txavail(FAR struct net_driver_s *dev);
  174. #ifdef CONFIG_NET_MCASTGROUP
  175. static int macnet_addmac(FAR struct net_driver_s *dev,
  176. FAR const uint8_t *mac);
  177. static int macnet_rmmac(FAR struct net_driver_s *dev,
  178. FAR const uint8_t *mac);
  179. #endif
  180. #ifdef CONFIG_NETDEV_IOCTL
  181. static int macnet_ioctl(FAR struct net_driver_s *dev, int cmd,
  182. unsigned long arg);
  183. #endif
  184. static int macnet_get_mhrlen(FAR struct radio_driver_s *netdev,
  185. FAR const void *meta);
  186. static int macnet_req_data(FAR struct radio_driver_s *netdev,
  187. FAR const void *meta, FAR struct iob_s *framelist);
  188. static int macnet_properties(FAR struct radio_driver_s *netdev,
  189. FAR struct radiodev_properties_s *properties);
  190. /****************************************************************************
  191. * Private Data
  192. ****************************************************************************/
  193. /****************************************************************************
  194. * Private Functions
  195. ****************************************************************************/
  196. /****************************************************************************
  197. * Name: macnet_update_nvaddr
  198. *
  199. * Description:
  200. * Advertise the MAC and IPv6 address for this node.
  201. *
  202. *
  203. ****************************************************************************/
  204. static int macnet_update_nvaddr(FAR struct net_driver_s *dev)
  205. {
  206. FAR struct macnet_driver_s *priv;
  207. union ieee802154_macarg_u arg;
  208. int ret;
  209. DEBUGASSERT(dev != NULL && dev->d_private != NULL);
  210. priv = (FAR struct macnet_driver_s *)dev->d_private;
  211. #ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR
  212. /* Get the eaddr from the MAC */
  213. arg.getreq.attr = IEEE802154_ATTR_MAC_EADDR;
  214. ret = mac802154_ioctl(priv->md_mac, MAC802154IOC_MLME_GET_REQUEST,
  215. (unsigned long)((uintptr_t)&arg));
  216. if (ret < 0)
  217. {
  218. wlerr("ERROR: MAC802154IOC_MLME_GET_REQUEST failed: %d\n", ret);
  219. return ret;
  220. }
  221. else
  222. {
  223. IEEE802154_EADDRCOPY(dev->d_mac.radio.nv_addr, arg.getreq.attrval.mac.eaddr);
  224. dev->d_mac.radio.nv_addrlen = IEEE802154_EADDRSIZE;
  225. return OK;
  226. }
  227. #else
  228. uint8_t *saddr;
  229. /* Get the saddr from the MAC */
  230. arg.getreq.attr = IEEE802154_ATTR_MAC_SADDR;
  231. ret = mac802154_ioctl(priv->md_mac, MAC802154IOC_MLME_GET_REQUEST,
  232. (unsigned long)((uintptr_t)&arg));
  233. if (ret < 0)
  234. {
  235. wlerr("ERROR: MAC802154IOC_MLME_GET_REQUEST failed: %d\n", ret);
  236. return ret;
  237. }
  238. else
  239. {
  240. /* Set the MAC address as the saddr */
  241. saddr = arg.getreq.attrval.mac.saddr;
  242. /* Network layers expect address in Network Order (Big Endian) */
  243. dev->d_mac.radio.nv_addr[0] = saddr[1];
  244. dev->d_mac.radio.nv_addr[1] = saddr[0];
  245. dev->d_mac.radio.nv_addrlen = IEEE802154_SADDRSIZE;
  246. return OK;
  247. }
  248. #endif
  249. }
  250. /****************************************************************************
  251. * Name: macnet_netmask
  252. *
  253. * Description:
  254. * Create a netmask of a MAC-based IP address which may be based on either
  255. * the IEEE 802.15.14 short or extended address of the MAC.
  256. *
  257. * 128 112 96 80 64 48 32 16
  258. * ---- ---- ---- ---- ---- ---- ---- ----
  259. * fe80 0000 0000 0000 0000 00ff fe00 xxxx 2-byte short address IEEE 48-bit MAC
  260. * fe80 0000 0000 0000 xxxx xxxx xxxx xxxx 8-byte extended address IEEE EUI-64
  261. *
  262. ****************************************************************************/
  263. static inline void macnet_netmask(FAR struct net_driver_s *dev)
  264. {
  265. dev->d_ipv6netmask[0] = 0xffff;
  266. dev->d_ipv6netmask[1] = 0xffff;
  267. dev->d_ipv6netmask[2] = 0xffff;
  268. dev->d_ipv6netmask[3] = 0xffff;
  269. #ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR
  270. dev->d_ipv6netmask[4] = 0;
  271. dev->d_ipv6netmask[5] = 0;
  272. dev->d_ipv6netmask[6] = 0;
  273. dev->d_ipv6netmask[7] = 0;
  274. #else
  275. dev->d_ipv6netmask[4] = 0xffff;
  276. dev->d_ipv6netmask[5] = 0xffff;
  277. dev->d_ipv6netmask[6] = 0xffff;
  278. dev->d_ipv6netmask[7] = 0;
  279. #endif
  280. }
  281. /****************************************************************************
  282. * Name: macnet_notify
  283. *
  284. * Description:
  285. *
  286. ****************************************************************************/
  287. static int macnet_notify(FAR struct mac802154_maccb_s *maccb,
  288. FAR struct ieee802154_primitive_s *primitive)
  289. {
  290. FAR struct macnet_callback_s *cb =
  291. (FAR struct macnet_callback_s *)maccb;
  292. FAR struct macnet_driver_s *priv;
  293. DEBUGASSERT(cb != NULL && cb->mc_priv != NULL);
  294. priv = cb->mc_priv;
  295. /* Handle the special case for data indications or "incoming frames" */
  296. if (primitive->type == IEEE802154_PRIMITIVE_IND_DATA)
  297. {
  298. return macnet_rxframe(priv, &primitive->u.dataind);
  299. }
  300. /* If there is a registered notification receiver, queue the event and signal
  301. * the receiver. Events should be popped from the queue from the application
  302. * at a reasonable rate in order for the MAC layer to be able to allocate new
  303. * notifications.
  304. */
  305. if (priv->md_enableevents)
  306. {
  307. /* Get exclusive access to the driver structure. We don't care about any
  308. * signals so if we see one, just go back to trying to get access again
  309. */
  310. while (nxsem_wait(&priv->md_exclsem) < 0);
  311. sq_addlast((FAR sq_entry_t *)primitive, &priv->primitive_queue);
  312. /* Check if there is a read waiting for data */
  313. if (priv->md_eventpending)
  314. {
  315. /* Wake the thread waiting for the data transmission */
  316. priv->md_eventpending = false;
  317. nxsem_post(&priv->md_eventsem);
  318. }
  319. if (priv->md_notify_registered)
  320. {
  321. priv->md_notify_event.sigev_value.sival_int = primitive->type;
  322. nxsig_notification(priv->md_notify_pid, &priv->md_notify_event,
  323. SI_QUEUE, &priv->md_notify_work);
  324. }
  325. nxsem_post(&priv->md_exclsem);
  326. return OK;
  327. }
  328. /* By returning a negative value, we let the MAC know that we don't want the
  329. * primitive and it will free it for us
  330. */
  331. return -1;
  332. }
  333. /****************************************************************************
  334. * Name: macnet_rxframe
  335. *
  336. * Description:
  337. * Handle received frames forward by the IEEE 802.15.4 MAC.
  338. *
  339. * Returned Value:
  340. * Zero (OK) is returned on success; a negated errno value is returned on
  341. * any failure. On success, the ind and its contained iob will be freed.
  342. * The ind will be intact if this function returns a failure.
  343. *
  344. ****************************************************************************/
  345. static int macnet_rxframe(FAR struct macnet_driver_s *priv,
  346. FAR struct ieee802154_data_ind_s *ind)
  347. {
  348. FAR struct iob_s *iob;
  349. int ret;
  350. /* Ignore the frame if the network is not up */
  351. if (!priv->md_bifup)
  352. {
  353. wlwarn("WARNING: Dropped... Network is down\n");
  354. return -ENETDOWN;
  355. }
  356. /* Peek the IOB contained the frame in the struct ieee802154_data_ind_s */
  357. DEBUGASSERT(priv != NULL && ind != NULL && ind->frame != NULL);
  358. iob = ind->frame;
  359. /* Remove the IOB containing the frame. */
  360. ind->frame = NULL;
  361. net_lock();
  362. /* Transfer the frame to the network logic */
  363. #ifdef CONFIG_NET_IEEE802154
  364. /* Invoke the PF_IEEE802154 tap first. If the frame matches
  365. * with a connected PF_IEEE802145 socket, it will take the
  366. * frame and return success.
  367. */
  368. ret = ieee802154_input(&priv->md_dev, iob, (FAR void *)ind);
  369. if (ret < 0)
  370. #endif
  371. #ifdef CONFIG_NET_6LOWPAN
  372. {
  373. /* If the frame is not a 6LoWPAN frame, then return an error. The
  374. * first byte following the MAC head at the io_offset should be a
  375. * valid IPHC header.
  376. */
  377. if ((iob->io_data[iob->io_offset] & SIXLOWPAN_DISPATCH_NALP_MASK) ==
  378. SIXLOWPAN_DISPATCH_NALP)
  379. {
  380. wlwarn("WARNING: Dropped... Not a 6LoWPAN frame: %02x\n",
  381. iob->io_data[iob->io_offset]);
  382. ret = -EINVAL;
  383. }
  384. else
  385. {
  386. /* Make sure the our single packet buffer is attached */
  387. priv->md_dev.r_dev.d_buf = priv->md_iobuffer.rb_buf;
  388. /* And give the packet to 6LoWPAN */
  389. ret = sixlowpan_input(&priv->md_dev, iob, (FAR void *)ind);
  390. }
  391. }
  392. if (ret < 0)
  393. #endif
  394. {
  395. net_unlock();
  396. ind->frame = iob;
  397. return ret;
  398. }
  399. /* Increment statistics */
  400. NETDEV_RXPACKETS(&priv->md_dev.r_dev);
  401. NETDEV_RXIPV6(&priv->md_dev.r_dev);
  402. net_unlock();
  403. /* sixlowpan_input() will free the IOB, but we must free the struct
  404. * ieee802154_primitive_s container here.
  405. */
  406. ieee802154_primitive_free((FAR struct ieee802154_primitive_s *)ind);
  407. return OK;
  408. }
  409. /****************************************************************************
  410. * Name: macnet_txpoll_callback
  411. *
  412. * Description:
  413. * The transmitter is available, check if the network has any outgoing
  414. * packets ready to send. This is a callback from devif_poll().
  415. * devif_poll() may be called:
  416. *
  417. * 1. When the preceding TX packet send is complete,
  418. * 2. When the preceding TX packet send timesout and the interface is reset
  419. * 3. During normal TX polling
  420. *
  421. * Input Parameters:
  422. * dev - Reference to the NuttX driver state structure
  423. *
  424. * Returned Value:
  425. * OK on success; a negated errno on failure
  426. *
  427. * Assumptions:
  428. * The network is locked.
  429. *
  430. ****************************************************************************/
  431. static int macnet_txpoll_callback(FAR struct net_driver_s *dev)
  432. {
  433. /* If zero is returned, the polling will continue until all connections have
  434. * been examined.
  435. */
  436. return 0;
  437. }
  438. /****************************************************************************
  439. * Name: macnet_txpoll_work
  440. *
  441. * Description:
  442. * Perform periodic polling from the worker thread
  443. *
  444. * Input Parameters:
  445. * arg - The argument passed when work_queue() as called.
  446. *
  447. * Returned Value:
  448. * OK on success
  449. *
  450. * Assumptions:
  451. * The network is locked.
  452. *
  453. ****************************************************************************/
  454. static void macnet_txpoll_work(FAR void *arg)
  455. {
  456. FAR struct macnet_driver_s *priv = (FAR struct macnet_driver_s *)arg;
  457. /* Lock the network and serialize driver operations if necessary.
  458. * NOTE: Serialization is only required in the case where the driver work
  459. * is performed on an LP worker thread and where more than one LP worker
  460. * thread has been configured.
  461. */
  462. net_lock();
  463. #ifdef CONFIG_NET_6LOWPAN
  464. /* Make sure the our single packet buffer is attached */
  465. priv->md_dev.r_dev.d_buf = priv->md_iobuffer.rb_buf;
  466. #endif
  467. /* Then perform the poll */
  468. (void)devif_timer(&priv->md_dev.r_dev, macnet_txpoll_callback);
  469. /* Setup the watchdog poll timer again */
  470. (void)wd_start(priv->md_txpoll, TXPOLL_WDDELAY, macnet_txpoll_expiry, 1,
  471. (wdparm_t)priv);
  472. net_unlock();
  473. }
  474. /****************************************************************************
  475. * Name: macnet_txpoll_expiry
  476. *
  477. * Description:
  478. * Periodic timer handler. Called from the timer interrupt handler.
  479. *
  480. * Input Parameters:
  481. * argc - The number of available arguments
  482. * arg - The first argument
  483. *
  484. * Returned Value:
  485. * None
  486. *
  487. * Assumptions:
  488. * Global interrupts are disabled by the watchdog logic.
  489. *
  490. ****************************************************************************/
  491. static void macnet_txpoll_expiry(int argc, wdparm_t arg, ...)
  492. {
  493. FAR struct macnet_driver_s *priv = (FAR struct macnet_driver_s *)arg;
  494. /* Schedule to perform the interrupt processing on the worker thread. */
  495. work_queue(WPANWORK, &priv->md_pollwork, macnet_txpoll_work, priv, 0);
  496. }
  497. /****************************************************************************
  498. * Name: macnet_coord_eaddr
  499. *
  500. * Description:
  501. * Get the extended address of the PAN coordinator.
  502. *
  503. * Input Parameters:
  504. * radio - Reference to a radio network driver state instance.
  505. * eaddr - The location in which to return the extended address.
  506. *
  507. * Returned Value:
  508. * Zero (OK) on success; a negated errno value on failure.
  509. *
  510. ****************************************************************************/
  511. #if defined(CONFIG_NET_STARPOINT) && defined(CONFIG_NET_6LOWPAN_EXTENDEDADDR)
  512. static int macnet_coord_eaddr(FAR struct radio_driver_s *radio,
  513. FAR uint8_t *eaddr)
  514. {
  515. FAR struct macnet_driver_s *priv = (FAR struct macnet_driver_s *)radio;
  516. union ieee802154_macarg_u arg;
  517. int ret;
  518. arg.getreq.attr = IEEE802154_ATTR_MAC_COORD_EADDR ;
  519. ret = mac802154_ioctl(priv->md_mac, MAC802154IOC_MLME_GET_REQUEST,
  520. (unsigned long)((uintptr_t)&arg));
  521. if (ret < 0)
  522. {
  523. nerr("ERROR: MAC802154IOC_MLME_GET_REQUEST failed: %d\n", ret);
  524. return ret;
  525. }
  526. IEEE802154_EADDRCOPY(eaddr, arg.getreq.attrval.mac.eaddr);
  527. return OK;
  528. }
  529. #endif
  530. /****************************************************************************
  531. * Name: macnet_coord_saddr
  532. *
  533. * Description:
  534. * Get the short address of the PAN coordinator.
  535. *
  536. * Input Parameters:
  537. * radio - Reference to a radio network driver state instance.
  538. * saddr - The location in which to return the short address.
  539. *
  540. * Returned Value:
  541. * Zero (OK) on success; a negated errno value on failure.
  542. *
  543. ****************************************************************************/
  544. #if defined(CONFIG_NET_STARPOINT) && !defined(CONFIG_NET_6LOWPAN_EXTENDEDADDR)
  545. static int macnet_coord_saddr(FAR struct radio_driver_s *radio,
  546. FAR uint8_t *saddr)
  547. {
  548. FAR struct macnet_driver_s *priv = (FAR struct macnet_driver_s *)radio;
  549. union ieee802154_macarg_u arg;
  550. int ret;
  551. arg.getreq.attr = IEEE802154_ATTR_MAC_COORD_SADDR ;
  552. ret = mac802154_ioctl(priv->md_mac, MAC802154IOC_MLME_GET_REQUEST,
  553. (unsigned long)((uintptr_t)&arg));
  554. if (ret < 0)
  555. {
  556. nerr("ERROR: MAC802154IOC_MLME_GET_REQUEST failed: %d\n", ret);
  557. return ret;
  558. }
  559. IEEE802154_SADDRCOPY(saddr, arg.getreq.attrval.mac.saddr);
  560. return OK;
  561. }
  562. #endif
  563. /****************************************************************************
  564. * Name: macnet_ifup
  565. *
  566. * Description:
  567. * Creates a MAC-based IP address from the IEEE 802.15.14 short or extended
  568. * address assigned to the node.
  569. *
  570. * 128 112 96 80 64 48 32 16
  571. * ---- ---- ---- ---- ---- ---- ---- ----
  572. * fe80 0000 0000 0000 0000 00ff fe00 xxxx 2-byte short address IEEE 48-bit MAC
  573. * fe80 0000 0000 0000 xxxx xxxx xxxx xxxx 8-byte extended address IEEE EUI-64
  574. *
  575. * Input Parameters:
  576. * dev - Reference to the NuttX driver state structure
  577. *
  578. * Returned Value:
  579. * None
  580. *
  581. * Assumptions:
  582. *
  583. ****************************************************************************/
  584. static int macnet_ifup(FAR struct net_driver_s *dev)
  585. {
  586. FAR struct macnet_driver_s *priv =
  587. (FAR struct macnet_driver_s *)dev->d_private;
  588. int ret;
  589. ret = macnet_update_nvaddr(dev);
  590. if (ret == OK)
  591. {
  592. uint8_t *nvaddr = dev->d_mac.radio.nv_addr;
  593. /* Set the IP address based on the addressing assigned to the node */
  594. dev->d_ipv6addr[0] = HTONS(CONFIG_IEEE802154_NETDEV_DEFAULT_PREFIX_0);
  595. dev->d_ipv6addr[1] = HTONS(CONFIG_IEEE802154_NETDEV_DEFAULT_PREFIX_1);
  596. dev->d_ipv6addr[2] = HTONS(CONFIG_IEEE802154_NETDEV_DEFAULT_PREFIX_2);
  597. dev->d_ipv6addr[3] = HTONS(CONFIG_IEEE802154_NETDEV_DEFAULT_PREFIX_3);
  598. #ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR
  599. dev->d_ipv6addr[4] = HTONS((uint16_t)nvaddr[0] << 8 | (uint16_t)nvaddr[1]);
  600. dev->d_ipv6addr[5] = HTONS((uint16_t)nvaddr[2] << 8 | (uint16_t)nvaddr[3]);
  601. dev->d_ipv6addr[6] = HTONS((uint16_t)nvaddr[4] << 8 | (uint16_t)nvaddr[5]);
  602. dev->d_ipv6addr[7] = HTONS((uint16_t)nvaddr[6] << 8 | (uint16_t)nvaddr[7]);
  603. /* Invert the U/L bit */
  604. dev->d_ipv6addr[4] ^= HTONS(0x0200);
  605. #else
  606. dev->d_ipv6addr[4] = 0;
  607. dev->d_ipv6addr[5] = HTONS(0x00ff);
  608. dev->d_ipv6addr[6] = HTONS(0xfe00);
  609. dev->d_ipv6addr[7] = HTONS((uint16_t)nvaddr[0] << 8 | (uint16_t)nvaddr[1]);
  610. #endif
  611. wlinfo("Bringing up: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
  612. dev->d_ipv6addr[0], dev->d_ipv6addr[1], dev->d_ipv6addr[2],
  613. dev->d_ipv6addr[3], dev->d_ipv6addr[4], dev->d_ipv6addr[5],
  614. dev->d_ipv6addr[6], dev->d_ipv6addr[7]);
  615. #ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR
  616. wlinfo(" Node: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
  617. dev->d_mac.radio.nv_addr[0], dev->d_mac.radio.nv_addr[1],
  618. dev->d_mac.radio.nv_addr[2], dev->d_mac.radio.nv_addr[3],
  619. dev->d_mac.radio.nv_addr[4], dev->d_mac.radio.nv_addr[5],
  620. dev->d_mac.radio.nv_addr[6], dev->d_mac.radio.nv_addr[7]);
  621. #else
  622. wlinfo(" Node: %02x:%02x\n",
  623. dev->d_mac.radio.nv_addr[0], dev->d_mac.radio.nv_addr[1]);
  624. #endif
  625. /* Set and activate a timer process */
  626. (void)wd_start(priv->md_txpoll, TXPOLL_WDDELAY, macnet_txpoll_expiry,
  627. 1, (wdparm_t)priv);
  628. ret = OK;
  629. }
  630. /* The interface is now up */
  631. priv->md_bifup = true;
  632. return ret;
  633. }
  634. /****************************************************************************
  635. * Name: macnet_ifdown
  636. *
  637. * Description:
  638. * NuttX Callback: Stop the interface.
  639. *
  640. * Input Parameters:
  641. * dev - Reference to the NuttX driver state structure
  642. *
  643. * Returned Value:
  644. * None
  645. *
  646. * Assumptions:
  647. *
  648. ****************************************************************************/
  649. static int macnet_ifdown(FAR struct net_driver_s *dev)
  650. {
  651. FAR struct macnet_driver_s *priv = (FAR struct macnet_driver_s *)dev->d_private;
  652. irqstate_t flags;
  653. /* Disable interruption */
  654. flags = enter_critical_section();
  655. /* Cancel the TX poll timer and TX timeout timers */
  656. wd_cancel(priv->md_txpoll);
  657. /* Put the EMAC in its reset, non-operational state. This should be
  658. * a known configuration that will guarantee the macnet_ifup() always
  659. * successfully brings the interface back up.
  660. */
  661. /* Mark the device "down" */
  662. priv->md_bifup = false;
  663. leave_critical_section(flags);
  664. return OK;
  665. }
  666. /****************************************************************************
  667. * Name: macnet_txavail_work
  668. *
  669. * Description:
  670. * Perform an out-of-cycle poll on the worker thread.
  671. *
  672. * Input Parameters:
  673. * arg - Reference to the NuttX driver state structure (cast to void*)
  674. *
  675. * Returned Value:
  676. * None
  677. *
  678. * Assumptions:
  679. * Called on the higher priority worker thread.
  680. *
  681. ****************************************************************************/
  682. static void macnet_txavail_work(FAR void *arg)
  683. {
  684. FAR struct macnet_driver_s *priv = (FAR struct macnet_driver_s *)arg;
  685. wlinfo("ifup=%u\n", priv->md_bifup);
  686. /* Lock the network and serialize driver operations if necessary.
  687. * NOTE: Serialization is only required in the case where the driver work
  688. * is performed on an LP worker thread and where more than one LP worker
  689. * thread has been configured.
  690. */
  691. net_lock();
  692. /* Ignore the notification if the interface is not yet up */
  693. if (priv->md_bifup)
  694. {
  695. #ifdef CONFIG_NET_6LOWPAN
  696. /* Make sure the our single packet buffer is attached */
  697. priv->md_dev.r_dev.d_buf = priv->md_iobuffer.rb_buf;
  698. #endif
  699. /* Then poll the network for new XMIT data */
  700. (void)devif_poll(&priv->md_dev.r_dev, macnet_txpoll_callback);
  701. }
  702. net_unlock();
  703. }
  704. /****************************************************************************
  705. * Name: macnet_txavail
  706. *
  707. * Description:
  708. * Driver callback invoked when new TX data is available. This is a
  709. * stimulus perform an out-of-cycle poll and, thereby, reduce the TX
  710. * latency.
  711. *
  712. * Input Parameters:
  713. * dev - Reference to the NuttX driver state structure
  714. *
  715. * Returned Value:
  716. * None
  717. *
  718. * Assumptions:
  719. * Called in normal user mode
  720. *
  721. ****************************************************************************/
  722. static int macnet_txavail(FAR struct net_driver_s *dev)
  723. {
  724. FAR struct macnet_driver_s *priv = (FAR struct macnet_driver_s *)dev->d_private;
  725. wlinfo("Available=%u\n", work_available(&priv->md_pollwork));
  726. /* Is our single work structure available? It may not be if there are
  727. * pending interrupt actions and we will have to ignore the Tx
  728. * availability action.
  729. */
  730. if (work_available(&priv->md_pollwork))
  731. {
  732. /* Schedule to serialize the poll on the worker thread. */
  733. work_queue(WPANWORK, &priv->md_pollwork, macnet_txavail_work, priv, 0);
  734. }
  735. return OK;
  736. }
  737. /****************************************************************************
  738. * Name: macnet_addmac
  739. *
  740. * Description:
  741. * NuttX Callback: Add the specified MAC address to the hardware multicast
  742. * address filtering
  743. *
  744. * Input Parameters:
  745. * dev - Reference to the NuttX driver state structure
  746. * mac - The MAC address to be added
  747. *
  748. * Returned Value:
  749. * None
  750. *
  751. * Assumptions:
  752. *
  753. ****************************************************************************/
  754. #ifdef CONFIG_NET_MCASTGROUP
  755. static int macnet_addmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac)
  756. {
  757. FAR struct macnet_driver_s *priv = (FAR struct macnet_driver_s *)dev->d_private;
  758. /* Add the MAC address to the hardware multicast routing table. Not used
  759. * with IEEE 802.15.4 radios.
  760. */
  761. return -ENOSYS;
  762. }
  763. #endif
  764. /****************************************************************************
  765. * Name: macnet_rmmac
  766. *
  767. * Description:
  768. * NuttX Callback: Remove the specified MAC address from the hardware multicast
  769. * address filtering
  770. *
  771. * Input Parameters:
  772. * dev - Reference to the NuttX driver state structure
  773. * mac - The MAC address to be removed
  774. *
  775. * Returned Value:
  776. * None
  777. *
  778. * Assumptions:
  779. *
  780. ****************************************************************************/
  781. #ifdef CONFIG_NET_MCASTGROUP
  782. static int macnet_rmmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac)
  783. {
  784. FAR struct macnet_driver_s *priv = (FAR struct macnet_driver_s *)dev->d_private;
  785. /* Remove the MAC address from the hardware multicast routing table Not used
  786. * with IEEE 802.15.4 radios.
  787. */
  788. return -ENOSYS;
  789. }
  790. #endif
  791. /****************************************************************************
  792. * Name: macnet_ioctl
  793. *
  794. * Description:
  795. * Handle network IOCTL commands directed to this device.
  796. *
  797. * Input Parameters:
  798. * dev - Reference to the NuttX driver state structure
  799. * cmd - The IOCTL command
  800. * arg - The argument for the IOCTL command
  801. *
  802. * Returned Value:
  803. * OK on success; Negated errno on failure.
  804. *
  805. * Assumptions:
  806. *
  807. ****************************************************************************/
  808. #ifdef CONFIG_NETDEV_IOCTL
  809. static int macnet_ioctl(FAR struct net_driver_s *dev, int cmd,
  810. unsigned long arg)
  811. {
  812. FAR struct macnet_driver_s *priv = (FAR struct macnet_driver_s *)dev->d_private;
  813. int ret = -EINVAL;
  814. ret = nxsem_wait(&priv->md_exclsem);
  815. if (ret < 0)
  816. {
  817. wlerr("ERROR: nxsem_wait failed: %d\n", ret);
  818. return ret;
  819. }
  820. /* Check for IOCTLs aimed at the IEEE802.15.4 MAC layer */
  821. if (_MAC802154IOCVALID(cmd))
  822. {
  823. FAR struct ieee802154_netmac_s *netmac =
  824. (FAR struct ieee802154_netmac_s *)arg;
  825. if (netmac != NULL)
  826. {
  827. unsigned long macarg = (unsigned int)((uintptr_t)&netmac->u);
  828. switch (cmd)
  829. {
  830. /* Command: MAC802154IOC_NOTIFY_REGISTER
  831. * Description: Register to receive a signal whenever there is a
  832. * event primitive sent from the MAC layer.
  833. * Argument: A read-only pointer to an instance of struct
  834. * macnet_notify_s
  835. * Return: Zero (OK) on success. Minus one will be returned on
  836. * failure with the errno value set appropriately.
  837. */
  838. case MAC802154IOC_NOTIFY_REGISTER:
  839. {
  840. /* Save the notification events */
  841. priv->md_notify_event = netmac->u.event;
  842. priv->md_notify_pid = getpid();
  843. priv->md_notify_registered = true;
  844. ret = OK;
  845. }
  846. break;
  847. case MAC802154IOC_GET_EVENT:
  848. {
  849. FAR struct ieee802154_primitive_s *primitive;
  850. while (1)
  851. {
  852. /* Try popping an event off the queue */
  853. primitive = (FAR struct ieee802154_primitive_s *)
  854. sq_remfirst(&priv->primitive_queue);
  855. /* If there was an event to pop off, copy it into the user
  856. * data and free it from the MAC layer's memory.
  857. */
  858. if (primitive != NULL)
  859. {
  860. memcpy(&netmac->u, primitive,
  861. sizeof(struct ieee802154_primitive_s));
  862. /* Free the event */
  863. ieee802154_primitive_free(primitive);
  864. ret = OK;
  865. break;
  866. }
  867. /* There can only be one getevent pending at a time */
  868. if (priv->md_eventpending)
  869. {
  870. ret = -EAGAIN;
  871. break;
  872. }
  873. priv->md_eventpending = true;
  874. nxsem_post(&priv->md_exclsem);
  875. /* Wait to be signaled when an event is queued */
  876. ret = nxsem_wait(&priv->md_eventsem);
  877. if (ret < 0)
  878. {
  879. DEBUGASSERT(ret == -EINTR || ret == -ECANCELED);
  880. priv->md_eventpending = false;
  881. return ret;
  882. }
  883. /* Get exclusive access again, then loop back around and try and
  884. * pop an event off the queue
  885. */
  886. ret = nxsem_wait(&priv->md_exclsem);
  887. if (ret < 0)
  888. {
  889. wlerr("ERROR: nxsem_wait failed: %d\n", ret);
  890. return ret;
  891. }
  892. }
  893. }
  894. break;
  895. case MAC802154IOC_ENABLE_EVENTS:
  896. {
  897. priv->md_enableevents = netmac->u.enable;
  898. ret = OK;
  899. }
  900. break;
  901. default:
  902. {
  903. ret = mac802154_ioctl(priv->md_mac, cmd, macarg);
  904. }
  905. break;
  906. }
  907. }
  908. }
  909. /* Okay, we have no idea what this command is.. just give to the
  910. * IEEE802.15.4 MAC layer without modification.
  911. */
  912. else
  913. {
  914. ret = mac802154_ioctl(priv->md_mac, cmd, arg);
  915. }
  916. nxsem_post(&priv->md_exclsem);
  917. return ret;
  918. }
  919. #endif
  920. /****************************************************************************
  921. * Name: macnet_get_mhrlen
  922. *
  923. * Description:
  924. * Calculate the MAC header length given the frame meta-data.
  925. *
  926. * Input Parameters:
  927. * netdev - The network device that will mediate the MAC interface
  928. * meta - Obfuscated metadata structure needed to create the radio
  929. * MAC header
  930. *
  931. * Returned Value:
  932. * A non-negative MAC header length is returned on success; a negated
  933. * errno value is returned on any failure.
  934. *
  935. ****************************************************************************/
  936. static int macnet_get_mhrlen(FAR struct radio_driver_s *netdev,
  937. FAR const void *meta)
  938. {
  939. FAR struct macnet_driver_s *priv =
  940. (FAR struct macnet_driver_s *)netdev;
  941. FAR const struct ieee802154_frame_meta_s *pktmeta =
  942. (FAR const struct ieee802154_frame_meta_s *)meta;
  943. DEBUGASSERT(priv != NULL && priv->md_mac != NULL && pktmeta != NULL);
  944. return mac802154_get_mhrlen(priv->md_mac, pktmeta);
  945. }
  946. /****************************************************************************
  947. * Name: macnet_req_data
  948. *
  949. * Description:
  950. * Requests the transfer of a list of frames to the MAC.
  951. *
  952. * Input Parameters:
  953. * netdev - The network device that will mediate the MAC interface
  954. * meta - Obfuscated metadata structure needed to create the radio
  955. * MAC header
  956. * framelist - Head of a list of frames to be transferred.
  957. *
  958. * Returned Value:
  959. * Zero (OK) returned on success; a negated errno value is returned on
  960. * any failure.
  961. *
  962. ****************************************************************************/
  963. static int macnet_req_data(FAR struct radio_driver_s *netdev,
  964. FAR const void *meta, FAR struct iob_s *framelist)
  965. {
  966. FAR struct macnet_driver_s *priv =
  967. (FAR struct macnet_driver_s *)netdev;
  968. FAR const struct ieee802154_frame_meta_s *pktmeta =
  969. (FAR const struct ieee802154_frame_meta_s *)meta;
  970. FAR struct iob_s *iob;
  971. int ret;
  972. wlinfo("Received framelist\n");
  973. DEBUGASSERT(priv != NULL && pktmeta != NULL && framelist != NULL);
  974. /* Add the incoming list of frames to the MAC's outgoing queue */
  975. for (iob = framelist; iob != NULL; iob = framelist)
  976. {
  977. /* Increment statistics */
  978. NETDEV_TXPACKETS(&priv->md_dev.r_dev);
  979. /* Remove the IOB from the queue */
  980. framelist = iob->io_flink;
  981. iob->io_flink = NULL;
  982. /* Transfer the frame to the MAC. mac802154_req_data will return
  983. * -EINTR if a signal is received during certain phases of processing.
  984. * In this context we just need to ignore -EINTR errors and try again.
  985. */
  986. do
  987. {
  988. ret = mac802154_req_data(priv->md_mac, pktmeta, iob);
  989. }
  990. while (ret == -EINTR);
  991. if (ret < 0)
  992. {
  993. wlerr("ERROR: mac802154_req_data failed: %d\n", ret);
  994. iob_free(iob, IOBUSER_WIRELESS_MAC802154_NETDEV);
  995. for (iob = framelist; iob != NULL; iob = framelist)
  996. {
  997. /* Remove the IOB from the queue and free */
  998. framelist = iob->io_flink;
  999. iob_free(iob, IOBUSER_WIRELESS_MAC802154_NETDEV);
  1000. }
  1001. NETDEV_TXERRORS(&priv->md_dev.r_dev);
  1002. return ret;
  1003. }
  1004. NETDEV_TXDONE(&priv->md_dev.r_dev);
  1005. }
  1006. return OK;
  1007. }
  1008. /****************************************************************************
  1009. * Name: macnet_properties
  1010. *
  1011. * Description:
  1012. * Different packet radios may have different properties. If there are
  1013. * multiple packet radios, then those properties have to be queried at
  1014. * run time. This information is provided to the 6LoWPAN network via the
  1015. * following structure.
  1016. *
  1017. * Input Parameters:
  1018. * netdev - The network device to be queried
  1019. * properties - Location where radio properties will be returned.
  1020. *
  1021. * Returned Value:
  1022. * Zero (OK) returned on success; a negated errno value is returned on
  1023. * any failure.
  1024. *
  1025. ****************************************************************************/
  1026. static int macnet_properties(FAR struct radio_driver_s *netdev,
  1027. FAR struct radiodev_properties_s *properties)
  1028. {
  1029. DEBUGASSERT(netdev != NULL && properties != NULL);
  1030. memset(properties, 0, sizeof(struct radiodev_properties_s));
  1031. /* General */
  1032. properties->sp_addrlen = MACNET_ADDRSIZE; /* Length of an address */
  1033. properties->sp_framelen = MACNET_FRAMELEN; /* Fixed frame length */
  1034. /* Multicast address (uses broadcast address)
  1035. *
  1036. * For meshes (only) a multicast address candetermined by the first 3 bits
  1037. * of a short address (RFC 4944):
  1038. *
  1039. * 0xxxxxxx xxxxxxxx: Unicast address
  1040. * 100xxxxx xxxxxxxx: Multicast address
  1041. * 101xxxxx xxxxxxxx: Reserved
  1042. * 110xxxxx xxxxxxxx: Reserved
  1043. * 111xxxxx xxxxxxxx: Reserved
  1044. *
  1045. * Otherwise, Multicast is implemented with the broadcast address
  1046. * (qualified by the destination PANID).
  1047. */
  1048. properties->sp_mcast.nv_addrlen = IEEE802154_SADDRSIZE;
  1049. memset(properties->sp_mcast.nv_addr, 0xff, RADIO_MAX_ADDRLEN);
  1050. /* Broadcast address */
  1051. properties->sp_bcast.nv_addrlen = IEEE802154_SADDRSIZE;
  1052. memset(properties->sp_mcast.nv_addr, 0xff, RADIO_MAX_ADDRLEN);
  1053. #ifdef CONFIG_NET_STARPOINT
  1054. /* Star hub node address.
  1055. *
  1056. * If this node is a "point" in a star topology, then the hub node
  1057. * MAC address is the address of the hub/PAN coordinator.
  1058. */
  1059. #ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR
  1060. (void)macnet_coord_eaddr(netdev, properties->sp_hubnode.nv_addr);
  1061. properties->sp_hubnode.nv_addrlen = IEEE802154_EADDRSIZE;
  1062. #else
  1063. (void)macnet_coord_saddr(netdev, properties->sp_hubnode.nv_addr);
  1064. properties->sp_hubnode.nv_addrlen = IEEE802154_SADDRSIZE;
  1065. #endif
  1066. #endif
  1067. return OK;
  1068. }
  1069. /****************************************************************************
  1070. * Public Functions
  1071. ****************************************************************************/
  1072. /****************************************************************************
  1073. * Name: mac802154netdev_register
  1074. *
  1075. * Description:
  1076. * Register a network driver to access the IEEE 802.15.4 MAC layer from
  1077. * a socket using 6LoWPAN
  1078. *
  1079. * Input Parameters:
  1080. * mac - Pointer to the mac layer struct to be registered.
  1081. *
  1082. * Returned Value:
  1083. * Zero (OK) is returned on success. Otherwise a negated errno value is
  1084. * returned to indicate the nature of the failure.
  1085. *
  1086. ****************************************************************************/
  1087. int mac802154netdev_register(MACHANDLE mac)
  1088. {
  1089. FAR struct macnet_driver_s *priv;
  1090. FAR struct radio_driver_s *radio;
  1091. FAR struct net_driver_s *dev;
  1092. FAR struct mac802154_maccb_s *maccb;
  1093. int ret;
  1094. DEBUGASSERT(mac != NULL);
  1095. /* Get the interface structure associated with this interface number. */
  1096. priv = (FAR struct macnet_driver_s *)
  1097. kmm_zalloc(sizeof(struct macnet_driver_s));
  1098. if (priv == NULL)
  1099. {
  1100. nerr("ERROR: Failed to allocate the device structure\n");
  1101. return -ENOMEM;
  1102. }
  1103. /* Initialize the driver structure */
  1104. radio = &priv->md_dev;
  1105. dev = &radio->r_dev;
  1106. dev->d_ifup = macnet_ifup; /* I/F up (new IP address) callback */
  1107. dev->d_ifdown = macnet_ifdown; /* I/F down callback */
  1108. dev->d_txavail = macnet_txavail; /* New TX data callback */
  1109. #ifdef CONFIG_NET_MCASTGROUP
  1110. dev->d_addmac = macnet_addmac; /* Add multicast MAC address */
  1111. dev->d_rmmac = macnet_rmmac; /* Remove multicast MAC address */
  1112. #endif
  1113. #ifdef CONFIG_NETDEV_IOCTL
  1114. dev->d_ioctl = macnet_ioctl; /* Handle network IOCTL commands */
  1115. #endif
  1116. dev->d_private = (FAR void *)priv; /* Used to recover private state from dev */
  1117. /* Create a watchdog for timing polling for and timing of transmissions */
  1118. priv->md_mac = mac; /* Save the MAC interface instance */
  1119. priv->md_txpoll = wd_create(); /* Create periodic poll timer */
  1120. /* Setup a locking semaphore for exclusive device driver access */
  1121. nxsem_init(&priv->md_exclsem, 0, 1);
  1122. DEBUGASSERT(priv->md_txpoll != NULL);
  1123. /* Set the network mask. */
  1124. macnet_netmask(dev);
  1125. /* Initialize the Network frame-related callbacks */
  1126. radio->r_get_mhrlen = macnet_get_mhrlen; /* Get MAC header length */
  1127. radio->r_req_data = macnet_req_data; /* Enqueue frame for transmission */
  1128. radio->r_properties = macnet_properties; /* Return radio properties */
  1129. /* Initialize fields related to MAC event handling */
  1130. priv->md_eventpending = false;
  1131. nxsem_init(&priv->md_eventsem, 0, 0);
  1132. nxsem_setprotocol(&priv->md_eventsem, SEM_PRIO_NONE);
  1133. sq_init(&priv->primitive_queue);
  1134. priv->md_enableevents = false;
  1135. priv->md_notify_registered = false;
  1136. /* Initialize the MAC callbacks */
  1137. priv->md_cb.mc_priv = priv;
  1138. maccb = &priv->md_cb.mc_cb;
  1139. maccb->flink = NULL;
  1140. maccb->prio = CONFIG_IEEE802154_NETDEV_RECVRPRIO;
  1141. maccb->notify = macnet_notify;
  1142. /* Bind the callback structure */
  1143. ret = mac802154_bind(mac, maccb);
  1144. if (ret < 0)
  1145. {
  1146. nerr("ERROR: Failed to bind the MAC callbacks: %d\n", ret);
  1147. goto errout;
  1148. }
  1149. ret = macnet_update_nvaddr(&priv->md_dev.r_dev);
  1150. if (ret < 0)
  1151. {
  1152. nerr("ERROR: Failed updating nvaddr: %d\n", ret);
  1153. goto errout;
  1154. }
  1155. #ifdef CONFIG_NET_6LOWPAN
  1156. /* Make sure the our single packet buffer is attached. We must do this before
  1157. * registering the device since, once the device is registered, a packet may
  1158. * be attempted to be forwarded and require the buffer.
  1159. */
  1160. priv->md_dev.r_dev.d_buf = priv->md_iobuffer.rb_buf;
  1161. #endif
  1162. /* Register the device with the OS so that socket IOCTLs can be performed */
  1163. (void)netdev_register(&priv->md_dev.r_dev, NET_LL_IEEE802154);
  1164. /* Put the network in the DOWN state, let the user decide when to bring it up */
  1165. dev->d_flags = IFF_DOWN;
  1166. return macnet_ifdown(&priv->md_dev.r_dev);
  1167. errout:
  1168. /* Release wdog timers */
  1169. wd_delete(priv->md_txpoll);
  1170. /* Free memory and return the error */
  1171. kmm_free(priv);
  1172. return ret;
  1173. }
  1174. #endif /* CONFIG_NET && CONFIG_NET_skeleton */