CCID: Add support for PC-to-Reader XfrBlock message
authorFilipe Rodrigues <filipepazrodrigues@gmail.com>
Mon, 18 Jun 2018 00:51:09 +0000 (17:51 -0700)
committerFilipe Rodrigues <filipepazrodrigues@gmail.com>
Mon, 25 Jun 2018 02:02:31 +0000 (19:02 -0700)
Demos/Device/ClassDriver/CCID/CCID.c
Demos/Device/ClassDriver/CCID/CCID.h
Demos/Device/ClassDriver/CCID/Descriptors.c
Demos/Device/ClassDriver/CCID/Descriptors.h
Demos/Device/LowLevel/CCID/CCID.c
Demos/Device/LowLevel/CCID/Descriptors.c
Demos/Device/LowLevel/CCID/HostTestApp/test_generic_ccid_libusb.js
LUFA/Drivers/USB/Class/Common/CCIDClassCommon.h
LUFA/Drivers/USB/Class/Device/CCIDClassDevice.c
LUFA/Drivers/USB/Class/Device/CCIDClassDevice.h

index 9059ad4..bb4c11c 100644 (file)
@@ -213,6 +213,34 @@ uint8_t CALLBACK_CCID_GetSlotStatus(USB_ClassInfo_CCID_Device_t* const CCIDInter
        }
 }
 
+/** Event handler for the CCID_PC_to_RDR_XfrBlock. This message is sent to the device
+ *  whenever an application at the host wants to send a block of bytes to the device
+ *  THe device reply back with an array of bytes
+ */
+uint8_t CALLBACK_CCID_XfrBlock(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo,
+                                                          uint8_t slot,
+                                                          uint8_t* const receivedBuffer,
+                                                          uint8_t receivedBufferSize,
+                                                          uint8_t* const sendBuffer,
+                                                          uint8_t* const sentBufferSize,
+                                                          uint8_t* const error)
+{
+       if (slot < CCID_Interface.Config.TotalSlots)
+       {
+               uint8_t okResponse[2] = {0x90, 0x00};
+               memcpy(sendBuffer, okResponse, sizeof(okResponse));
+               *sentBufferSize = sizeof(okResponse);
+
+               *error = CCID_ERROR_NO_ERROR;
+               return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_NOICCPRESENT;
+       }
+       else
+       {
+                *error = CCID_ERROR_SLOT_NOT_FOUND;
+         return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
+       }
+}
+
 uint8_t CALLBACK_CCID_Abort(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo,
                             uint8_t slot,
                                                        uint8_t seq,
index f6dd4ad..88c29ae 100644 (file)
                uint8_t CALLBACK_CCID_GetSlotStatus(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo,
                                                    uint8_t slot,
                                                    uint8_t* const error);
+               uint8_t CALLBACK_CCID_XfrBlock(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo,
+                                                                          uint8_t slot,
+                                                                          uint8_t* const receivedBuffer,
+                                                                          uint8_t receivedBufferSize,
+                                                                          uint8_t* const sendBuffer,
+                                                                          uint8_t* const sentBufferSize,
+                                                                          uint8_t* const error);
                uint8_t CALLBACK_CCID_Abort(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo,
                                            uint8_t slot,
                                            uint8_t seq,
index 43a6961..8860426 100644 (file)
@@ -117,8 +117,8 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
                        .MaxIFSD                                = 2038,
                        .SynchProtocols                 = 0,
                        .Mechanical                             = 0,
-                       .Features                               = 0x0400fe,
-                       .MaxCCIDMessageLength   = 0x0c00,
+                       .Features                               = CCID_Features_ExchangeLevel_ShortAPDU | CCID_Features_Auto_ParameterConfiguration| CCID_Features_Auto_ICCActivation | CCID_Features_Auto_VoltageSelection,
+                       .MaxCCIDMessageLength   = CCID_EPSIZE,
                        .ClassGetResponse               = 0xff,
                        .ClassEnvelope                  = 0xff,
                        .LcdLayout                              = 0,
index 239d612..63672d1 100644 (file)
@@ -49,7 +49,7 @@
                /** Endpoint address of the CCID data OUT endpoint, for host-to-device data transfers. */
                #define CCID_OUT_EPADDR      (ENDPOINT_DIR_OUT | 1)
 
-               /** Endpoint size in bytes of the Audio isochronous streaming data IN and OUT endpoints. */
+               /** Endpoint size in bytes of the CCID data being sent between IN and OUT endpoints. */
                #define CCID_EPSIZE          64
 
 
index 764392d..24849dc 100644 (file)
@@ -252,6 +252,33 @@ uint8_t CCID_GetSlotStatus(uint8_t slot,
        }
 }
 
+/** Event handler for the CCID_PC_to_RDR_XfrBlock. This message is sent to the device
+ *  whenever an application at the host wants to send a block of bytes to the device
+ *  THe device reply back with an array of bytes
+ */
+uint8_t CCID_XfrBlock(uint8_t slot,
+                                         uint8_t* const receivedBuffer,
+                                         uint8_t receivedBufferSize,
+                                         uint8_t* const sendBuffer,
+                                         uint8_t* const sentBufferSize,
+                                         uint8_t* const error)
+{
+       if (slot == 0)
+       {
+               uint8_t okResponse[2] = {0x90, 0x00};
+               memcpy(sendBuffer, okResponse, sizeof(okResponse));
+               *sentBufferSize = sizeof(okResponse);
+
+               *error = CCID_ERROR_NO_ERROR;
+               return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_NOICCPRESENT;
+       }
+       else
+       {
+                *error = CCID_ERROR_SLOT_NOT_FOUND;
+         return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
+       }
+}
+
 /** Event handler for the CCID_PC_to_RDR_ABort message. This message is sent to the device
  *  whenever an application wants to abort the current operation. A previous CCID_ABORT
  *  control message has to be sent before this one in order to start the abort operation.
@@ -293,7 +320,8 @@ void CCID_Task(void)
 {
        Endpoint_SelectEndpoint(CCID_OUT_EPADDR);
 
-       uint8_t BlockBuffer[0x20];
+       uint8_t RequestBuffer[CCID_EPSIZE - sizeof(USB_CCID_BulkMessage_Header_t)];
+       uint8_t ResponseBuffer[CCID_EPSIZE];
        Aborted = false;
        AbortedSeq = -1;
 
@@ -313,7 +341,7 @@ void CCID_Task(void)
                        case CCID_PC_to_RDR_IccPowerOn:
                        {
                                uint8_t  AtrLength;
-                               USB_CCID_RDR_to_PC_DataBlock_t* ResponseATR = (USB_CCID_RDR_to_PC_DataBlock_t*)&BlockBuffer;
+                               USB_CCID_RDR_to_PC_DataBlock_t* ResponseATR = (USB_CCID_RDR_to_PC_DataBlock_t*)&ResponseBuffer;
 
                                ResponseATR->CCIDHeader.MessageType = CCID_RDR_to_PC_DataBlock;
                                ResponseATR->CCIDHeader.Slot        = CCIDHeader.Slot;
@@ -350,7 +378,7 @@ void CCID_Task(void)
 
                        case CCID_PC_to_RDR_IccPowerOff:
                        {
-                               USB_CCID_RDR_to_PC_SlotStatus_t* ResponsePowerOff =  (USB_CCID_RDR_to_PC_SlotStatus_t*)&BlockBuffer;
+                               USB_CCID_RDR_to_PC_SlotStatus_t* ResponsePowerOff =  (USB_CCID_RDR_to_PC_SlotStatus_t*)&ResponseBuffer;
                                ResponsePowerOff->CCIDHeader.MessageType = CCID_RDR_to_PC_SlotStatus;
                                ResponsePowerOff->CCIDHeader.Length      = 0;
                                ResponsePowerOff->CCIDHeader.Slot        = CCIDHeader.Slot;
@@ -373,7 +401,7 @@ void CCID_Task(void)
 
                        case CCID_PC_to_RDR_GetSlotStatus:
                        {
-                               USB_CCID_RDR_to_PC_SlotStatus_t* ResponseSlotStatus = (USB_CCID_RDR_to_PC_SlotStatus_t*)&BlockBuffer;
+                               USB_CCID_RDR_to_PC_SlotStatus_t* ResponseSlotStatus = (USB_CCID_RDR_to_PC_SlotStatus_t*)&ResponseBuffer;
                                ResponseSlotStatus->CCIDHeader.MessageType = CCID_RDR_to_PC_SlotStatus;
                                ResponseSlotStatus->CCIDHeader.Length      = 0;
                                ResponseSlotStatus->CCIDHeader.Slot        = CCIDHeader.Slot;
@@ -394,9 +422,56 @@ void CCID_Task(void)
                                break;
                        }
 
+                       case CCID_PC_to_RDR_XfrBlock:
+                       {
+                               uint8_t  Bwi            = Endpoint_Read_8();
+                               uint16_t LevelParameter = Endpoint_Read_16_LE();
+
+                               (void)Bwi;
+                               (void)LevelParameter;
+
+                               Endpoint_Read_Stream_LE(RequestBuffer, CCIDHeader.Length * sizeof(uint8_t), NULL);
+
+                               uint8_t  ResponseDataLength = 0;
+
+                               USB_CCID_RDR_to_PC_DataBlock_t* ResponseBlock = (USB_CCID_RDR_to_PC_DataBlock_t*)&ResponseBuffer;
+                               ResponseBlock->CCIDHeader.MessageType = CCID_RDR_to_PC_DataBlock;
+                               ResponseBlock->CCIDHeader.Slot        = CCIDHeader.Slot;
+                               ResponseBlock->CCIDHeader.Seq         = CCIDHeader.Seq;
+
+                               ResponseBlock->ChainParam = 0;
+
+                               Status = CCID_XfrBlock(CCIDHeader.Slot, RequestBuffer, CCIDHeader.Length, &ResponseBlock->Data, &ResponseDataLength, &Error);
+
+                               if (CCID_CheckStatusNoError(Status) && !Aborted)
+                               {
+                                       ResponseBlock->CCIDHeader.Length = ResponseDataLength;
+                               }
+                               else if (Aborted)
+                               {
+                                       Status = CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_PRESENTANDACTIVE;
+                                       Error =  CCID_ERROR_CMD_ABORTED;
+                                       ResponseDataLength = 0;
+                               }
+                               else
+                               {
+                                       ResponseDataLength = 0;
+                               }
+
+                               ResponseBlock->Status = Status;
+                               ResponseBlock->Error  = Error;
+
+                               Endpoint_ClearOUT();
+
+                               Endpoint_SelectEndpoint(CCID_IN_EPADDR);
+                               Endpoint_Write_Stream_LE(ResponseBlock, sizeof(USB_CCID_RDR_to_PC_DataBlock_t) + ResponseDataLength, NULL);
+                               Endpoint_ClearIN();
+                               break;
+                       }
+
                        case CCID_PC_to_RDR_Abort:
                        {
-                               USB_CCID_RDR_to_PC_SlotStatus_t* ResponseAbort =  (USB_CCID_RDR_to_PC_SlotStatus_t*)&BlockBuffer;
+                               USB_CCID_RDR_to_PC_SlotStatus_t* ResponseAbort =  (USB_CCID_RDR_to_PC_SlotStatus_t*)&ResponseBuffer;
                                ResponseAbort->CCIDHeader.MessageType = CCID_RDR_to_PC_SlotStatus;
                                ResponseAbort->CCIDHeader.Length      = 0;
                                ResponseAbort->CCIDHeader.Slot        = CCIDHeader.Slot;
@@ -418,10 +493,10 @@ void CCID_Task(void)
                        }
                        default:
                        {
-                               memset(BlockBuffer, 0x00, sizeof(BlockBuffer));
+                               memset(ResponseBuffer, 0x00, sizeof(ResponseBuffer));
 
                                Endpoint_SelectEndpoint(CCID_IN_EPADDR);
-                               Endpoint_Write_Stream_LE(BlockBuffer, sizeof(BlockBuffer), NULL);
+                               Endpoint_Write_Stream_LE(ResponseBuffer, sizeof(ResponseBuffer), NULL);
                                Endpoint_ClearIN();
                        }
                }
index c82216c..5e092e2 100644 (file)
@@ -119,8 +119,8 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
                        .MaxIFSD                                = 2038,
                        .SynchProtocols                 = 0,
                        .Mechanical                             = 0,
-                       .Features                               = 0x0400fe,
-                       .MaxCCIDMessageLength   = 0x0c00,
+                       .Features                               = CCID_Features_ExchangeLevel_ShortAPDU | CCID_Features_Auto_ParameterConfiguration| CCID_Features_Auto_ICCActivation | CCID_Features_Auto_VoltageSelection,
+                       .MaxCCIDMessageLength   = CCID_EPSIZE,
                        .ClassGetResponse               = 0xff,
                        .ClassEnvelope                  = 0xff,
                        .LcdLayout                              = 0,
index 993c0e5..e521cdb 100644 (file)
@@ -106,17 +106,16 @@ function GetSlotStatusMessage(slot, seq)
     ];
 }
 
-function XfrBlockMessage(slot, seq)
+function XfrBlockMessage(slot, seq, apdu)
 {
     return [
         CCID_PC_to_RDR_XfrBlock, //message type
-        5, 0, 0, 0, //length (05)
+        apdu.length, 0, 0, 0, //length: only for < 0xFF
         slot,
         seq,
         0, //BWI 
-        0, 0, //level parameter
-        0, 0xfd, 0, 0, 0 //message
-    ];
+        0, 0 //level parameter
+    ].concat(apdu);
 
 }
 
@@ -140,6 +139,12 @@ function startTest()
         },
         function(callback) {
             read(ccidInterface, 10, callback);
+        },
+        function(callback) {
+            write(ccidInterface, new Buffer(XfrBlockMessage(0, 4, [0x0, 0xFD, 0x0, 0x0, 0x0])), callback);
+        },
+        function(callback) {
+            read(ccidInterface, 10 + 2, callback);
         }
         ]);
 }
index 6cedcad..cf8fdba 100644 (file)
                        CCID_DTYPE_Functional                       = 0x21, /**< CCID class specific Interface functional descriptor. */
                };
 
+               enum CCID_Features_Auto_t
+               {
+                       CCID_Features_Auto_None                                         = 0x0,
+                       CCID_Features_Auto_ParameterConfiguration       = 0x2,
+                       CCID_Features_Auto_ICCActivation                        = 0x4,
+                       CCID_Features_Auto_VoltageSelection                     = 0x8,
+
+                       CCID_Features_Auto_ICCClockFrequencyChange      = 0x10,
+                       CCID_Features_Auto_ICCBaudRateChange            = 0x20,
+                       CCID_Features_Auto_ParameterNegotiation         = 0x40,
+                       CCID_Features_Auto_PPS                                          = 0x80,
+               };
+
+               enum CCID_Features_ExchangeLevel_t
+               {
+                       CCID_Features_ExchangeLevel_TPDU                                = 0x00010000,
+                       CCID_Features_ExchangeLevel_ShortAPDU                   = 0x00020000,
+                       CCID_Features_ExchangeLevel_ShortExtendedAPDU   = 0x00040000
+               };
+
        /* Type Defines: */
                typedef struct
                {
index 0595e07..450ed9d 100644 (file)
@@ -129,7 +129,9 @@ void CCID_Device_USBTask(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo)
 {
        Endpoint_SelectEndpoint(CCIDInterfaceInfo->Config.DataOUTEndpoint.Address);
 
-       uint8_t BlockBuffer[0x20];
+       uint8_t RequestBuffer[0x40 - sizeof(USB_CCID_BulkMessage_Header_t)];
+       uint8_t ResponseBuffer[0x40];
+
        CCIDInterfaceInfo->State.Aborted    = false;
        CCIDInterfaceInfo->State.AbortedSeq = -1;
 
@@ -149,7 +151,7 @@ void CCID_Device_USBTask(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo)
                        case CCID_PC_to_RDR_IccPowerOn:
                        {
                                uint8_t AtrLength;
-                               USB_CCID_RDR_to_PC_DataBlock_t* ResponseATR = (USB_CCID_RDR_to_PC_DataBlock_t*)&BlockBuffer;
+                               USB_CCID_RDR_to_PC_DataBlock_t* ResponseATR = (USB_CCID_RDR_to_PC_DataBlock_t*)&ResponseBuffer;
 
                                ResponseATR->CCIDHeader.MessageType = CCID_RDR_to_PC_DataBlock;
                                ResponseATR->CCIDHeader.Slot        = CCIDHeader.Slot;
@@ -186,7 +188,7 @@ void CCID_Device_USBTask(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo)
 
                        case CCID_PC_to_RDR_IccPowerOff:
                        {
-                               USB_CCID_RDR_to_PC_SlotStatus_t* ResponsePowerOff = (USB_CCID_RDR_to_PC_SlotStatus_t*)&BlockBuffer;
+                               USB_CCID_RDR_to_PC_SlotStatus_t* ResponsePowerOff = (USB_CCID_RDR_to_PC_SlotStatus_t*)&ResponseBuffer;
                                ResponsePowerOff->CCIDHeader.MessageType = CCID_RDR_to_PC_SlotStatus;
                                ResponsePowerOff->CCIDHeader.Length      = 0;
                                ResponsePowerOff->CCIDHeader.Slot        = CCIDHeader.Slot;
@@ -209,7 +211,7 @@ void CCID_Device_USBTask(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo)
 
                        case CCID_PC_to_RDR_GetSlotStatus:
                        {
-                               USB_CCID_RDR_to_PC_SlotStatus_t* ResponseSlotStatus = (USB_CCID_RDR_to_PC_SlotStatus_t*)&BlockBuffer;
+                               USB_CCID_RDR_to_PC_SlotStatus_t* ResponseSlotStatus = (USB_CCID_RDR_to_PC_SlotStatus_t*)&ResponseBuffer;
                                ResponseSlotStatus->CCIDHeader.MessageType = CCID_RDR_to_PC_SlotStatus;
                                ResponseSlotStatus->CCIDHeader.Length      = 0;
                                ResponseSlotStatus->CCIDHeader.Slot        = CCIDHeader.Slot;
@@ -230,9 +232,57 @@ void CCID_Device_USBTask(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo)
                                break;
                        }
 
+                       case CCID_PC_to_RDR_XfrBlock:
+                       {
+                               uint8_t  Bwi            = Endpoint_Read_8();
+                               uint16_t LevelParameter = Endpoint_Read_16_LE();
+                               uint8_t  ReceivedBuffer[0x4];
+
+                               (void)Bwi;
+                               (void)LevelParameter;
+
+                               Endpoint_Read_Stream_LE(ReceivedBuffer, sizeof(ReceivedBuffer), NULL);
+
+                               uint8_t ResponseDataLength      = 0;
+
+                               USB_CCID_RDR_to_PC_DataBlock_t* ResponseBlock = (USB_CCID_RDR_to_PC_DataBlock_t*)&ResponseBuffer;
+                               ResponseBlock->CCIDHeader.MessageType = CCID_RDR_to_PC_DataBlock;
+                               ResponseBlock->CCIDHeader.Slot        = CCIDHeader.Slot;
+                               ResponseBlock->CCIDHeader.Seq         = CCIDHeader.Seq;
+
+                               ResponseBlock->ChainParam = 0;
+
+                               Status = CALLBACK_CCID_XfrBlock(CCIDInterfaceInfo, CCIDHeader.Slot, RequestBuffer, CCIDHeader.Length, (uint8_t*) &ResponseBlock->Data, &ResponseDataLength, &Error);
+
+                               if (CCID_CheckStatusNoError(Status) && !CCIDInterfaceInfo->State.Aborted)
+                               {
+                                       ResponseBlock->CCIDHeader.Length = ResponseDataLength;
+                               }
+                               else if(CCIDInterfaceInfo->State.Aborted)
+                               {
+                                       Status = CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_PRESENTANDACTIVE;
+                                       Error  = CCID_ERROR_CMD_ABORTED;
+                                       ResponseDataLength = 0;
+                               }
+                               else
+                               {
+                                       ResponseDataLength = 0;
+                               }
+
+                               ResponseBlock->Status = Status;
+                               ResponseBlock->Error  = Error;
+
+                               Endpoint_ClearOUT();
+
+                               Endpoint_SelectEndpoint(CCIDInterfaceInfo->Config.DataINEndpoint.Address);
+                               Endpoint_Write_Stream_LE(ResponseBlock, sizeof(USB_CCID_RDR_to_PC_DataBlock_t) + ResponseDataLength, NULL);
+                               Endpoint_ClearIN();
+                               break;
+                       }
+
                        case CCID_PC_to_RDR_Abort:
                        {
-                               USB_CCID_RDR_to_PC_SlotStatus_t* ResponseAbort = (USB_CCID_RDR_to_PC_SlotStatus_t*)&BlockBuffer;
+                               USB_CCID_RDR_to_PC_SlotStatus_t* ResponseAbort = (USB_CCID_RDR_to_PC_SlotStatus_t*)&ResponseBuffer;
                                ResponseAbort->CCIDHeader.MessageType = CCID_RDR_to_PC_SlotStatus;
                                ResponseAbort->CCIDHeader.Length      = 0;
                                ResponseAbort->CCIDHeader.Slot        = CCIDHeader.Slot;
@@ -255,10 +305,10 @@ void CCID_Device_USBTask(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo)
 
                        default:
                        {
-                               memset(BlockBuffer, 0x00, sizeof(BlockBuffer));
+                               memset(ResponseBuffer, 0x00, sizeof(ResponseBuffer));
 
                                Endpoint_SelectEndpoint(CCIDInterfaceInfo->Config.DataINEndpoint.Address);
-                               Endpoint_Write_Stream_LE(BlockBuffer, sizeof(BlockBuffer), NULL);
+                               Endpoint_Write_Stream_LE(ResponseBuffer, sizeof(ResponseBuffer), NULL);
                                Endpoint_ClearIN();
                        }
                }
index 245e126..d101723 100644 (file)
                                                            uint8_t slot,
                                                            uint8_t* const error) ATTR_NON_NULL_PTR_ARG(1);
 
+                       /** CCID class driver callback for PC_TO_RDR_XfrBlock CCID message
+                        *  Send a block of bytes from the host to a slot in the device 
+                        *  and also received a block of bytes as a response
+                        * 
+                        *  \param[in,out] CCIDInterfaceInfo    Pointer to a structure containing a CCID Class configuration and state.
+                        *  \param[in]     slot                                 The slot ID from which we want to retrieve the status.
+                        *  \param[in]     receivedBuffer               Pointer to an array holding the received block of bytes
+                        *  \param[in]     receivedBufferSize   The size of the received block of bytes
+                        *  \param[out]    sendBuffer                   Pointer to a buffer which will hold the bytes being sent back to the host
+                        *  \param[out]     sentBufferSize              The size of the block of bytes being sent back to the host
+                        *  \param[out]    error                                The result of the operation, or error.
+                        *
+                        *  \return     The command result code.
+                        */
+                       uint8_t CALLBACK_CCID_XfrBlock(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo,
+                                                                                  uint8_t slot, 
+                                                                                  uint8_t* const receivedBuffer, 
+                                                                                  uint8_t receivedBufferSize, 
+                                                                                  uint8_t* const sendBuffer, 
+                                                                                  uint8_t* const sentBufferSize, 
+                                                                                  uint8_t* const error);
+
                        /** CCID class driver callback for CCID_PC_to_RDR_Abort CCID message
                         *  Aborts a BULK out message previously sent to a slot
                         *