Contact:       Samuel Ortiz <sameo@linux.intel.com>
                linux-mei@linux.intel.com
 Description:   Stores the same MODALIAS value emitted by uevent
-               Format: mei:<mei device name>
+               Format: mei:<mei device name>:<device uuid>:
 
 #define to_mei_cl_driver(d) container_of(d, struct mei_cl_driver, driver)
 #define to_mei_cl_device(d) container_of(d, struct mei_cl_device, dev)
 
+static inline uuid_le uuid_le_cast(const __u8 uuid[16])
+{
+       return *(uuid_le *)uuid;
+}
+
 static int mei_cl_device_match(struct device *dev, struct device_driver *drv)
 {
        struct mei_cl_device *device = to_mei_cl_device(dev);
        struct mei_cl_driver *driver = to_mei_cl_driver(drv);
        const struct mei_cl_device_id *id;
+       const uuid_le *uuid;
+       const char *name;
 
        if (!device)
                return 0;
 
+       uuid = mei_me_cl_uuid(device->me_cl);
+       name = device->name;
+
        if (!driver || !driver->id_table)
                return 0;
 
        id = driver->id_table;
 
-       while (id->name[0]) {
-               if (!strncmp(dev_name(dev), id->name, sizeof(id->name)))
-                       return 1;
+       while (uuid_le_cmp(NULL_UUID_LE, uuid_le_cast(id->uuid))) {
+
+               if (!uuid_le_cmp(*uuid, uuid_le_cast(id->uuid))) {
+                       if (id->name[0]) {
+                               if (!strncmp(name, id->name, sizeof(id->name)))
+                                       return 1;
+                       } else {
+                               return 1;
+                       }
+               }
 
                id++;
        }
 
        dev_dbg(dev, "Device probe\n");
 
-       strlcpy(id.name, dev_name(dev), sizeof(id.name));
+       strlcpy(id.name, device->name, sizeof(id.name));
 
        return driver->probe(device, &id);
 }
 static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
                             char *buf)
 {
-       int len;
+       struct mei_cl_device *device = to_mei_cl_device(dev);
+       const uuid_le *uuid = mei_me_cl_uuid(device->me_cl);
+       size_t len;
 
-       len = snprintf(buf, PAGE_SIZE, "mei:%s\n", dev_name(dev));
+       len = snprintf(buf, PAGE_SIZE, "mei:%s:" MEI_CL_UUID_FMT ":",
+               device->name, MEI_CL_UUID_ARGS(uuid->b));
 
        return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
 }
 
 static int mei_cl_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
-       if (add_uevent_var(env, "MODALIAS=mei:%s", dev_name(dev)))
+       struct mei_cl_device *device = to_mei_cl_device(dev);
+       const uuid_le *uuid = mei_me_cl_uuid(device->me_cl);
+
+       if (add_uevent_var(env, "MODALIAS=mei:%s:" MEI_CL_UUID_FMT ":",
+               device->name, MEI_CL_UUID_ARGS(uuid->b)))
                return -ENOMEM;
 
        return 0;
        device->dev.bus = &mei_cl_bus_type;
        device->dev.type = &mei_cl_device_type;
 
-       dev_set_name(&device->dev, "%s", name);
+       strlcpy(device->name, name, sizeof(device->name));
+
+       dev_set_name(&device->dev, "mei:%s:%pUl", name, mei_me_cl_uuid(me_cl));
 
        status = device_register(&device->dev);
        if (status) {
 
  * @dev: linux driver model device pointer
  * @me_cl: me client
  * @cl: mei client
+ * @name: device name
  * @ops: ME transport ops
  * @event_work: async work to execute event callback
  * @event_cb: Drivers register this callback to get asynchronous ME
 
        struct mei_me_client *me_cl;
        struct mei_cl *cl;
+       char name[MEI_CL_NAME_SIZE];
 
        const struct mei_cl_ops *ops;
 
 
 
 #include <linux/mei_cl_bus.h>
 #include <net/nfc/hci.h>
+#include <linux/uuid.h>
 
+#define MEI_NFC_UUID __UUID_LE(0x0bb17a78, 0x2a8e, 0x4c50, \
+               0x94, 0xd4, 0x50, 0x26, 0x67, 0x23, 0x77, 0x5c)
 #define MEI_NFC_HEADER_SIZE 10
 #define MEI_NFC_MAX_HCI_PAYLOAD 300
 
 
 }
 
 static struct mei_cl_device_id microread_mei_tbl[] = {
-       { MICROREAD_DRIVER_NAME },
+       { MICROREAD_DRIVER_NAME, MEI_NFC_UUID},
 
        /* required last entry */
        { }
 
 }
 
 static struct mei_cl_device_id pn544_mei_tbl[] = {
-       { PN544_DRIVER_NAME },
+       { PN544_DRIVER_NAME, MEI_NFC_UUID},
 
        /* required last entry */
        { }
 
 
 #define MEI_CL_MODULE_PREFIX "mei:"
 #define MEI_CL_NAME_SIZE 32
+#define MEI_CL_UUID_FMT "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
+#define MEI_CL_UUID_ARGS(_u) \
+       _u[0], _u[1], _u[2], _u[3], _u[4], _u[5], _u[6], _u[7], \
+       _u[8], _u[9], _u[10], _u[11], _u[12], _u[13], _u[14], _u[15]
 
+/**
+ * struct mei_cl_device_id - MEI client device identifier
+ * @name: helper name
+ * @uuid: client uuid
+ * @driver_info: information used by the driver.
+ *
+ * identifies mei client device by uuid and name
+ */
 struct mei_cl_device_id {
        char name[MEI_CL_NAME_SIZE];
+       __u8 uuid[16];
        kernel_ulong_t driver_info;
 };
 
 
 
        DEVID(mei_cl_device_id);
        DEVID_FIELD(mei_cl_device_id, name);
+       DEVID_FIELD(mei_cl_device_id, uuid);
 
        DEVID(rio_device_id);
        DEVID_FIELD(rio_device_id, did);
 
                strcat(str + len, "*");
 }
 
+static inline void add_uuid(char *str, __u8 uuid[16])
+{
+       int len = strlen(str);
+       int i;
+
+       for (i = 0; i < 16; i++)
+               sprintf(str + len + (i << 1), "%02x", uuid[i]);
+}
+
 /**
  * Check that sizeof(device_id type) are consistent with size of section
  * in .o file. If in-consistent then userspace and kernel does not agree
 }
 ADD_TO_DEVTABLE("cpu", cpu_feature, do_cpu_entry);
 
-/* Looks like: mei:S */
+/* Looks like: mei:S:uuid */
 static int do_mei_entry(const char *filename, void *symval,
                        char *alias)
 {
        DEF_FIELD_ADDR(symval, mei_cl_device_id, name);
+       DEF_FIELD_ADDR(symval, mei_cl_device_id, uuid);
+
+       sprintf(alias, MEI_CL_MODULE_PREFIX);
+       sprintf(alias + strlen(alias), "%s:",  (*name)[0]  ? *name : "*");
+       add_uuid(alias, *uuid);
 
-       sprintf(alias, MEI_CL_MODULE_PREFIX "%s", *name);
+       strcat(alias, ":*");
 
        return 1;
 }