MKL27Z64VLH4 detect USB disconnect

cancel
Showing results for 
Search instead for 
Did you mean: 

MKL27Z64VLH4 detect USB disconnect

471 Views
dusek_martin
Contributor IV

Hi,

how can I detect USB cable disconnect event on MKL27Z64VLH4?

I use MKL27Z64VLH4 as USB device. It is connceted to a smartphone and at the same time it is powered by external power supply and it also powers USB bus so the smartphone can charge (USB Accessory charging adaptor).

This means It is not possible to detect USB disconnect event using USB bus voltage.

Thank you

Martin

Labels (2)
3 Replies

359 Views
myke_predko
Senior Contributor III

Hey Martin,

As I noted elsewhere, I'm using a modified form of the USB device demo code.  

To detect a connection/disconnection I have added code to notify my (FreeRTOS) command task that there has been a USB "disconnect" by the modifications to the "virtual_USB" code segements (int red).  I've put in the whole "case" code so you can find where the locations are more easily.  

Here:

case kUSB_DeviceCdcEventRecvResponse:
{

uint32_t i;
if ((1 == s_cdcVcom.attach) && (1 == s_cdcVcom.startTransactions)) {
s_recvSize = epCbParam->length;
if ((0 != s_recvSize) && (0xFFFFFFFF != s_recvSize)) {
for (i = 0; (s_recvSize + 0) > i; ++i) {
if (0 != usbBlockCountDown) {
usbCMDMsg.msg[usbCMDMsgSize++] = s_currRecvBuf[i];
--usbBlockCountDown;
}
else if (usbBlockFlag) {
usbBlockCountDown = (uint32_t)(usbCMDMsg.msg[usbCMDMsgSize++] = s_currRecvBuf[i]);
usbBlockFlag = FALSE;
}
else {

// myke packet receive code here/Modified from the original

mykeUSBBuffer[usbBufferSize++] = s_currRecvBuf[i];
}
}
s_recvSize = 0;
error = USB_DeviceCdcAcmRecv(handle
, USB_CDC_VCOM_BULK_OUT_ENDPOINT
, s_currRecvBuf
, g_UsbDeviceCdcVcomDicEndpoints[0].maxPacketSize);
}
else {
usbCMDMsg.header = CMD_REQUEST_DISCONNECT;
CMDMSGISR(usbCMDMsg)
}
}
}
break;

and here (I marked where I detect the "connection" in blue):

case kUSB_DeviceCdcEventSetControlLineState:
{
s_usbCdcAcmInfo.dteStatus = acmReqParam->setupValue;
/* activate/deactivate Tx carrier */
if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_CARRIER_ACTIVATION)
{
acmInfo->uartState |= USB_DEVICE_CDC_UART_STATE_TX_CARRIER;
}
else
{
acmInfo->uartState &= (uint16_t)~USB_DEVICE_CDC_UART_STATE_TX_CARRIER;
}

/* activate carrier and DTE */
if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_DTE_PRESENCE)
{
acmInfo->uartState |= USB_DEVICE_CDC_UART_STATE_RX_CARRIER;
}
else
{
acmInfo->uartState &= (uint16_t)~USB_DEVICE_CDC_UART_STATE_RX_CARRIER;
}

/* Indicates to DCE if DTE is present or not */
acmInfo->dtePresent = (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_DTE_PRESENCE) ? true : false;

/* Initialize the serial state buffer */
acmInfo->serialStateBuf[0] = NOTIF_REQUEST_TYPE; /* bmRequestType */
acmInfo->serialStateBuf[1] = USB_DEVICE_CDC_NOTIF_SERIAL_STATE; /* bNotification */
acmInfo->serialStateBuf[2] = 0x00; /* wValue */
acmInfo->serialStateBuf[3] = 0x00;
acmInfo->serialStateBuf[4] = 0x00; /* wIndex */
acmInfo->serialStateBuf[5] = 0x00;
acmInfo->serialStateBuf[6] = UART_BITMAP_SIZE; /* wLength */
acmInfo->serialStateBuf[7] = 0x00;
/* Notifiy to host the line state */
acmInfo->serialStateBuf[4] = acmReqParam->interfaceIndex;
/* Lower byte of UART BITMAP */
uartBitmap = (uint8_t *)&acmInfo->serialStateBuf[NOTIF_PACKET_SIZE + UART_BITMAP_SIZE - 2];
uartBitmap[0] = acmInfo->uartState & 0xFFu;
uartBitmap[1] = (acmInfo->uartState >> 8) & 0xFFu;
len = (uint32_t)(NOTIF_PACKET_SIZE + UART_BITMAP_SIZE);
if (0 == ((usb_device_cdc_acm_struct_t *)handle)->hasSentState)
{
error = USB_DeviceCdcAcmSend(handle, USB_CDC_VCOM_INTERRUPT_IN_ENDPOINT, acmInfo->serialStateBuf, len);
if (kStatus_USB_Success != error)
{
usb_echo("kUSB_DeviceCdcEventSetControlLineState error!");
}
((usb_device_cdc_acm_struct_t *)handle)->hasSentState = 1;
}

/* Update status */
if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_CARRIER_ACTIVATION) {
/* To do: CARRIER_ACTIVATED */
}
else {
/* To do: CARRIER_DEACTIVATED */
}
if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_DTE_PRESENCE)
{
/* DTE_ACTIVATED */
if (1 == s_cdcVcom.attach)
{
usbCMDMsg.header = CMD_REQUEST_CONNECT;
CMDMSGISR(usbCMDMsg)
s_cdcVcom.startTransactions = 1;
#if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \
defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \
defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
s_waitForDataReceive = 1;
USB0->INTEN &= ~USB_INTEN_SOFTOKEN_MASK;
s_comOpen = 1;
usb_echo("USB_APP_CDC_DTE_ACTIVATED\r\n");
#endif
}
}
else
{
/* DTE_DEACTIVATED */
if (1 == s_cdcVcom.attach)
{
usbCMDMsg.header = CMD_REQUEST_DISCONNECT;
CMDMSGISR(usbCMDMsg)
s_cdcVcom.startTransactions = 0;
}
}
}
break;

I don't if you would call these modifications "elegant" but they do the job.  I have the two "disconnect" locations as I have found that different apps and situations (ie unplugging the cable) will result in different code locations executing - but there are no observed conditions where there is something like "disconnect" - "connect" - "disconnect".  

Note that as this code is executing in the USB callback, I'm treating it like an ISR (and using the ISR Message Send APIs).  

If there's a better way of detecting connections/disconnections I'm interested in seeing it.  

myke

359 Views
dusek_martin
Contributor IV

Hi Myke,

thanks, but to be honest, I don't understand how the cable disconnect event detection can work with your code. Why is it implemented in CDC-related code (FYI I use HID device and I would like to have application-agnostic cable disconnect event)? Can you please explain?

Thanks

Martin

0 Kudos

359 Views
myke_predko
Senior Contributor III

Hi Martin,

Sorry, when you said "device", I assumed CDC and not HID - it's not specified in your original post.  

I haven't looked at the HID device code, but I would suggest that you look for similar events in the code as I found in the CDC device and see if you can determine when the device is connected/enumerated.  

Good luck, let me know if you have any other questions.

myke

0 Kudos