xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlme/include/wlan_mlme_cmn.h (revision 97f44cd39e4ff816eaa1710279d28cf6b9e65ad9)
1 /*
2  * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /**
18  * DOC: Define Common MLME structure and APIs
19  */
20 #ifndef _WLAN_MLME_CMN_H_
21 #define _WLAN_MLME_CMN_H_
22 
23 #include <include/wlan_psoc_mlme.h>
24 #include <include/wlan_pdev_mlme.h>
25 #include <include/wlan_vdev_mlme.h>
26 #ifdef FEATURE_CM_ENABLE
27 #include "wlan_cm_public_struct.h"
28 #endif
29 
30 #ifdef FEATURE_CM_ENABLE
31 
32 /**
33  * mlme_cm_ops: connection manager osif callbacks
34  * @mlme_cm_connect_complete_cb: Connect done callback
35  * @vdev: vdev pointer
36  * @rsp: connect response
37  *
38  * @mlme_cm_failed_candidate_cb: Callback to indicate failed candidate
39  * @vdev: vdev pointer
40  * @rsp: connect response
41  *
42  * @mlme_cm_update_id_and_src_cb: Callback to update connect id and
43  *                                source of the connect request
44  * @vdev: vdev pointer
45  * @Source: Source of the connect req
46  * @cm_id: connection manager id
47  *
48  * @mlme_cm_disconnect_complete_cb: Disconnect done callback
49  * @vdev: vdev pointer
50  * @rsp: Disconnect response
51  *
52  * @mlme_cm_disconnect_start_cb: Disconnect start callback
53  * @vdev: vdev pointer
54  */
55 struct mlme_cm_ops {
56 	QDF_STATUS (*mlme_cm_connect_complete_cb)(
57 					struct wlan_objmgr_vdev *vdev,
58 					struct wlan_cm_connect_resp *rsp);
59 	QDF_STATUS (*mlme_cm_failed_candidate_cb)(
60 					struct wlan_objmgr_vdev *vdev,
61 					struct wlan_cm_connect_resp *rsp);
62 	QDF_STATUS (*mlme_cm_update_id_and_src_cb)(
63 					struct wlan_objmgr_vdev *vdev,
64 					enum wlan_cm_source source,
65 					wlan_cm_id cm_id);
66 	QDF_STATUS (*mlme_cm_disconnect_complete_cb)(
67 					struct wlan_objmgr_vdev *vdev,
68 					struct wlan_cm_discon_rsp *rsp);
69 	QDF_STATUS (*mlme_cm_disconnect_start_cb)(
70 					struct wlan_objmgr_vdev *vdev);
71 };
72 #endif
73 
74 /**
75  * struct vdev_mlme_ext_ops - VDEV MLME legacy callbacks structure
76  * @mlme_psoc_ext_hdl_create:               callback to invoke creation of
77  *                                          legacy psoc object
78  * @mlme_psoc_ext_hdl_destroy:              callback to invoke destroy of legacy
79  *                                          psoc object
80  * @mlme_pdev_ext_hdl_create:               callback to invoke creation of
81  *                                          legacy pdev object
82  * @mlme_pdev_ext_hdl_destroy:              callback to invoke destroy of legacy
83  *                                          pdev object
84  * @mlme_vdev_ext_hdl_create:               callback to invoke creation of
85  *                                          legacy vdev object
86  * @mlme_vdev_ext_hdl_post_create:          callback to invoke post creation
87  *                                          actions of legacy vdev object
88  * @mlme_vdev_ext_hdl_destroy:              callback to invoke destroy of legacy
89  *                                          vdev object
90  * @mlme_vdev_start_fw_send:                callback to invoke vdev start
91  *                                          command
92  * @mlme_vdev_stop_fw_send:                 callback to invoke vdev stop command
93  * @mlme_vdev_down_fw_send:                 callback to invoke vdev down command
94  * @mlme_multivdev_restart_fw_send:         callback to invoke multivdev restart
95  *                                          command
96  * @mlme_vdev_enqueue_exp_cmd:              callback to enqueue exception
97  *                                          command
98  *                                          required by serialization
99  * @mlme_multi_vdev_restart_resp:           callback to process multivdev
100  *                                          restart response
101  * @mlme_cm_ext_connect_start_ind_cb:       callback to indicate connect start
102  * @mlme_cm_ext_bss_select_ind_cb:          callback to indicate candidate
103  *                                          select for connect
104  * @mlme_cm_ext_bss_peer_create_req_cb:     callback to bss peer create request
105  * @mlme_cm_ext_connect_req_cb:             callback for connect request to
106  *                                          VDEV/PEER SM
107  * @mlme_cm_ext_connect_complete_ind_cb:    callback to indicate connect
108  *                                          complete
109  * @mlme_cm_ext_disconnect_start_ind_cb :   callback to indicate disconnect
110  *                                          start
111  * @mlme_cm_ext_disconnect_req_cb:          callback to disconnect req to
112  *                                          VDEV/PEER SM
113  * @mlme_cm_ext_bss_peer_delete_req_cb:     callback to bss peer delete request
114  * @mlme_cm_ext_disconnect_complete_ind_cb: callback to indicate disconnect
115  *                                          complete
116  * @mlme_cm_ext_vdev_down_req_cb:           callback to send vdev down to FW
117  */
118 struct mlme_ext_ops {
119 	QDF_STATUS (*mlme_psoc_ext_hdl_create)(
120 				struct psoc_mlme_obj *psoc_mlme);
121 	QDF_STATUS (*mlme_psoc_ext_hdl_destroy)(
122 				struct psoc_mlme_obj *pdev_mlme);
123 	QDF_STATUS (*mlme_pdev_ext_hdl_create)(
124 				struct pdev_mlme_obj *pdev_mlme);
125 	QDF_STATUS (*mlme_pdev_ext_hdl_destroy)(
126 				struct pdev_mlme_obj *pdev_mlme);
127 	QDF_STATUS (*mlme_vdev_ext_hdl_create)(
128 				struct vdev_mlme_obj *vdev_mlme);
129 	QDF_STATUS (*mlme_vdev_ext_hdl_post_create)(
130 				struct vdev_mlme_obj *vdev_mlme);
131 	QDF_STATUS (*mlme_vdev_ext_hdl_destroy)(
132 				struct vdev_mlme_obj *vdev_mlme);
133 	QDF_STATUS (*mlme_vdev_start_fw_send)(
134 				struct wlan_objmgr_vdev *vdev, uint8_t restart);
135 	QDF_STATUS (*mlme_vdev_stop_fw_send)(struct wlan_objmgr_vdev *vdev);
136 	QDF_STATUS (*mlme_vdev_down_fw_send)(struct wlan_objmgr_vdev *vdev);
137 	QDF_STATUS (*mlme_multivdev_restart_fw_send)(
138 				struct wlan_objmgr_pdev *pdev);
139 	QDF_STATUS (*mlme_vdev_enqueue_exp_cmd)(
140 				struct vdev_mlme_obj *vdev_mlme,
141 				uint8_t cmd_type);
142 	QDF_STATUS (*mlme_vdev_ext_delete_rsp)(
143 					   struct wlan_objmgr_psoc *psoc,
144 					   struct vdev_delete_response *rsp);
145 	QDF_STATUS (*mlme_multi_vdev_restart_resp)(
146 				struct wlan_objmgr_psoc *psoc,
147 				struct multi_vdev_restart_resp *resp);
148 #ifdef FEATURE_CM_ENABLE
149 	QDF_STATUS (*mlme_cm_ext_connect_start_ind_cb)(
150 				struct wlan_objmgr_vdev *vdev,
151 				struct wlan_cm_connect_req *req);
152 	QDF_STATUS (*mlme_cm_ext_bss_select_ind_cb)(
153 			struct wlan_objmgr_vdev *vdev,
154 			struct wlan_cm_vdev_connect_req *req);
155 	QDF_STATUS (*mlme_cm_ext_bss_peer_create_req_cb)(
156 				struct wlan_objmgr_vdev *vdev,
157 				struct qdf_mac_addr *peer_mac);
158 	QDF_STATUS (*mlme_cm_ext_connect_req_cb)(struct wlan_objmgr_vdev *vdev,
159 			struct wlan_cm_vdev_connect_req *req);
160 	QDF_STATUS (*mlme_cm_ext_connect_complete_ind_cb)(
161 				struct wlan_objmgr_vdev *vdev,
162 				struct wlan_cm_connect_resp *rsp);
163 	QDF_STATUS (*mlme_cm_ext_disconnect_start_ind_cb)(
164 				struct wlan_objmgr_vdev *vdev,
165 				struct wlan_cm_disconnect_req *req);
166 	QDF_STATUS (*mlme_cm_ext_disconnect_req_cb)
167 			(struct wlan_objmgr_vdev *vdev,
168 			struct wlan_cm_vdev_discon_req *req);
169 	QDF_STATUS (*mlme_cm_ext_bss_peer_delete_req_cb)(
170 			struct wlan_objmgr_vdev *vdev);
171 	QDF_STATUS (*mlme_cm_ext_disconnect_complete_ind_cb)(
172 				struct wlan_objmgr_vdev *vdev,
173 				struct wlan_cm_discon_rsp *rsp);
174 	QDF_STATUS (*mlme_cm_ext_vdev_down_req_cb)(
175 				struct wlan_objmgr_vdev *vdev);
176 #endif
177 };
178 
179 /**
180  * mlme_psoc_ops_ext_hdl_create() - Alloc PSOC mlme ext handle
181  * @psoc_mlme:  PSOC MLME comp object
182  *
183  * API to allocate PSOC MLME ext handle
184  *
185  * Return: SUCCESS on successful allocation
186  *         Else FAILURE
187  */
188 QDF_STATUS mlme_psoc_ops_ext_hdl_create(struct psoc_mlme_obj *psoc_mlme);
189 
190 /**
191  * mlme_psoc_ops_ext_hdl_destroy() - Destroy PSOC mlme ext handle
192  * @psoc_mlme:  PSOC MLME comp object
193  *
194  * API to free psoc MLME ext handle
195  *
196  * Return: SUCCESS on successful free
197  *         Else FAILURE
198  */
199 QDF_STATUS mlme_psoc_ops_ext_hdl_destroy(struct psoc_mlme_obj *psoc_mlme);
200 
201 /**
202  * mlme_pdev_ops_ext_hdl_create - Alloc PDEV mlme ext handle
203  * @pdev_mlme_obj:  PDEV MLME comp object
204  *
205  * API to allocate PDEV MLME ext handle
206  *
207  * Return: SUCCESS on successful allocation
208  *         Else FAILURE
209  */
210 QDF_STATUS mlme_pdev_ops_ext_hdl_create(struct pdev_mlme_obj *pdev_mlme);
211 
212 /**
213  * mlme_pdev_ops_ext_hdl_destroy - Destroy PDEV mlme ext handle
214  * @pdev_mlme_obj:  PDEV MLME comp object
215  *
216  * API to free pdev MLME ext handle
217  *
218  * Return: SUCCESS on successful free
219  *         Else FAILURE
220  */
221 QDF_STATUS mlme_pdev_ops_ext_hdl_destroy(struct pdev_mlme_obj *pdev_mlme);
222 
223 /**
224  * mlme_vdev_ops_ext_hdl_create - Alloc VDEV mlme ext handle
225  * @vdev_mlme_obj:  VDEV MLME comp object
226  *
227  * API to allocate VDEV MLME ext handle
228  *
229  * Return: SUCCESS on successful allocation
230  *         Else FAILURE
231  */
232 QDF_STATUS mlme_vdev_ops_ext_hdl_create(struct vdev_mlme_obj *vdev_mlme);
233 
234 /**
235  * mlme_vdev_ops_ext_hdl_post_create - Perform post VDEV mlme ext handle alloc
236  *                                     operations
237  * @vdev_mlme_obj:  VDEV MLME comp object
238  *
239  * API to perform post vdev MLME ext handle allocation operations
240  *
241  * Return: SUCCESS on initialization successful
242  *         Else FAILURE
243  */
244 QDF_STATUS mlme_vdev_ops_ext_hdl_post_create(struct vdev_mlme_obj *vdev_mlme);
245 
246 /**
247  * mlme_vdev_ops_ext_hdl_destroy - Destroy VDEV mlme ext handle
248  * @vdev_mlme_obj:  VDEV MLME comp object
249  *
250  * API to free vdev MLME ext handle
251  *
252  * Return: SUCCESS on successful free
253  *         Else FAILURE
254  */
255 QDF_STATUS mlme_vdev_ops_ext_hdl_destroy(struct vdev_mlme_obj *vdev_mlme);
256 
257 /**
258  * mlme_vdev_enqueue_exp_ser_cmd - Enqueue exception serialization cmd
259  * @vdev_mlme_obj:  VDEV MLME comp object
260  * @cmd_type: Serialization command type
261  *
262  * API to enqueue the exception serialization command, used by
263  * mlme-serialization wrapper layer
264  *
265  * Return: SUCCESS on successful enqueuing the command
266  *         Else FAILURE
267  */
268 QDF_STATUS mlme_vdev_enqueue_exp_ser_cmd(struct vdev_mlme_obj *vdev_mlme,
269 					 uint8_t cmd_type);
270 
271 /**
272  * mlme_vdev_ops_start_fw_send - Send WMI START/RESTART commmand to FW
273  * @vdev:  VDEV object
274  *
275  * API to send WMI start/restart command to FW
276  *
277  * Return: SUCCESS on successful sending the command
278  *         Else FAILURE
279  */
280 QDF_STATUS mlme_vdev_ops_start_fw_send(struct wlan_objmgr_vdev *vdev,
281 				       uint8_t restart);
282 
283 /**
284  * mlme_vdev_ops_multivdev_restart_fw_cmd_send - Send WMI Multivdev restart
285  *                                              commmand to FW
286  * @pdev:  PDEV object
287  *
288  * API to send WMI multivdev restart command to FW
289  *
290  * Return: SUCCESS on successful sending the command
291  *         Else FAILURE
292  */
293 QDF_STATUS mlme_vdev_ops_multivdev_restart_fw_cmd_send(
294 						struct wlan_objmgr_pdev *pdev);
295 
296 /**
297  * mlme_vdev_ops_stop_fw_send - Send WMI STOP commmand to FW
298  * @vdev:  VDEV object
299  *
300  * API to send WMI stop command to FW
301  *
302  * Return: SUCCESS on successful sending the command
303  *         Else FAILURE
304  */
305 QDF_STATUS mlme_vdev_ops_stop_fw_send(struct wlan_objmgr_vdev *vdev);
306 
307 /**
308  * mlme_vdev_ops_down_fw_send - Send WMI Down commmand to FW
309  * @vdev:  VDEV object
310  *
311  * API to send WMI down command to FW
312  *
313  * Return: SUCCESS on successful sending the command
314  *         Else FAILURE
315  */
316 QDF_STATUS mlme_vdev_ops_down_fw_send(struct wlan_objmgr_vdev *vdev);
317 
318 /*
319  * mlme_vdev_ops_ext_hdl_multivdev_restart_resp() - Handler multivdev restart
320  * response event
321  * @psoc: PSOC object manager handle
322  * @resp: Restart response event
323  *
324  * Return: Success on successful handling of the response event,
325  *         Else failure
326  */
327 QDF_STATUS mlme_vdev_ops_ext_hdl_multivdev_restart_resp(
328 		struct wlan_objmgr_psoc *psoc,
329 		struct multi_vdev_restart_resp *resp);
330 
331 /**
332  * mlme_set_ops_register_cb - Sets ops registration callback
333  * @ops_cb:  Function pointer
334  *
335  * API to set ops registration call back
336  *
337  * Return: void
338  */
339 typedef struct mlme_ext_ops *(*mlme_get_global_ops_cb)(void);
340 void mlme_set_ops_register_cb(mlme_get_global_ops_cb ops_cb);
341 
342 /**
343  * wlan_cmn_mlme_init - Initializes MLME component
344  *
345  * Registers callbacks with object manager for create/destroy
346  *
347  * Return: SUCCESS on successful registration
348  *         FAILURE, if registration fails
349  */
350 QDF_STATUS wlan_cmn_mlme_init(void);
351 
352 /**
353  * wlan_cmn_mlme_deinit - Uninitializes MLME component
354  *
355  * Unregisters callbacks with object manager for create/destroy
356  *
357  * Return: SUCCESS on successful registration
358  *         FAILURE, if registration fails
359  */
360 QDF_STATUS wlan_cmn_mlme_deinit(void);
361 
362 /**
363  * mlme_vdev_ops_ext_hdl_delete_rsp - Vdev Delete response ext handler
364  * @psoc: PSOC object
365  * @rsp: Vdev delete response received from the firmware
366  *
367  * API to invoke the legacy delete response handler for legacy cleanup
368  *
369  * Return: SUCCESS on successful deletion
370  *         FAILURE, if deletion fails
371  */
372 QDF_STATUS mlme_vdev_ops_ext_hdl_delete_rsp(struct wlan_objmgr_psoc *psoc,
373 					    struct vdev_delete_response *rsp);
374 
375 #ifdef FEATURE_CM_ENABLE
376 /**
377  * mlme_cm_connect_start_ind() - Connection manager ext Connect start indication
378  * @vdev: VDEV object
379  * @req: Connection manager connect request
380  *
381  * Return: QDF_STATUS
382  */
383 QDF_STATUS mlme_cm_connect_start_ind(struct wlan_objmgr_vdev *vdev,
384 				     struct wlan_cm_connect_req *req);
385 
386 /**
387  * mlme_cm_bss_select_ind() - Connection manager ext Connect candidate
388  * select indication, to do operations for the candidate
389  * @vdev: VDEV object
390  * @req: Vdev connect request
391  *
392  * Return: QDF_STATUS
393  */
394 QDF_STATUS mlme_cm_bss_select_ind(struct wlan_objmgr_vdev *vdev,
395 				  struct wlan_cm_vdev_connect_req *req);
396 
397 /**
398  * mlme_cm_bss_peer_create_req() - Connection manager ext bss peer create
399  * request
400  * @vdev: VDEV object
401  * @peer_mac: Peer mac address
402  *
403  * Return: QDF_STATUS
404  */
405 QDF_STATUS mlme_cm_bss_peer_create_req(struct wlan_objmgr_vdev *vdev,
406 				       struct qdf_mac_addr *peer_mac);
407 
408 /**
409  * mlme_cm_connect_req() - Connection manager ext connect request to start vdev
410  * and peer assoc state machine
411  * @vdev: VDEV object
412  * @req: Vdev connect request
413  *
414  * Context: The req is on stack, so the API need to make a copy, if it want to
415  * use the req after return.
416  *
417  * Return: QDF_STATUS
418  */
419 QDF_STATUS mlme_cm_connect_req(struct wlan_objmgr_vdev *vdev,
420 			       struct wlan_cm_vdev_connect_req *req);
421 
422 /**
423  * mlme_cm_connect_complete_ind() - Connection manager ext connect complete
424  * indication
425  * @vdev: VDEV object
426  * @rsp: Connection manager connect response
427  *
428  * Return: QDF_STATUS
429  */
430 QDF_STATUS mlme_cm_connect_complete_ind(struct wlan_objmgr_vdev *vdev,
431 					struct wlan_cm_connect_resp *rsp);
432 
433 /**
434  * mlme_cm_disconnect_start_ind() - Connection manager ext disconnect start
435  * indication
436  * @vdev: VDEV object
437  * @req: Connection manager disconnect request
438  *
439  * Return: QDF_STATUS
440  */
441 QDF_STATUS mlme_cm_disconnect_start_ind(struct wlan_objmgr_vdev *vdev,
442 					struct wlan_cm_disconnect_req *req);
443 
444 /**
445  * mlme_cm_disconnect_req() - Connection manager ext disconnect
446  * req to vdev and peer sm
447  * @vdev: VDEV object
448  * @req: vdev disconnect request
449  *
450  * Return: QDF_STATUS
451  */
452 QDF_STATUS mlme_cm_disconnect_req(struct wlan_objmgr_vdev *vdev,
453 				  struct wlan_cm_vdev_discon_req *req);
454 
455 /**
456  * mlme_cm_bss_peer_delete_req() - Connection manager ext bss peer delete
457  * request
458  * @vdev: VDEV object
459  *
460  * Return: QDF_STATUS
461  */
462 QDF_STATUS
463 mlme_cm_bss_peer_delete_req(struct wlan_objmgr_vdev *vdev);
464 
465 /**
466  * mlme_cm_disconnect_complete_ind() - Connection manager ext disconnect
467  * complete indication
468  * @vdev: VDEV object
469  * @rsp: Connection manager disconnect response
470  *
471  * Return: QDF_STATUS
472  */
473 QDF_STATUS mlme_cm_disconnect_complete_ind(struct wlan_objmgr_vdev *vdev,
474 					   struct wlan_cm_discon_rsp *rsp);
475 
476 /**
477  * mlme_cm_vdev_down() - Connection manager ext req to send vdev down to FW
478  * @vdev: VDEV object
479  *
480  * Return: QDF_STATUS
481  */
482 QDF_STATUS mlme_cm_vdev_down_req(struct wlan_objmgr_vdev *vdev);
483 
484 /**
485  * mlme_cm_osif_connect_complete() - Connect complete resp to osif
486  * @vdev: vdev pointer
487  * @rsp: Connect response
488  *
489  * Return: QDF_STATUS
490  */
491 QDF_STATUS mlme_cm_osif_connect_complete(struct wlan_objmgr_vdev *vdev,
492 					 struct wlan_cm_connect_resp *rsp);
493 
494 /**
495  * mlme_cm_osif_failed_candidate_ind() - Failed Candidate indication to osif
496  * @vdev: vdev pointer
497  * @rsp: Connect response
498  *
499  * Return: QDF_STATUS
500  */
501 QDF_STATUS
502 mlme_cm_osif_failed_candidate_ind(struct wlan_objmgr_vdev *vdev,
503 				  struct wlan_cm_connect_resp *rsp);
504 
505 /**
506  * mlme_cm_osif_update_id_and_src() - Update connection id and source to osif
507  * @vdev: vdev pointer
508  * @source: source of request
509  * @cm_id: connection manager id
510  *
511  * Return: QDF_STATUS
512  */
513 QDF_STATUS mlme_cm_osif_update_id_and_src(struct wlan_objmgr_vdev *vdev,
514 					  enum wlan_cm_source source,
515 					  wlan_cm_id cm_id);
516 
517 /**
518  * mlme_cm_osif_disconnect_complete() - Disconnect complete osif response
519  * @vdev: vdev pointer
520  * @cm_conn_rsp: Connect response
521  *
522  * Return: QDF_STATUS
523  */
524 QDF_STATUS
525 mlme_cm_osif_disconnect_complete(struct wlan_objmgr_vdev *vdev,
526 				 struct wlan_cm_discon_rsp *rsp);
527 
528 /**
529  * mlme_cm_osif_disconnect_start_ind() - osif Disconnect start indication
530  * @vdev: vdev pointer
531  * @cm_conn_rsp: Connect response
532  *
533  * Return: QDF_STATUS
534  */
535 QDF_STATUS mlme_cm_osif_disconnect_start_ind(struct wlan_objmgr_vdev *vdev);
536 
537 /**
538  * typedef osif_cm_get_global_ops_cb() - Callback to get connection manager
539  * global ops
540  */
541 typedef struct mlme_cm_ops *(*osif_cm_get_global_ops_cb)(void);
542 
543 /**
544  * mlme_set_osif_cm_cb() - Sets ops registration callback
545  * @cm_osif_ops:  Function pointer
546  *
547  * API to set ops registration call back
548  *
549  * Return: void
550  */
551 void mlme_set_osif_cm_cb(osif_cm_get_global_ops_cb cm_osif_ops);
552 
553 #endif
554 
555 #endif
556