Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/include/linux/hwmon.h
122413 views
1
/* SPDX-License-Identifier: GPL-2.0-only */
2
/*
3
hwmon.h - part of lm_sensors, Linux kernel modules for hardware monitoring
4
5
This file declares helper functions for the sysfs class "hwmon",
6
for use by sensors drivers.
7
8
Copyright (C) 2005 Mark M. Hoffman <[email protected]>
9
10
*/
11
12
#ifndef _HWMON_H_
13
#define _HWMON_H_
14
15
#include <linux/bitops.h>
16
17
struct device;
18
struct attribute_group;
19
20
enum hwmon_sensor_types {
21
hwmon_chip,
22
hwmon_temp,
23
hwmon_in,
24
hwmon_curr,
25
hwmon_power,
26
hwmon_energy,
27
hwmon_energy64,
28
hwmon_humidity,
29
hwmon_fan,
30
hwmon_pwm,
31
hwmon_intrusion,
32
hwmon_max,
33
};
34
35
enum hwmon_chip_attributes {
36
hwmon_chip_temp_reset_history,
37
hwmon_chip_in_reset_history,
38
hwmon_chip_curr_reset_history,
39
hwmon_chip_power_reset_history,
40
hwmon_chip_register_tz,
41
hwmon_chip_update_interval,
42
hwmon_chip_alarms,
43
hwmon_chip_samples,
44
hwmon_chip_curr_samples,
45
hwmon_chip_in_samples,
46
hwmon_chip_power_samples,
47
hwmon_chip_temp_samples,
48
hwmon_chip_beep_enable,
49
hwmon_chip_pec,
50
};
51
52
#define HWMON_C_TEMP_RESET_HISTORY BIT(hwmon_chip_temp_reset_history)
53
#define HWMON_C_IN_RESET_HISTORY BIT(hwmon_chip_in_reset_history)
54
#define HWMON_C_CURR_RESET_HISTORY BIT(hwmon_chip_curr_reset_history)
55
#define HWMON_C_POWER_RESET_HISTORY BIT(hwmon_chip_power_reset_history)
56
#define HWMON_C_REGISTER_TZ BIT(hwmon_chip_register_tz)
57
#define HWMON_C_UPDATE_INTERVAL BIT(hwmon_chip_update_interval)
58
#define HWMON_C_ALARMS BIT(hwmon_chip_alarms)
59
#define HWMON_C_SAMPLES BIT(hwmon_chip_samples)
60
#define HWMON_C_CURR_SAMPLES BIT(hwmon_chip_curr_samples)
61
#define HWMON_C_IN_SAMPLES BIT(hwmon_chip_in_samples)
62
#define HWMON_C_POWER_SAMPLES BIT(hwmon_chip_power_samples)
63
#define HWMON_C_TEMP_SAMPLES BIT(hwmon_chip_temp_samples)
64
#define HWMON_C_BEEP_ENABLE BIT(hwmon_chip_beep_enable)
65
#define HWMON_C_PEC BIT(hwmon_chip_pec)
66
67
enum hwmon_temp_attributes {
68
hwmon_temp_enable,
69
hwmon_temp_input,
70
hwmon_temp_type,
71
hwmon_temp_lcrit,
72
hwmon_temp_lcrit_hyst,
73
hwmon_temp_min,
74
hwmon_temp_min_hyst,
75
hwmon_temp_max,
76
hwmon_temp_max_hyst,
77
hwmon_temp_crit,
78
hwmon_temp_crit_hyst,
79
hwmon_temp_emergency,
80
hwmon_temp_emergency_hyst,
81
hwmon_temp_alarm,
82
hwmon_temp_lcrit_alarm,
83
hwmon_temp_min_alarm,
84
hwmon_temp_max_alarm,
85
hwmon_temp_crit_alarm,
86
hwmon_temp_emergency_alarm,
87
hwmon_temp_fault,
88
hwmon_temp_offset,
89
hwmon_temp_label,
90
hwmon_temp_lowest,
91
hwmon_temp_highest,
92
hwmon_temp_reset_history,
93
hwmon_temp_rated_min,
94
hwmon_temp_rated_max,
95
hwmon_temp_beep,
96
};
97
98
#define HWMON_T_ENABLE BIT(hwmon_temp_enable)
99
#define HWMON_T_INPUT BIT(hwmon_temp_input)
100
#define HWMON_T_TYPE BIT(hwmon_temp_type)
101
#define HWMON_T_LCRIT BIT(hwmon_temp_lcrit)
102
#define HWMON_T_LCRIT_HYST BIT(hwmon_temp_lcrit_hyst)
103
#define HWMON_T_MIN BIT(hwmon_temp_min)
104
#define HWMON_T_MIN_HYST BIT(hwmon_temp_min_hyst)
105
#define HWMON_T_MAX BIT(hwmon_temp_max)
106
#define HWMON_T_MAX_HYST BIT(hwmon_temp_max_hyst)
107
#define HWMON_T_CRIT BIT(hwmon_temp_crit)
108
#define HWMON_T_CRIT_HYST BIT(hwmon_temp_crit_hyst)
109
#define HWMON_T_EMERGENCY BIT(hwmon_temp_emergency)
110
#define HWMON_T_EMERGENCY_HYST BIT(hwmon_temp_emergency_hyst)
111
#define HWMON_T_ALARM BIT(hwmon_temp_alarm)
112
#define HWMON_T_MIN_ALARM BIT(hwmon_temp_min_alarm)
113
#define HWMON_T_MAX_ALARM BIT(hwmon_temp_max_alarm)
114
#define HWMON_T_CRIT_ALARM BIT(hwmon_temp_crit_alarm)
115
#define HWMON_T_LCRIT_ALARM BIT(hwmon_temp_lcrit_alarm)
116
#define HWMON_T_EMERGENCY_ALARM BIT(hwmon_temp_emergency_alarm)
117
#define HWMON_T_FAULT BIT(hwmon_temp_fault)
118
#define HWMON_T_OFFSET BIT(hwmon_temp_offset)
119
#define HWMON_T_LABEL BIT(hwmon_temp_label)
120
#define HWMON_T_LOWEST BIT(hwmon_temp_lowest)
121
#define HWMON_T_HIGHEST BIT(hwmon_temp_highest)
122
#define HWMON_T_RESET_HISTORY BIT(hwmon_temp_reset_history)
123
#define HWMON_T_RATED_MIN BIT(hwmon_temp_rated_min)
124
#define HWMON_T_RATED_MAX BIT(hwmon_temp_rated_max)
125
#define HWMON_T_BEEP BIT(hwmon_temp_beep)
126
127
enum hwmon_in_attributes {
128
hwmon_in_enable,
129
hwmon_in_input,
130
hwmon_in_min,
131
hwmon_in_max,
132
hwmon_in_lcrit,
133
hwmon_in_crit,
134
hwmon_in_average,
135
hwmon_in_lowest,
136
hwmon_in_highest,
137
hwmon_in_reset_history,
138
hwmon_in_label,
139
hwmon_in_alarm,
140
hwmon_in_min_alarm,
141
hwmon_in_max_alarm,
142
hwmon_in_lcrit_alarm,
143
hwmon_in_crit_alarm,
144
hwmon_in_rated_min,
145
hwmon_in_rated_max,
146
hwmon_in_beep,
147
hwmon_in_fault,
148
};
149
150
#define HWMON_I_ENABLE BIT(hwmon_in_enable)
151
#define HWMON_I_INPUT BIT(hwmon_in_input)
152
#define HWMON_I_MIN BIT(hwmon_in_min)
153
#define HWMON_I_MAX BIT(hwmon_in_max)
154
#define HWMON_I_LCRIT BIT(hwmon_in_lcrit)
155
#define HWMON_I_CRIT BIT(hwmon_in_crit)
156
#define HWMON_I_AVERAGE BIT(hwmon_in_average)
157
#define HWMON_I_LOWEST BIT(hwmon_in_lowest)
158
#define HWMON_I_HIGHEST BIT(hwmon_in_highest)
159
#define HWMON_I_RESET_HISTORY BIT(hwmon_in_reset_history)
160
#define HWMON_I_LABEL BIT(hwmon_in_label)
161
#define HWMON_I_ALARM BIT(hwmon_in_alarm)
162
#define HWMON_I_MIN_ALARM BIT(hwmon_in_min_alarm)
163
#define HWMON_I_MAX_ALARM BIT(hwmon_in_max_alarm)
164
#define HWMON_I_LCRIT_ALARM BIT(hwmon_in_lcrit_alarm)
165
#define HWMON_I_CRIT_ALARM BIT(hwmon_in_crit_alarm)
166
#define HWMON_I_RATED_MIN BIT(hwmon_in_rated_min)
167
#define HWMON_I_RATED_MAX BIT(hwmon_in_rated_max)
168
#define HWMON_I_BEEP BIT(hwmon_in_beep)
169
#define HWMON_I_FAULT BIT(hwmon_in_fault)
170
171
enum hwmon_curr_attributes {
172
hwmon_curr_enable,
173
hwmon_curr_input,
174
hwmon_curr_min,
175
hwmon_curr_max,
176
hwmon_curr_lcrit,
177
hwmon_curr_crit,
178
hwmon_curr_average,
179
hwmon_curr_lowest,
180
hwmon_curr_highest,
181
hwmon_curr_reset_history,
182
hwmon_curr_label,
183
hwmon_curr_alarm,
184
hwmon_curr_min_alarm,
185
hwmon_curr_max_alarm,
186
hwmon_curr_lcrit_alarm,
187
hwmon_curr_crit_alarm,
188
hwmon_curr_rated_min,
189
hwmon_curr_rated_max,
190
hwmon_curr_beep,
191
};
192
193
#define HWMON_C_ENABLE BIT(hwmon_curr_enable)
194
#define HWMON_C_INPUT BIT(hwmon_curr_input)
195
#define HWMON_C_MIN BIT(hwmon_curr_min)
196
#define HWMON_C_MAX BIT(hwmon_curr_max)
197
#define HWMON_C_LCRIT BIT(hwmon_curr_lcrit)
198
#define HWMON_C_CRIT BIT(hwmon_curr_crit)
199
#define HWMON_C_AVERAGE BIT(hwmon_curr_average)
200
#define HWMON_C_LOWEST BIT(hwmon_curr_lowest)
201
#define HWMON_C_HIGHEST BIT(hwmon_curr_highest)
202
#define HWMON_C_RESET_HISTORY BIT(hwmon_curr_reset_history)
203
#define HWMON_C_LABEL BIT(hwmon_curr_label)
204
#define HWMON_C_ALARM BIT(hwmon_curr_alarm)
205
#define HWMON_C_MIN_ALARM BIT(hwmon_curr_min_alarm)
206
#define HWMON_C_MAX_ALARM BIT(hwmon_curr_max_alarm)
207
#define HWMON_C_LCRIT_ALARM BIT(hwmon_curr_lcrit_alarm)
208
#define HWMON_C_CRIT_ALARM BIT(hwmon_curr_crit_alarm)
209
#define HWMON_C_RATED_MIN BIT(hwmon_curr_rated_min)
210
#define HWMON_C_RATED_MAX BIT(hwmon_curr_rated_max)
211
#define HWMON_C_BEEP BIT(hwmon_curr_beep)
212
213
enum hwmon_power_attributes {
214
hwmon_power_enable,
215
hwmon_power_average,
216
hwmon_power_average_interval,
217
hwmon_power_average_interval_max,
218
hwmon_power_average_interval_min,
219
hwmon_power_average_highest,
220
hwmon_power_average_lowest,
221
hwmon_power_average_max,
222
hwmon_power_average_min,
223
hwmon_power_input,
224
hwmon_power_input_highest,
225
hwmon_power_input_lowest,
226
hwmon_power_reset_history,
227
hwmon_power_accuracy,
228
hwmon_power_cap,
229
hwmon_power_cap_hyst,
230
hwmon_power_cap_max,
231
hwmon_power_cap_min,
232
hwmon_power_min,
233
hwmon_power_max,
234
hwmon_power_crit,
235
hwmon_power_lcrit,
236
hwmon_power_label,
237
hwmon_power_alarm,
238
hwmon_power_cap_alarm,
239
hwmon_power_min_alarm,
240
hwmon_power_max_alarm,
241
hwmon_power_lcrit_alarm,
242
hwmon_power_crit_alarm,
243
hwmon_power_rated_min,
244
hwmon_power_rated_max,
245
};
246
247
#define HWMON_P_ENABLE BIT(hwmon_power_enable)
248
#define HWMON_P_AVERAGE BIT(hwmon_power_average)
249
#define HWMON_P_AVERAGE_INTERVAL BIT(hwmon_power_average_interval)
250
#define HWMON_P_AVERAGE_INTERVAL_MAX BIT(hwmon_power_average_interval_max)
251
#define HWMON_P_AVERAGE_INTERVAL_MIN BIT(hwmon_power_average_interval_min)
252
#define HWMON_P_AVERAGE_HIGHEST BIT(hwmon_power_average_highest)
253
#define HWMON_P_AVERAGE_LOWEST BIT(hwmon_power_average_lowest)
254
#define HWMON_P_AVERAGE_MAX BIT(hwmon_power_average_max)
255
#define HWMON_P_AVERAGE_MIN BIT(hwmon_power_average_min)
256
#define HWMON_P_INPUT BIT(hwmon_power_input)
257
#define HWMON_P_INPUT_HIGHEST BIT(hwmon_power_input_highest)
258
#define HWMON_P_INPUT_LOWEST BIT(hwmon_power_input_lowest)
259
#define HWMON_P_RESET_HISTORY BIT(hwmon_power_reset_history)
260
#define HWMON_P_ACCURACY BIT(hwmon_power_accuracy)
261
#define HWMON_P_CAP BIT(hwmon_power_cap)
262
#define HWMON_P_CAP_HYST BIT(hwmon_power_cap_hyst)
263
#define HWMON_P_CAP_MAX BIT(hwmon_power_cap_max)
264
#define HWMON_P_CAP_MIN BIT(hwmon_power_cap_min)
265
#define HWMON_P_MIN BIT(hwmon_power_min)
266
#define HWMON_P_MAX BIT(hwmon_power_max)
267
#define HWMON_P_LCRIT BIT(hwmon_power_lcrit)
268
#define HWMON_P_CRIT BIT(hwmon_power_crit)
269
#define HWMON_P_LABEL BIT(hwmon_power_label)
270
#define HWMON_P_ALARM BIT(hwmon_power_alarm)
271
#define HWMON_P_CAP_ALARM BIT(hwmon_power_cap_alarm)
272
#define HWMON_P_MIN_ALARM BIT(hwmon_power_min_alarm)
273
#define HWMON_P_MAX_ALARM BIT(hwmon_power_max_alarm)
274
#define HWMON_P_LCRIT_ALARM BIT(hwmon_power_lcrit_alarm)
275
#define HWMON_P_CRIT_ALARM BIT(hwmon_power_crit_alarm)
276
#define HWMON_P_RATED_MIN BIT(hwmon_power_rated_min)
277
#define HWMON_P_RATED_MAX BIT(hwmon_power_rated_max)
278
279
enum hwmon_energy_attributes {
280
hwmon_energy_enable,
281
hwmon_energy_input,
282
hwmon_energy_label,
283
};
284
285
#define HWMON_E_ENABLE BIT(hwmon_energy_enable)
286
#define HWMON_E_INPUT BIT(hwmon_energy_input)
287
#define HWMON_E_LABEL BIT(hwmon_energy_label)
288
289
enum hwmon_humidity_attributes {
290
hwmon_humidity_enable,
291
hwmon_humidity_input,
292
hwmon_humidity_label,
293
hwmon_humidity_min,
294
hwmon_humidity_min_hyst,
295
hwmon_humidity_max,
296
hwmon_humidity_max_hyst,
297
hwmon_humidity_alarm,
298
hwmon_humidity_fault,
299
hwmon_humidity_rated_min,
300
hwmon_humidity_rated_max,
301
hwmon_humidity_min_alarm,
302
hwmon_humidity_max_alarm,
303
};
304
305
#define HWMON_H_ENABLE BIT(hwmon_humidity_enable)
306
#define HWMON_H_INPUT BIT(hwmon_humidity_input)
307
#define HWMON_H_LABEL BIT(hwmon_humidity_label)
308
#define HWMON_H_MIN BIT(hwmon_humidity_min)
309
#define HWMON_H_MIN_HYST BIT(hwmon_humidity_min_hyst)
310
#define HWMON_H_MAX BIT(hwmon_humidity_max)
311
#define HWMON_H_MAX_HYST BIT(hwmon_humidity_max_hyst)
312
#define HWMON_H_ALARM BIT(hwmon_humidity_alarm)
313
#define HWMON_H_FAULT BIT(hwmon_humidity_fault)
314
#define HWMON_H_RATED_MIN BIT(hwmon_humidity_rated_min)
315
#define HWMON_H_RATED_MAX BIT(hwmon_humidity_rated_max)
316
#define HWMON_H_MIN_ALARM BIT(hwmon_humidity_min_alarm)
317
#define HWMON_H_MAX_ALARM BIT(hwmon_humidity_max_alarm)
318
319
enum hwmon_fan_attributes {
320
hwmon_fan_enable,
321
hwmon_fan_input,
322
hwmon_fan_label,
323
hwmon_fan_min,
324
hwmon_fan_max,
325
hwmon_fan_div,
326
hwmon_fan_pulses,
327
hwmon_fan_target,
328
hwmon_fan_alarm,
329
hwmon_fan_min_alarm,
330
hwmon_fan_max_alarm,
331
hwmon_fan_fault,
332
hwmon_fan_beep,
333
};
334
335
#define HWMON_F_ENABLE BIT(hwmon_fan_enable)
336
#define HWMON_F_INPUT BIT(hwmon_fan_input)
337
#define HWMON_F_LABEL BIT(hwmon_fan_label)
338
#define HWMON_F_MIN BIT(hwmon_fan_min)
339
#define HWMON_F_MAX BIT(hwmon_fan_max)
340
#define HWMON_F_DIV BIT(hwmon_fan_div)
341
#define HWMON_F_PULSES BIT(hwmon_fan_pulses)
342
#define HWMON_F_TARGET BIT(hwmon_fan_target)
343
#define HWMON_F_ALARM BIT(hwmon_fan_alarm)
344
#define HWMON_F_MIN_ALARM BIT(hwmon_fan_min_alarm)
345
#define HWMON_F_MAX_ALARM BIT(hwmon_fan_max_alarm)
346
#define HWMON_F_FAULT BIT(hwmon_fan_fault)
347
#define HWMON_F_BEEP BIT(hwmon_fan_beep)
348
349
enum hwmon_pwm_attributes {
350
hwmon_pwm_input,
351
hwmon_pwm_enable,
352
hwmon_pwm_mode,
353
hwmon_pwm_freq,
354
hwmon_pwm_auto_channels_temp,
355
};
356
357
#define HWMON_PWM_INPUT BIT(hwmon_pwm_input)
358
#define HWMON_PWM_ENABLE BIT(hwmon_pwm_enable)
359
#define HWMON_PWM_MODE BIT(hwmon_pwm_mode)
360
#define HWMON_PWM_FREQ BIT(hwmon_pwm_freq)
361
#define HWMON_PWM_AUTO_CHANNELS_TEMP BIT(hwmon_pwm_auto_channels_temp)
362
363
enum hwmon_intrusion_attributes {
364
hwmon_intrusion_alarm,
365
hwmon_intrusion_beep,
366
};
367
#define HWMON_INTRUSION_ALARM BIT(hwmon_intrusion_alarm)
368
#define HWMON_INTRUSION_BEEP BIT(hwmon_intrusion_beep)
369
370
/**
371
* struct hwmon_ops - hwmon device operations
372
* @visible: Static visibility. If non-zero, 'is_visible' is ignored.
373
* @is_visible: Callback to return attribute visibility. Mandatory unless
374
* 'visible' is non-zero.
375
* Parameters are:
376
* @const void *drvdata:
377
* Pointer to driver-private data structure passed
378
* as argument to hwmon_device_register_with_info().
379
* @type: Sensor type
380
* @attr: Sensor attribute
381
* @channel:
382
* Channel number
383
* The function returns the file permissions.
384
* If the return value is 0, no attribute will be created.
385
* @read: Read callback for data attributes. Mandatory if readable
386
* data attributes are present.
387
* Parameters are:
388
* @dev: Pointer to hardware monitoring device
389
* @type: Sensor type
390
* @attr: Sensor attribute
391
* @channel:
392
* Channel number
393
* @val: Pointer to returned value
394
* The function returns 0 on success or a negative error number.
395
* @read_string:
396
* Read callback for string attributes. Mandatory if string
397
* attributes are present.
398
* Parameters are:
399
* @dev: Pointer to hardware monitoring device
400
* @type: Sensor type
401
* @attr: Sensor attribute
402
* @channel:
403
* Channel number
404
* @str: Pointer to returned string
405
* The function returns 0 on success or a negative error number.
406
* @write: Write callback for data attributes. Mandatory if writeable
407
* data attributes are present.
408
* Parameters are:
409
* @dev: Pointer to hardware monitoring device
410
* @type: Sensor type
411
* @attr: Sensor attribute
412
* @channel:
413
* Channel number
414
* @val: Value to write
415
* The function returns 0 on success or a negative error number.
416
*/
417
struct hwmon_ops {
418
umode_t visible;
419
umode_t (*is_visible)(const void *drvdata, enum hwmon_sensor_types type,
420
u32 attr, int channel);
421
int (*read)(struct device *dev, enum hwmon_sensor_types type,
422
u32 attr, int channel, long *val);
423
int (*read_string)(struct device *dev, enum hwmon_sensor_types type,
424
u32 attr, int channel, const char **str);
425
int (*write)(struct device *dev, enum hwmon_sensor_types type,
426
u32 attr, int channel, long val);
427
};
428
429
/**
430
* struct hwmon_channel_info - Channel information
431
* @type: Channel type.
432
* @config: Pointer to NULL-terminated list of channel parameters.
433
* Use for per-channel attributes.
434
*/
435
struct hwmon_channel_info {
436
enum hwmon_sensor_types type;
437
const u32 *config;
438
};
439
440
#define HWMON_CHANNEL_INFO(stype, ...) \
441
(&(const struct hwmon_channel_info) { \
442
.type = hwmon_##stype, \
443
.config = (const u32 []) { \
444
__VA_ARGS__, 0 \
445
} \
446
})
447
448
/**
449
* struct hwmon_chip_info - Chip configuration
450
* @ops: Pointer to hwmon operations.
451
* @info: Null-terminated list of channel information.
452
*/
453
struct hwmon_chip_info {
454
const struct hwmon_ops *ops;
455
const struct hwmon_channel_info * const *info;
456
};
457
458
/* hwmon_device_register() is deprecated */
459
struct device *hwmon_device_register(struct device *dev);
460
461
/*
462
* hwmon_device_register_with_groups() and
463
* devm_hwmon_device_register_with_groups() are deprecated.
464
*/
465
struct device *
466
hwmon_device_register_with_groups(struct device *dev, const char *name,
467
void *drvdata,
468
const struct attribute_group **groups);
469
struct device *
470
devm_hwmon_device_register_with_groups(struct device *dev, const char *name,
471
void *drvdata,
472
const struct attribute_group **groups);
473
struct device *
474
hwmon_device_register_with_info(struct device *dev,
475
const char *name, void *drvdata,
476
const struct hwmon_chip_info *info,
477
const struct attribute_group **extra_groups);
478
struct device *
479
hwmon_device_register_for_thermal(struct device *dev, const char *name,
480
void *drvdata);
481
struct device *
482
devm_hwmon_device_register_with_info(struct device *dev,
483
const char *name, void *drvdata,
484
const struct hwmon_chip_info *info,
485
const struct attribute_group **extra_groups);
486
487
void hwmon_device_unregister(struct device *dev);
488
489
int hwmon_notify_event(struct device *dev, enum hwmon_sensor_types type,
490
u32 attr, int channel);
491
492
char *hwmon_sanitize_name(const char *name);
493
char *devm_hwmon_sanitize_name(struct device *dev, const char *name);
494
495
void hwmon_lock(struct device *dev);
496
void hwmon_unlock(struct device *dev);
497
498
/**
499
* hwmon_is_bad_char - Is the char invalid in a hwmon name
500
* @ch: the char to be considered
501
*
502
* hwmon_is_bad_char() can be used to determine if the given character
503
* may not be used in a hwmon name.
504
*
505
* Returns true if the char is invalid, false otherwise.
506
*/
507
static inline bool hwmon_is_bad_char(const char ch)
508
{
509
switch (ch) {
510
case '-':
511
case '*':
512
case ' ':
513
case '\t':
514
case '\n':
515
return true;
516
default:
517
return false;
518
}
519
}
520
521
#endif
522
523