From dbf7ffa75b208bcf8f1a7e4f633327f0515bae36 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Tue, 9 Nov 2010 15:15:20 +0100 Subject: Version two of refactored driver Signed-off-by: Henrik Rydberg --- usr/src/dkms_source_tree/applesmc.c | 252 +++++++++++++++++------------------- 1 file changed, 119 insertions(+), 133 deletions(-) (limited to 'usr') diff --git a/usr/src/dkms_source_tree/applesmc.c b/usr/src/dkms_source_tree/applesmc.c index 2eb78e3..01071e5 100644 --- a/usr/src/dkms_source_tree/applesmc.c +++ b/usr/src/dkms_source_tree/applesmc.c @@ -91,7 +91,7 @@ #define FAN_ID_FMT "F%dID" /* r-o char[16] */ /* List of keys used to read/write fan speeds */ -static const char *fan_speed_fmt[] = { +static const char *const fan_speed_fmt[] = { "F%dAc", /* actual speed */ "F%dMn", /* minimum speed (rw) */ "F%dMx", /* maximum speed */ @@ -133,7 +133,8 @@ struct applesmc_entry { char key[5]; /* four-letter key code */ u8 valid; /* set when entry is successfully read once */ u8 len; /* bounded by APPLESMC_MAX_DATA_LENGTH */ - char type[5]; /* four-letter type code (padded) */ + char type[5]; /* four-letter type code */ + u8 flags; /* 0x10: func; 0x40: write; 0x80: read */ }; /* Register lookup and registers common to all SMCs */ @@ -144,12 +145,11 @@ static struct applesmc_registers { unsigned int temp_count; /* number of temperature registers */ unsigned int temp_begin; /* temperature lower index bound */ unsigned int temp_end; /* temperature upper index bound */ + int num_light_sensors; /* number of light sensors */ bool has_accelerometer; /* has motion sensor */ - bool has_left_light; /* has left light sensor */ - bool has_right_light; /* has right light sensor */ - bool has_key_light; /* has keyboard backlight */ + bool has_key_backlight; /* has keyboard backlight */ bool init_complete; /* true when fully initialized */ - struct applesmc_entry *entry; /* key entries */ + struct applesmc_entry *cache; /* cached key entries */ } smcreg; static const int debug; @@ -167,7 +167,6 @@ static struct input_polled_dev *applesmc_idev; */ static unsigned int key_at_index; - static struct workqueue_struct *applesmc_led_wq; /* @@ -311,48 +310,52 @@ static int applesmc_write_entry(const struct applesmc_entry *entry, return ret; } -static int applesmc_get_entry_by_index(int index, struct applesmc_entry *entry) +static const struct applesmc_entry *applesmc_get_entry_by_index(int index) { - struct applesmc_entry *cache = &smcreg.entry[index]; + struct applesmc_entry *cache = &smcreg.cache[index]; + u8 key[4], info[6]; __be32 be; - int ret; + int ret = 0; - if (cache->valid) { - memcpy(entry, cache, sizeof(*entry)); - return 0; - } + if (cache->valid) + return cache; mutex_lock(&smcreg.mutex); + if (cache->valid) + goto out; be = cpu_to_be32(index); - ret = read_smc(APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, cache->key, 4); + ret = read_smc(APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4); if (ret) goto out; - ret = read_smc(APPLESMC_GET_KEY_TYPE_CMD, cache->key, &cache->len, 6); + ret = read_smc(APPLESMC_GET_KEY_TYPE_CMD, key, info, 6); if (ret) goto out; - cache->type[4] = 0; + memcpy(cache->key, key, 4); + cache->len = info[0]; + memcpy(cache->type, &info[1], 4); + cache->flags = info[5]; cache->valid = 1; - memcpy(entry, cache, sizeof(*entry)); out: mutex_unlock(&smcreg.mutex); - return ret; + if (ret) + return ERR_PTR(ret); + return cache; } static int applesmc_get_lower_bound(unsigned int *lo, const char *key) { int begin = 0, end = smcreg.key_count; - struct applesmc_entry entry; - int ret; + const struct applesmc_entry *entry; while (begin != end) { int middle = begin + (end - begin) / 2; - ret = applesmc_get_entry_by_index(middle, &entry); - if (ret) - return ret; - if (strcmp(entry.key, key) < 0) + entry = applesmc_get_entry_by_index(middle); + if (IS_ERR(entry)) + return PTR_ERR(entry); + if (strcmp(entry->key, key) < 0) begin = middle + 1; else end = middle; @@ -365,15 +368,14 @@ static int applesmc_get_lower_bound(unsigned int *lo, const char *key) static int applesmc_get_upper_bound(unsigned int *hi, const char *key) { int begin = 0, end = smcreg.key_count; - struct applesmc_entry entry; - int ret; + const struct applesmc_entry *entry; while (begin != end) { int middle = begin + (end - begin) / 2; - ret = applesmc_get_entry_by_index(middle, &entry); - if (ret) - return ret; - if (strcmp(key, entry.key) < 0) + entry = applesmc_get_entry_by_index(middle); + if (IS_ERR(entry)) + return PTR_ERR(entry); + if (strcmp(key, entry->key) < 0) end = middle; else begin = middle + 1; @@ -383,58 +385,54 @@ static int applesmc_get_upper_bound(unsigned int *hi, const char *key) return 0; } -static int applesmc_get_entry_by_key(const char *key, - struct applesmc_entry *entry) +static const struct applesmc_entry *applesmc_get_entry_by_key(const char *key) { int begin, end; int ret; ret = applesmc_get_lower_bound(&begin, key); if (ret) - return ret; + return ERR_PTR(ret); ret = applesmc_get_upper_bound(&end, key); if (ret) - return ret; + return ERR_PTR(ret); if (end - begin != 1) - return -EINVAL; + return ERR_PTR(-EINVAL); - return applesmc_get_entry_by_index(begin, entry); + return applesmc_get_entry_by_index(begin); } static int applesmc_read_key(const char *key, u8 *buffer, u8 len) { - struct applesmc_entry entry; - int ret; + const struct applesmc_entry *entry; - ret = applesmc_get_entry_by_key(key, &entry); - if (ret) - return ret; + entry = applesmc_get_entry_by_key(key); + if (IS_ERR(entry)) + return PTR_ERR(entry); - return applesmc_read_entry(&entry, buffer, len); + return applesmc_read_entry(entry, buffer, len); } static int applesmc_write_key(const char *key, const u8 *buffer, u8 len) { - struct applesmc_entry entry; - int ret; + const struct applesmc_entry *entry; - ret = applesmc_get_entry_by_key(key, &entry); - if (ret) - return ret; + entry = applesmc_get_entry_by_key(key); + if (IS_ERR(entry)) + return PTR_ERR(entry); - return applesmc_write_entry(&entry, buffer, len); + return applesmc_write_entry(entry, buffer, len); } static int applesmc_has_key(const char *key, bool *value) { - struct applesmc_entry entry; - int ret; + const struct applesmc_entry *entry; - ret = applesmc_get_entry_by_key(key, &entry); - if (ret && ret != -EINVAL) - return ret; + entry = applesmc_get_entry_by_key(key); + if (IS_ERR(entry) && PTR_ERR(entry) != -EINVAL) + return PTR_ERR(entry); - *value = ret == 0 && entry.len; + *value = !IS_ERR(entry); return 0; } @@ -466,23 +464,20 @@ static int applesmc_read_motion_sensor(int index, s16* value) } /* - * applesmc_device_init - initialize the accelerometer. Returns zero on success - * and negative error code on failure. Can sleep. + * applesmc_device_init - initialize the accelerometer. Can sleep. */ -static int applesmc_device_init(void) +static void applesmc_device_init(void) { - int total, ret = -ENXIO; + int total; u8 buffer[2]; if (!smcreg.has_accelerometer) - return 0; + return; for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) { if (!applesmc_read_key(MOTION_SENSOR_KEY, buffer, 2) && - (buffer[0] != 0x00 || buffer[1] != 0x00)) { - ret = 0; - goto out; - } + (buffer[0] != 0x00 || buffer[1] != 0x00)) + return; buffer[0] = 0xe0; buffer[1] = 0x00; applesmc_write_key(MOTION_SENSOR_KEY, buffer, 2); @@ -490,9 +485,6 @@ static int applesmc_device_init(void) } pr_warn("failed to init the device\n"); - -out: - return ret; } /* @@ -501,7 +493,8 @@ out: static int applesmc_init_smcreg_try(void) { struct applesmc_registers *s = &smcreg; - u8 tmp[4]; + bool left_light_sensor, right_light_sensor; + u8 tmp[1]; int ret; if (s->init_complete) @@ -513,9 +506,9 @@ static int applesmc_init_smcreg_try(void) if (ret) return ret; - if (!s->entry) - s->entry = kcalloc(s->key_count, sizeof(*s->entry), GFP_KERNEL); - if (!s->entry) + if (!s->cache) + s->cache = kcalloc(s->key_count, sizeof(*s->cache), GFP_KERNEL); + if (!s->cache) return -ENOMEM; ret = applesmc_read_key(FANS_COUNT, tmp, 1); @@ -531,26 +524,27 @@ static int applesmc_init_smcreg_try(void) return ret; s->temp_count = s->temp_end - s->temp_begin; - ret = applesmc_has_key(LIGHT_SENSOR_LEFT_KEY, &s->has_left_light); + ret = applesmc_has_key(LIGHT_SENSOR_LEFT_KEY, &left_light_sensor); if (ret) return ret; - ret = applesmc_has_key(LIGHT_SENSOR_RIGHT_KEY, &s->has_right_light); + ret = applesmc_has_key(LIGHT_SENSOR_RIGHT_KEY, &right_light_sensor); if (ret) return ret; ret = applesmc_has_key(MOTION_SENSOR_KEY, &s->has_accelerometer); if (ret) return ret; - ret = applesmc_has_key(BACKLIGHT_KEY, &s->has_key_light); + ret = applesmc_has_key(BACKLIGHT_KEY, &s->has_key_backlight); if (ret) return ret; + s->num_light_sensors = left_light_sensor + right_light_sensor; s->init_complete = true; - pr_info("key=%d fan=%d temp=%d acc=%d, light=%d, keyb=%d\n", + pr_info("key=%d fan=%d temp=%d acc=%d lux=%d kbd=%d\n", s->key_count, s->fan_count, s->temp_count, s->has_accelerometer, - s->has_left_light + s->has_right_light, - s->has_key_light); + s->num_light_sensors, + s->has_key_backlight); return 0; } @@ -578,8 +572,8 @@ static int applesmc_init_smcreg(void) static void applesmc_destroy_smcreg(void) { - kfree(smcreg.entry); - smcreg.entry = NULL; + kfree(smcreg.cache); + memset(&smcreg, 0, sizeof(smcreg)); } /* Device model stuff */ @@ -599,7 +593,7 @@ static int applesmc_probe(struct platform_device *dev) /* Synchronize device with memorized backlight state */ static int applesmc_pm_resume(struct device *dev) { - if (smcreg.has_key_light) + if (smcreg.has_key_backlight) applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2); return 0; } @@ -686,17 +680,19 @@ out: static ssize_t applesmc_light_show(struct device *dev, struct device_attribute *attr, char *sysfsbuf) { - struct applesmc_entry entry; + const struct applesmc_entry *entry; static int data_length; int ret; u8 left = 0, right = 0; u8 buffer[10]; if (!data_length) { - ret = applesmc_get_entry_by_key(LIGHT_SENSOR_LEFT_KEY, &entry); - if (ret) - goto out; - data_length = clamp_val(entry.len, 0, 10); + entry = applesmc_get_entry_by_key(LIGHT_SENSOR_LEFT_KEY); + if (IS_ERR(entry)) + return PTR_ERR(entry); + if (entry->len > 10) + return -ENXIO; + data_length = entry->len; pr_info("light sensor data length set to %d\n", data_length); } @@ -724,14 +720,13 @@ static ssize_t applesmc_show_sensor_label(struct device *dev, struct device_attribute *devattr, char *sysfsbuf) { int index = smcreg.temp_begin + to_index(devattr); - struct applesmc_entry entry; - int ret; + const struct applesmc_entry *entry; - ret = applesmc_get_entry_by_index(index, &entry); - if (ret) - return ret; + entry = applesmc_get_entry_by_index(index); + if (IS_ERR(entry)) + return PTR_ERR(entry); - return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry.key); + return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->key); } /* Displays degree Celsius * 1000 */ @@ -739,26 +734,25 @@ static ssize_t applesmc_show_temperature(struct device *dev, struct device_attribute *devattr, char *sysfsbuf) { int index = smcreg.temp_begin + to_index(devattr); - struct applesmc_entry entry; + const struct applesmc_entry *entry; int ret; u8 buffer[2]; unsigned int temp; - ret = applesmc_get_entry_by_index(index, &entry); - if (ret) - return ret; - if (entry.len > 2) + entry = applesmc_get_entry_by_index(index); + if (IS_ERR(entry)) + return PTR_ERR(entry); + if (entry->len > 2) return -EINVAL; - ret = applesmc_read_entry(&entry, buffer, entry.len); + ret = applesmc_read_entry(entry, buffer, entry->len); if (ret) return ret; - if (entry.len == 2) { - temp = buffer[0]*1000; + if (entry->len == 2) { + temp = buffer[0] * 1000; temp += (buffer[1] >> 6) * 250; } else { - /* wild guess */ temp = buffer[0] * 4000; } @@ -929,56 +923,53 @@ static ssize_t applesmc_key_count_show(struct device *dev, static ssize_t applesmc_key_at_index_read_show(struct device *dev, struct device_attribute *attr, char *sysfsbuf) { - struct applesmc_entry entry; + const struct applesmc_entry *entry; int ret; - ret = applesmc_get_entry_by_index(key_at_index, &entry); - if (ret) - return ret; - ret = applesmc_read_entry(&entry, sysfsbuf, entry.len); + entry = applesmc_get_entry_by_index(key_at_index); + if (IS_ERR(entry)) + return PTR_ERR(entry); + ret = applesmc_read_entry(entry, sysfsbuf, entry->len); if (ret) return ret; - return entry.len; + return entry->len; } static ssize_t applesmc_key_at_index_data_length_show(struct device *dev, struct device_attribute *attr, char *sysfsbuf) { - struct applesmc_entry entry; - int ret; + const struct applesmc_entry *entry; - ret = applesmc_get_entry_by_index(key_at_index, &entry); - if (ret) - return ret; + entry = applesmc_get_entry_by_index(key_at_index); + if (IS_ERR(entry)) + return PTR_ERR(entry); - return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", entry.len); + return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", entry->len); } static ssize_t applesmc_key_at_index_type_show(struct device *dev, struct device_attribute *attr, char *sysfsbuf) { - struct applesmc_entry entry; - int ret; + const struct applesmc_entry *entry; - ret = applesmc_get_entry_by_index(key_at_index, &entry); - if (ret) - return ret; + entry = applesmc_get_entry_by_index(key_at_index); + if (IS_ERR(entry)) + return PTR_ERR(entry); - return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry.type); + return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->type); } static ssize_t applesmc_key_at_index_name_show(struct device *dev, struct device_attribute *attr, char *sysfsbuf) { - struct applesmc_entry entry; - int ret; + const struct applesmc_entry *entry; - ret = applesmc_get_entry_by_index(key_at_index, &entry); - if (ret) - return ret; + entry = applesmc_get_entry_by_index(key_at_index); + if (IS_ERR(entry)) + return PTR_ERR(entry); - return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry.key); + return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->key); } static ssize_t applesmc_key_at_index_show(struct device *dev, @@ -1163,21 +1154,21 @@ static void applesmc_release_accelerometer(void) static int applesmc_create_light_sensor(void) { - if (!smcreg.has_left_light) + if (!smcreg.num_light_sensors) return 0; return applesmc_create_nodes(light_sensor_group, 1); } static void applesmc_release_light_sensor(void) { - if (!smcreg.has_left_light) + if (!smcreg.num_light_sensors) return; applesmc_destroy_nodes(light_sensor_group); } static int applesmc_create_key_backlight(void) { - if (!smcreg.has_key_light) + if (!smcreg.has_key_backlight) return 0; applesmc_led_wq = create_singlethread_workqueue("applesmc-led"); if (!applesmc_led_wq) @@ -1187,7 +1178,7 @@ static int applesmc_create_key_backlight(void) static void applesmc_release_key_backlight(void) { - if (!smcreg.has_key_light) + if (!smcreg.has_key_backlight) return; led_classdev_unregister(&applesmc_backlight); destroy_workqueue(applesmc_led_wq); @@ -1195,7 +1186,6 @@ static void applesmc_release_key_backlight(void) static int applesmc_dmi_match(const struct dmi_system_id *id) { - pr_info("%s detected\n", id->ident); return 1; } @@ -1291,8 +1281,6 @@ static int __init applesmc_init(void) goto out_light_ledclass; } - pr_info("driver successfully loaded\n"); - return 0; out_light_ledclass: @@ -1333,8 +1321,6 @@ static void __exit applesmc_exit(void) platform_device_unregister(pdev); platform_driver_unregister(&applesmc_driver); release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS); - - pr_info("driver unloaded\n"); } module_init(applesmc_init); -- cgit v1.2.3