From LinuxMCE wiki
See also : Dhcpd-plugin
There exists a plugin device 'Plug and Play Plugin' which handles the logic of implementing plug and play. This device does not do any detection, that is done by separate detection devices, but it coordinates all the activity. The detection devices only need to fire 2 events: 'Device Detected' when a new device is detected , and 'Device Removed' when a device is removed. The detection devices do not need to worry about whether a corresponding LinuxMCE device exists, nor handle any logic. They can fire the same events repeatedly and the plugin handles the logic of filtering duplicates.
The detection devices can look for new items on any number of methods: the usb bus, the lan, firewire, PCI bus, IDE, SCSI, RS232, etc. Regardless of the method, the event to fire is always the same. The detection device can be written as a normal C++ LinuxMCE device that connects to the router, or can be a simple bash script that uses the MessageSend utility to fire the events.
When a new Detected/Removed event comes in the plugin adds an entry in the table PnpQueue. The event is handled in this order:
- determine type(s) of LinuxMCE device templates this could be from the table DeviceTemplate
- if possible narrow down the list using detection scripts
- prompt the user to confirm what type of device it is and if he wants to use it
- ask the user for options for the device
- add the device to the Device table
- install any software the device needs to run
- run the device.
Note the device will run in a 'limited' use mode until the user does a reload router. The user will be informed of this and given the option to do the reload. Some of the steps are skipped depending on various situations.
If the system crashes, is rebooted, or is otherwise interrupted, when the plugin restarts it will continue processing any events it didn't already finish. When a new device is detected and the user is prompted for something, such as to confirm the type of device or specify options, all logically relevant orbiters will display the message. Once a user begins answering the prompts on one orbiter, only that orbiter that will be used to answer the rest of the prompts. If the user fails to answer a prompt within 2 minutes, then all orbiters will again be used to re-ask the same question.
The plugin has logic to block the queue when appropriate. For example, if three new devices are detected at the same time, the user will be prompted on the first device right away. But no mention will be made of the other two until the user completely finishes answering any questions about the first device. This is to prevent the user getting confused. If a 'device removed' is fired for a device that was recently detected and the user didn't yet confirm his selections, those messages will be removed from all orbiters and any other 'device detected' events in the queue will be processed.
If you remove a device while plug and play plugin is running, the device will immediately be disabled. There is also a mechanism for having the plug and play plugin disable devices that were removed while the system was turned off, and for which no 'Device Removed' events were fired. To use this, the Device Detected event's parameter called 'Signature' must be specified. This must be a string unique for the device that is firing the events. For example, if there is a HAL device 16, the signature is "16,HAL". If there's an internal disk scanner on the md 35, the signature is "35,disk". Whenever this parameter is specified, the device that ends up getting created will have a device data parameter called 'PNP Signature' with this value. Then when the device that is firing the 'Device Detected' events finishes it's initial detection of devices it must fire a 'Done Detecting Devices' event, and then continue firing 'Device Detected' events as new devices are detected. As the PNP Plugin gets Device Detected events where the signature parameter is not null it will block them and put them on hold until it gets the 'Done Detecting Devices' event. Then when it gets that event, it will find all devices previously created with the given signature, see which ones were already detected again and are being blocked in the queue, and disable any devices that were previously enabled but weren't detected. Then it will unblock any 'Device Detected' events for the given signature and process all of them like normal. When a new device is detected, before adding a new device, PNP Plugin will look to see if there is another device with the same template on the same PC that was previously disabled, and if so, it will re-use that device, enabling it, and changing the parameters. In this way if the user has, for example, a PCI capture card in slot #1 and powers off the PC and moves it slot #2, there will still be just 1 Capture Card device in the database and the parameter 'PCI Location on Bus' will change. But if the user adds a second card, that will result in a 2nd device being created.
Syntax of the detected/removed events
Both events take the following parameters (numbers are from the EventParameter table in pluto_main):
- PK_CommMethod (52): What method of communication is used for this device
- DeviceData (55): is any information that would normally be stored in the Device_DeviceData, such as the com port, the block device for a hard drive, and so on
- IP_Address (28), Mac_Address (5): If this is a network device these are specified
- PK_DeviceTemplate (49): This is normally not specified since the plugin handles figuring out what template is appropriate. If, however, a detection device knows this it can specify it. For example, the detection device that monitors the IDE bus will, when it finds a new hard drive, fire this event with the PK_DeviceTemplate equals the ID of 'Generic Internal Drive'
- VendorModelID (51): A Unique ID to identify your device
- PK_PnpProtocol (53): Which protocol the device uses
- PNP_Serial_Number (54): If the unique instance of the device has a serial number, it can be put here. If it is, then any detect/remove events with the same serial number are assumed to be the same device. Ethernet devices are easy to track individually by the Mac address, but most other devices, like USB, are not because they do not have unique serial numbers. The plugin handles the logic of figuring out when 2 devices are really the same.
- Text (13): This can contain some text that will be shown to the user when he is prompted if he wants to use the new device. Normally it is not specified, and the plugin figures out what to call it
Additionally the 'device removed' event can send a parameter: PK_Device (26) if it knows exactly which device was removed. Normally it does not.
Making your device plug and play
In the DeviceTemplate edit page there is a plug and play section where you can add information about your device. This address records to the table DHCPDevice; note the name is legacy as it is no longer limited to just dhcp devices. Here are some examples, which correspond to current records in DHCPDevice:
FK_DeviceTemplate=46, Mac_Range_Low=aa:bb:cc..., Mac_Range_High=dd:ee:ff... : This means if a network device requests an ip and the mac address is within that range, it is a device template 46. Mac addresses are assumed to be unique. See 'MessageSend #1' for how a message would look to add such a device
FK_DeviceTemplate=1783, VendorModelID='0403f850', and in the DeviceTemplate table FK_CommMethod = 'USB': When a USB device is detected with that vendor/model, it is a 1783. See 'MessageSend #2'.
FK_DeviceTemplate=1752, PnpDetectionScript='YamahaReceiver.sh', and the FK_CommMethod = 'RS232'. There is no way to know what the device is without running the detection script. The plugin will run all possible detection scripts until it figures out which one it is. See the 'detection script' below for the syntax, and the 'MessageSend #3'.
There are some DeviceData you can assign to your DeviceTemplate to specify additional options which the plugin will look for. Remember to check the box 'User Master Device List Defaults' since these options apply globally to the device template.
DeviceData - Only One Per PC: If this is 1, only 1 instance of this device will be allowed per PC. If a 2nd one is detected, the parameters for the first one will be changed, and the device id will be reused rather than creating a new device.
DeviceData - Auto-assign to parents room: If this is 1 the plugin will not prompt the user what room the new device is in. This should be used for things like USB devices, internal hard drives, and so on, which should just be assumed to be in the same room as the host PC.
DeviceData - PNP Create Without Prompting: If this is 1, then if the system definitively determines which device template a device is it will be created without first asking the user. If this is not done, then even if the 'device detected' event includes a PK_DeviceTemplate parameter, the user will still be prompted to confirm the device before it is created.
DeviceData - Keep Serial Number On Disable: HAL is used to detect pnp devices, and it gives each one a serial number. When a disabled device has a serial number that matches a new one reported by HAL, it is assumed this is the same device and needs to be re-enabled (see PnpQueue::LocateDevice). Normally the serial numbers are reused. For example, a mouse plugged into a usb port may have the same serial number as a usb->rs232 dongle. So when a device is removed/disabled, the serial number should be cleared, otherwise if a different device is connected to the same port and has the same serial number, the normal process of identifying the device is bypassed and it's assumed to be the previously disabled device. If your pnp device will always have a unique serial number that is not reused, and you want it to persist so that the individual instance of the device is always re-enabled, set this parameter to 1.
Samples with MessageSend
Here are some sample messages you can send with the MessageSend utility. This assumes your detection device has an id of 999. Note that you must use a valid device number as the 'from' since that is what the plugin uses to determine on which machine the device was added.
Detected a new device on the network
/usr/pluto/bin/MessageSend dcerouter $PK_Device -1001 2 65 28 "192.168.80.99" 5 "00:10:75:00:D2:22" 52 3 53 2
and when the device is no longer on the network
/usr/pluto/bin/MessageSend dcerouter $PK_Device -1001 2 66 28 "192.168.80.99" 5 "00:10:75:00:D2:22" 52 3 53 2
A USB device is detected
/usr/pluto/bin/MessageSend dcerouter $PK_Device -1001 2 65 55 "37|usb2/2-2/2-2:1.7" 52 4 51 "0403f850"
Note that the vendor/model id is specified, which will be looked up in the DHCP Device database. And parameter 55 is specified so that when the device is created it will have a device data 37 (com port on pc) of "usb2/2-2/2-2:1.7". The usb detection device should automatically determine that the device connected appears as a usb com port, and therefore pass in that com port as a parameter to the event.
Some RS232 device is detected, probably because a generic USB->RS232 dongle was attached
/usr/pluto/bin/MessageSend dcerouter $PK_Device -1001 2 65 55 "37|usb2/2-2/2-2:1.8" 52 2
Note the comm method is RS232, and the port "usb2/2-2/2-2:1.8" is specified. The plugin will run every detection script in DHCPDevice for all RS232 devices until one detection script reports a match.
An internal hard drive is detected
/usr/pluto/bin/MessageSend dcerouter $PK_Device -1001 2 65 55 "152|/dev/hdb1" 52 8 49 1790
These are normally used for RS232 and Ethernet. However they work with any type of device. For example, if there are multiple device templates with the same range of mac addresses, then when a device is detected the user will be prompted which one it is. If there is a way to determine the model programatically, you can create a script which does this, and put it in the PNPDetectionScript in your DHCPDevice record. Note many devices can use the same detection script. For example, all 'Yamaha Receivers' are identified with the script 'YamahaReceiver.sh'. When a detection script is specified for a device template that is a candidate for the 'device detected' event, the plugin will run the script with 4 parameters: the device id of the plugin, the unique id for this event (the PK_PnpQueue), a path where the device is located (IP address for Ethernet devices, serial port for RS-232 devices, etc.), and the name of the pnp detection script.
The detection script should attempt to determine what device template is on the path using any appropriate means. If it finds a match, it should fire a message using the parameters it received, such as this:
/usr/pluto/bin/MessageSend dcerouter -r 0 $1 806 224 $2 13 "$4" 44 1752
which means the device is template 1752. If the device template is not something that it can determine, send the message leaving off parameter 44 (ie leave off the 44 1752). If there is some error condition you want logged, add parameter 18, as this:
/usr/pluto/bin/MessageSend localhost -r 0 $1 806 224 $2 13 "$4" 18 "the com port doesn't exist"