|
|
|
|
@@ -1345,19 +1345,19 @@ static int input_print_modalias_bits(char *buf, int size,
|
|
|
|
|
char name, unsigned long *bm,
|
|
|
|
|
unsigned int min_bit, unsigned int max_bit)
|
|
|
|
|
{
|
|
|
|
|
int len = 0, i;
|
|
|
|
|
int bit = min_bit;
|
|
|
|
|
int len = 0;
|
|
|
|
|
|
|
|
|
|
len += snprintf(buf, max(size, 0), "%c", name);
|
|
|
|
|
for (i = min_bit; i < max_bit; i++)
|
|
|
|
|
if (bm[BIT_WORD(i)] & BIT_MASK(i))
|
|
|
|
|
len += snprintf(buf + len, max(size - len, 0), "%X,", i);
|
|
|
|
|
for_each_set_bit_from(bit, bm, max_bit)
|
|
|
|
|
len += snprintf(buf + len, max(size - len, 0), "%X,", bit);
|
|
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int input_print_modalias(char *buf, int size, struct input_dev *id,
|
|
|
|
|
int add_cr)
|
|
|
|
|
static int input_print_modalias_parts(char *buf, int size, int full_len,
|
|
|
|
|
struct input_dev *id)
|
|
|
|
|
{
|
|
|
|
|
int len;
|
|
|
|
|
int len, klen, remainder, space;
|
|
|
|
|
|
|
|
|
|
len = snprintf(buf, max(size, 0),
|
|
|
|
|
"input:b%04Xv%04Xp%04Xe%04X-",
|
|
|
|
|
@@ -1366,8 +1366,49 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id,
|
|
|
|
|
|
|
|
|
|
len += input_print_modalias_bits(buf + len, size - len,
|
|
|
|
|
'e', id->evbit, 0, EV_MAX);
|
|
|
|
|
len += input_print_modalias_bits(buf + len, size - len,
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Calculate the remaining space in the buffer making sure we
|
|
|
|
|
* have place for the terminating 0.
|
|
|
|
|
*/
|
|
|
|
|
space = max(size - (len + 1), 0);
|
|
|
|
|
|
|
|
|
|
klen = input_print_modalias_bits(buf + len, size - len,
|
|
|
|
|
'k', id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
|
|
|
|
|
len += klen;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If we have more data than we can fit in the buffer, check
|
|
|
|
|
* if we can trim key data to fit in the rest. We will indicate
|
|
|
|
|
* that key data is incomplete by adding "+" sign at the end, like
|
|
|
|
|
* this: * "k1,2,3,45,+,".
|
|
|
|
|
*
|
|
|
|
|
* Note that we shortest key info (if present) is "k+," so we
|
|
|
|
|
* can only try to trim if key data is longer than that.
|
|
|
|
|
*/
|
|
|
|
|
if (full_len && size < full_len + 1 && klen > 3) {
|
|
|
|
|
remainder = full_len - len;
|
|
|
|
|
/*
|
|
|
|
|
* We can only trim if we have space for the remainder
|
|
|
|
|
* and also for at least "k+," which is 3 more characters.
|
|
|
|
|
*/
|
|
|
|
|
if (remainder <= space - 3) {
|
|
|
|
|
int i;
|
|
|
|
|
/*
|
|
|
|
|
* We are guaranteed to have 'k' in the buffer, so
|
|
|
|
|
* we need at least 3 additional bytes for storing
|
|
|
|
|
* "+," in addition to the remainder.
|
|
|
|
|
*/
|
|
|
|
|
for (i = size - 1 - remainder - 3; i >= 0; i--) {
|
|
|
|
|
if (buf[i] == 'k' || buf[i] == ',') {
|
|
|
|
|
strcpy(buf + i + 1, "+,");
|
|
|
|
|
len = i + 3; /* Not counting '\0' */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len += input_print_modalias_bits(buf + len, size - len,
|
|
|
|
|
'r', id->relbit, 0, REL_MAX);
|
|
|
|
|
len += input_print_modalias_bits(buf + len, size - len,
|
|
|
|
|
@@ -1383,12 +1424,25 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id,
|
|
|
|
|
len += input_print_modalias_bits(buf + len, size - len,
|
|
|
|
|
'w', id->swbit, 0, SW_MAX);
|
|
|
|
|
|
|
|
|
|
if (add_cr)
|
|
|
|
|
len += snprintf(buf + len, max(size - len, 0), "\n");
|
|
|
|
|
|
|
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int input_print_modalias(char *buf, int size, struct input_dev *id)
|
|
|
|
|
{
|
|
|
|
|
int full_len;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Printing is done in 2 passes: first one figures out total length
|
|
|
|
|
* needed for the modalias string, second one will try to trim key
|
|
|
|
|
* data in case when buffer is too small for the entire modalias.
|
|
|
|
|
* If the buffer is too small regardless, it will fill as much as it
|
|
|
|
|
* can (without trimming key data) into the buffer and leave it to
|
|
|
|
|
* the caller to figure out what to do with the result.
|
|
|
|
|
*/
|
|
|
|
|
full_len = input_print_modalias_parts(NULL, 0, 0, id);
|
|
|
|
|
return input_print_modalias_parts(buf, size, full_len, id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static ssize_t input_dev_show_modalias(struct device *dev,
|
|
|
|
|
struct device_attribute *attr,
|
|
|
|
|
char *buf)
|
|
|
|
|
@@ -1396,7 +1450,9 @@ static ssize_t input_dev_show_modalias(struct device *dev,
|
|
|
|
|
struct input_dev *id = to_input_dev(dev);
|
|
|
|
|
ssize_t len;
|
|
|
|
|
|
|
|
|
|
len = input_print_modalias(buf, PAGE_SIZE, id, 1);
|
|
|
|
|
len = input_print_modalias(buf, PAGE_SIZE, id);
|
|
|
|
|
if (len < PAGE_SIZE - 2)
|
|
|
|
|
len += snprintf(buf + len, PAGE_SIZE - len, "\n");
|
|
|
|
|
|
|
|
|
|
return min_t(int, len, PAGE_SIZE);
|
|
|
|
|
}
|
|
|
|
|
@@ -1569,6 +1625,23 @@ static int input_add_uevent_bm_var(struct kobj_uevent_env *env,
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This is a pretty gross hack. When building uevent data the driver core
|
|
|
|
|
* may try adding more environment variables to kobj_uevent_env without
|
|
|
|
|
* telling us, so we have no idea how much of the buffer we can use to
|
|
|
|
|
* avoid overflows/-ENOMEM elsewhere. To work around this let's artificially
|
|
|
|
|
* reduce amount of memory we will use for the modalias environment variable.
|
|
|
|
|
*
|
|
|
|
|
* The potential additions are:
|
|
|
|
|
*
|
|
|
|
|
* SEQNUM=18446744073709551615 - (%llu - 28 bytes)
|
|
|
|
|
* HOME=/ (6 bytes)
|
|
|
|
|
* PATH=/sbin:/bin:/usr/sbin:/usr/bin (34 bytes)
|
|
|
|
|
*
|
|
|
|
|
* 68 bytes total. Allow extra buffer - 96 bytes
|
|
|
|
|
*/
|
|
|
|
|
#define UEVENT_ENV_EXTRA_LEN 96
|
|
|
|
|
|
|
|
|
|
static int input_add_uevent_modalias_var(struct kobj_uevent_env *env,
|
|
|
|
|
struct input_dev *dev)
|
|
|
|
|
{
|
|
|
|
|
@@ -1578,9 +1651,11 @@ static int input_add_uevent_modalias_var(struct kobj_uevent_env *env,
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
|
|
len = input_print_modalias(&env->buf[env->buflen - 1],
|
|
|
|
|
sizeof(env->buf) - env->buflen,
|
|
|
|
|
dev, 0);
|
|
|
|
|
if (len >= (sizeof(env->buf) - env->buflen))
|
|
|
|
|
(int)sizeof(env->buf) - env->buflen -
|
|
|
|
|
UEVENT_ENV_EXTRA_LEN,
|
|
|
|
|
dev);
|
|
|
|
|
if (len >= ((int)sizeof(env->buf) - env->buflen -
|
|
|
|
|
UEVENT_ENV_EXTRA_LEN))
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
|
|
env->buflen += len;
|
|
|
|
|
|