1*4882a593Smuzhiyun.. SPDX-License-Identifier: GPL-2.0 2*4882a593Smuzhiyun 3*4882a593Smuzhiyun============================================== 4*4882a593SmuzhiyunIntel(R) Management Engine (ME) Client bus API 5*4882a593Smuzhiyun============================================== 6*4882a593Smuzhiyun 7*4882a593Smuzhiyun 8*4882a593SmuzhiyunRationale 9*4882a593Smuzhiyun========= 10*4882a593Smuzhiyun 11*4882a593SmuzhiyunThe MEI character device is useful for dedicated applications to send and receive 12*4882a593Smuzhiyundata to the many FW appliance found in Intel's ME from the user space. 13*4882a593SmuzhiyunHowever, for some of the ME functionalities it makes sense to leverage existing software 14*4882a593Smuzhiyunstack and expose them through existing kernel subsystems. 15*4882a593Smuzhiyun 16*4882a593SmuzhiyunIn order to plug seamlessly into the kernel device driver model we add kernel virtual 17*4882a593Smuzhiyunbus abstraction on top of the MEI driver. This allows implementing Linux kernel drivers 18*4882a593Smuzhiyunfor the various MEI features as a stand alone entities found in their respective subsystem. 19*4882a593SmuzhiyunExisting device drivers can even potentially be re-used by adding an MEI CL bus layer to 20*4882a593Smuzhiyunthe existing code. 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun 23*4882a593SmuzhiyunMEI CL bus API 24*4882a593Smuzhiyun============== 25*4882a593Smuzhiyun 26*4882a593SmuzhiyunA driver implementation for an MEI Client is very similar to any other existing bus 27*4882a593Smuzhiyunbased device drivers. The driver registers itself as an MEI CL bus driver through 28*4882a593Smuzhiyunthe ``struct mei_cl_driver`` structure defined in :file:`include/linux/mei_cl_bus.c` 29*4882a593Smuzhiyun 30*4882a593Smuzhiyun.. code-block:: C 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun struct mei_cl_driver { 33*4882a593Smuzhiyun struct device_driver driver; 34*4882a593Smuzhiyun const char *name; 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun const struct mei_cl_device_id *id_table; 37*4882a593Smuzhiyun 38*4882a593Smuzhiyun int (*probe)(struct mei_cl_device *dev, const struct mei_cl_id *id); 39*4882a593Smuzhiyun int (*remove)(struct mei_cl_device *dev); 40*4882a593Smuzhiyun }; 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun 43*4882a593Smuzhiyun 44*4882a593SmuzhiyunThe mei_cl_device_id structure defined in :file:`include/linux/mod_devicetable.h` allows a 45*4882a593Smuzhiyundriver to bind itself against a device name. 46*4882a593Smuzhiyun 47*4882a593Smuzhiyun.. code-block:: C 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun struct mei_cl_device_id { 50*4882a593Smuzhiyun char name[MEI_CL_NAME_SIZE]; 51*4882a593Smuzhiyun uuid_le uuid; 52*4882a593Smuzhiyun __u8 version; 53*4882a593Smuzhiyun kernel_ulong_t driver_info; 54*4882a593Smuzhiyun }; 55*4882a593Smuzhiyun 56*4882a593SmuzhiyunTo actually register a driver on the ME Client bus one must call the :c:func:`mei_cl_add_driver` 57*4882a593SmuzhiyunAPI. This is typically called at module initialization time. 58*4882a593Smuzhiyun 59*4882a593SmuzhiyunOnce the driver is registered and bound to the device, a driver will typically 60*4882a593Smuzhiyuntry to do some I/O on this bus and this should be done through the :c:func:`mei_cl_send` 61*4882a593Smuzhiyunand :c:func:`mei_cl_recv` functions. More detailed information is in :ref:`api` section. 62*4882a593Smuzhiyun 63*4882a593SmuzhiyunIn order for a driver to be notified about pending traffic or event, the driver 64*4882a593Smuzhiyunshould register a callback via :c:func:`mei_cl_devev_register_rx_cb` and 65*4882a593Smuzhiyun:c:func:`mei_cldev_register_notify_cb` function respectively. 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun.. _api: 68*4882a593Smuzhiyun 69*4882a593SmuzhiyunAPI: 70*4882a593Smuzhiyun---- 71*4882a593Smuzhiyun.. kernel-doc:: drivers/misc/mei/bus.c 72*4882a593Smuzhiyun :export: drivers/misc/mei/bus.c 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun 76*4882a593SmuzhiyunExample 77*4882a593Smuzhiyun======= 78*4882a593Smuzhiyun 79*4882a593SmuzhiyunAs a theoretical example let's pretend the ME comes with a "contact" NFC IP. 80*4882a593SmuzhiyunThe driver init and exit routines for this device would look like: 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun.. code-block:: C 83*4882a593Smuzhiyun 84*4882a593Smuzhiyun #define CONTACT_DRIVER_NAME "contact" 85*4882a593Smuzhiyun 86*4882a593Smuzhiyun static struct mei_cl_device_id contact_mei_cl_tbl[] = { 87*4882a593Smuzhiyun { CONTACT_DRIVER_NAME, }, 88*4882a593Smuzhiyun 89*4882a593Smuzhiyun /* required last entry */ 90*4882a593Smuzhiyun { } 91*4882a593Smuzhiyun }; 92*4882a593Smuzhiyun MODULE_DEVICE_TABLE(mei_cl, contact_mei_cl_tbl); 93*4882a593Smuzhiyun 94*4882a593Smuzhiyun static struct mei_cl_driver contact_driver = { 95*4882a593Smuzhiyun .id_table = contact_mei_tbl, 96*4882a593Smuzhiyun .name = CONTACT_DRIVER_NAME, 97*4882a593Smuzhiyun 98*4882a593Smuzhiyun .probe = contact_probe, 99*4882a593Smuzhiyun .remove = contact_remove, 100*4882a593Smuzhiyun }; 101*4882a593Smuzhiyun 102*4882a593Smuzhiyun static int contact_init(void) 103*4882a593Smuzhiyun { 104*4882a593Smuzhiyun int r; 105*4882a593Smuzhiyun 106*4882a593Smuzhiyun r = mei_cl_driver_register(&contact_driver); 107*4882a593Smuzhiyun if (r) { 108*4882a593Smuzhiyun pr_err(CONTACT_DRIVER_NAME ": driver registration failed\n"); 109*4882a593Smuzhiyun return r; 110*4882a593Smuzhiyun } 111*4882a593Smuzhiyun 112*4882a593Smuzhiyun return 0; 113*4882a593Smuzhiyun } 114*4882a593Smuzhiyun 115*4882a593Smuzhiyun static void __exit contact_exit(void) 116*4882a593Smuzhiyun { 117*4882a593Smuzhiyun mei_cl_driver_unregister(&contact_driver); 118*4882a593Smuzhiyun } 119*4882a593Smuzhiyun 120*4882a593Smuzhiyun module_init(contact_init); 121*4882a593Smuzhiyun module_exit(contact_exit); 122*4882a593Smuzhiyun 123*4882a593SmuzhiyunAnd the driver's simplified probe routine would look like that: 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun.. code-block:: C 126*4882a593Smuzhiyun 127*4882a593Smuzhiyun int contact_probe(struct mei_cl_device *dev, struct mei_cl_device_id *id) 128*4882a593Smuzhiyun { 129*4882a593Smuzhiyun [...] 130*4882a593Smuzhiyun mei_cldev_enable(dev); 131*4882a593Smuzhiyun 132*4882a593Smuzhiyun mei_cldev_register_rx_cb(dev, contact_rx_cb); 133*4882a593Smuzhiyun 134*4882a593Smuzhiyun return 0; 135*4882a593Smuzhiyun } 136*4882a593Smuzhiyun 137*4882a593SmuzhiyunIn the probe routine the driver first enable the MEI device and then registers 138*4882a593Smuzhiyunan rx handler which is as close as it can get to registering a threaded IRQ handler. 139*4882a593SmuzhiyunThe handler implementation will typically call :c:func:`mei_cldev_recv` and then 140*4882a593Smuzhiyunprocess received data. 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun.. code-block:: C 143*4882a593Smuzhiyun 144*4882a593Smuzhiyun #define MAX_PAYLOAD 128 145*4882a593Smuzhiyun #define HDR_SIZE 4 146*4882a593Smuzhiyun static void conntact_rx_cb(struct mei_cl_device *cldev) 147*4882a593Smuzhiyun { 148*4882a593Smuzhiyun struct contact *c = mei_cldev_get_drvdata(cldev); 149*4882a593Smuzhiyun unsigned char payload[MAX_PAYLOAD]; 150*4882a593Smuzhiyun ssize_t payload_sz; 151*4882a593Smuzhiyun 152*4882a593Smuzhiyun payload_sz = mei_cldev_recv(cldev, payload, MAX_PAYLOAD) 153*4882a593Smuzhiyun if (reply_size < HDR_SIZE) { 154*4882a593Smuzhiyun return; 155*4882a593Smuzhiyun } 156*4882a593Smuzhiyun 157*4882a593Smuzhiyun c->process_rx(payload); 158*4882a593Smuzhiyun 159*4882a593Smuzhiyun } 160*4882a593Smuzhiyun 161*4882a593SmuzhiyunMEI Client Bus Drivers 162*4882a593Smuzhiyun====================== 163*4882a593Smuzhiyun 164*4882a593Smuzhiyun.. toctree:: 165*4882a593Smuzhiyun :maxdepth: 2 166*4882a593Smuzhiyun 167*4882a593Smuzhiyun hdcp 168*4882a593Smuzhiyun nfc 169