1818
1919#define IEEE802154_BEACON_MHR_SZ 13
2020#define IEEE802154_BEACON_PL_SZ 4
21+ #define IEEE802154_MAC_CMD_MHR_SZ 23
22+ #define IEEE802154_MAC_CMD_PL_SZ 1
2123#define IEEE802154_BEACON_SKB_SZ (IEEE802154_BEACON_MHR_SZ + \
2224 IEEE802154_BEACON_PL_SZ)
25+ #define IEEE802154_MAC_CMD_SKB_SZ (IEEE802154_MAC_CMD_MHR_SZ + \
26+ IEEE802154_MAC_CMD_PL_SZ)
2327
2428/* mac802154_scan_cleanup_locked() must be called upon scan completion or abort.
2529 * - Completions are asynchronous, not locked by the rtnl and decided by the
@@ -131,6 +135,42 @@ static int mac802154_scan_find_next_chan(struct ieee802154_local *local,
131135 return 0 ;
132136}
133137
138+ static int mac802154_scan_prepare_beacon_req (struct ieee802154_local * local )
139+ {
140+ memset (& local -> scan_beacon_req , 0 , sizeof (local -> scan_beacon_req ));
141+ local -> scan_beacon_req .mhr .fc .type = IEEE802154_FC_TYPE_MAC_CMD ;
142+ local -> scan_beacon_req .mhr .fc .dest_addr_mode = IEEE802154_SHORT_ADDRESSING ;
143+ local -> scan_beacon_req .mhr .fc .version = IEEE802154_2003_STD ;
144+ local -> scan_beacon_req .mhr .fc .source_addr_mode = IEEE802154_NO_ADDRESSING ;
145+ local -> scan_beacon_req .mhr .dest .mode = IEEE802154_ADDR_SHORT ;
146+ local -> scan_beacon_req .mhr .dest .pan_id = cpu_to_le16 (IEEE802154_PANID_BROADCAST );
147+ local -> scan_beacon_req .mhr .dest .short_addr = cpu_to_le16 (IEEE802154_ADDR_BROADCAST );
148+ local -> scan_beacon_req .mac_pl .cmd_id = IEEE802154_CMD_BEACON_REQ ;
149+
150+ return 0 ;
151+ }
152+
153+ static int mac802154_transmit_beacon_req (struct ieee802154_local * local ,
154+ struct ieee802154_sub_if_data * sdata )
155+ {
156+ struct sk_buff * skb ;
157+ int ret ;
158+
159+ skb = alloc_skb (IEEE802154_MAC_CMD_SKB_SZ , GFP_KERNEL );
160+ if (!skb )
161+ return - ENOBUFS ;
162+
163+ skb -> dev = sdata -> dev ;
164+
165+ ret = ieee802154_mac_cmd_push (skb , & local -> scan_beacon_req , NULL , 0 );
166+ if (ret ) {
167+ kfree_skb (skb );
168+ return ret ;
169+ }
170+
171+ return ieee802154_mlme_tx (local , sdata , skb );
172+ }
173+
134174void mac802154_scan_worker (struct work_struct * work )
135175{
136176 struct ieee802154_local * local =
@@ -206,6 +246,13 @@ void mac802154_scan_worker(struct work_struct *work)
206246 goto end_scan ;
207247 }
208248
249+ if (scan_req -> type == NL802154_SCAN_ACTIVE ) {
250+ ret = mac802154_transmit_beacon_req (local , sdata );
251+ if (ret )
252+ dev_err (& sdata -> dev -> dev ,
253+ "Error when transmitting beacon request (%d)\n" , ret );
254+ }
255+
209256 ieee802154_configure_durations (wpan_phy , page , channel );
210257 scan_duration = mac802154_scan_get_channel_time (scan_req_duration ,
211258 wpan_phy -> symbol_duration );
@@ -231,8 +278,8 @@ int mac802154_trigger_scan_locked(struct ieee802154_sub_if_data *sdata,
231278 if (mac802154_is_scanning (local ))
232279 return - EBUSY ;
233280
234- /* TODO: support other scanning type */
235- if ( request -> type != NL802154_SCAN_PASSIVE )
281+ if ( request -> type != NL802154_SCAN_PASSIVE &&
282+ request -> type != NL802154_SCAN_ACTIVE )
236283 return - EOPNOTSUPP ;
237284
238285 /* Store scanning parameters */
@@ -247,6 +294,8 @@ int mac802154_trigger_scan_locked(struct ieee802154_sub_if_data *sdata,
247294 local -> scan_page = request -> page ;
248295 local -> scan_channel = -1 ;
249296 set_bit (IEEE802154_IS_SCANNING , & local -> ongoing );
297+ if (request -> type == NL802154_SCAN_ACTIVE )
298+ mac802154_scan_prepare_beacon_req (local );
250299
251300 nl802154_scan_started (request -> wpan_phy , request -> wpan_dev );
252301
0 commit comments