Commit 8913c048 authored by Damien George's avatar Damien George
Browse files

stmhal: Add support for USB MSC device.

This gives a functioning, independent MSC device.
parent c070ff24
......@@ -21,7 +21,7 @@ INC += -I$(PY_SRC)
INC += -I$(CMSIS_DIR)/inc
INC += -I$(CMSIS_DIR)/devinc
INC += -I$(HAL_DIR)/inc
INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/cdc/inc
INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/cdc/inc -I$(USBDEV_DIR)/class/msc/inc
#INC += -I$(USBHOST_DIR)
INC += -I$(FATFS_DIR)/src
#INC += -I$(CC3K_DIR)
......@@ -56,8 +56,10 @@ SRC_C = \
stm32f4xx_it.c \
stm32f4xx_hal_msp.c \
usbd_conf.c \
usbd_desc.c \
usbd_desc_vcp.c \
usbd_cdc_interface.c \
usbd_desc_msc.c \
usbd_msc_storage.c \
pendsv.c \
systick.c \
led.c \
......@@ -123,6 +125,10 @@ SRC_USBDEV = $(addprefix $(USBDEV_DIR)/,\
core/src/usbd_ctlreq.c \
core/src/usbd_ioreq.c \
class/cdc/src/usbd_cdc.c \
class/msc/src/usbd_msc.c \
class/msc/src/usbd_msc_bot.c \
class/msc/src/usbd_msc_scsi.c \
class/msc/src/usbd_msc_data.c \
)
# usbd_core.c \
......
......@@ -374,6 +374,10 @@ soft_reset:
// turn boot-up LED off
led_state(PYB_LED_GREEN, 0);
#if defined(USE_DEVICE_MODE)
usbd_storage_medium_kind_t usbd_medium_kind = USBD_STORAGE_MEDIUM_FLASH;
#endif
#if MICROPY_HW_HAS_SDCARD
// if an SD card is present then mount it on 1:/
if (sdcard_is_present()) {
......@@ -383,8 +387,8 @@ soft_reset:
} else {
if (first_soft_reset) {
// use SD card as medium for the USB MSD
#if 0
usbd_storage_select_medium(USBD_STORAGE_MEDIUM_SDCARD);
#if defined(USE_DEVICE_MODE)
usbd_medium_kind = USBD_STORAGE_MEDIUM_SDCARD;
#endif
}
}
......@@ -396,7 +400,7 @@ soft_reset:
pyb_usb_host_init();
#elif defined(USE_DEVICE_MODE)
// USB device
pyb_usb_dev_init(PYB_USB_DEV_VCP_MSC);
pyb_usb_dev_init(USBD_DEVICE_MSC, usbd_medium_kind);
#endif
#if MICROPY_HW_HAS_MMA7660
......
#include <string.h>
/*
#include "usb_core.h"
#include "usbd_cdc_core.h"
#include "usbd_pyb_core.h"
#include "usbd_usr.h"
*/
#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_cdc.h"
#include "usbd_cdc_interface.h"
#include "usbd_msc.h"
#include "usbd_msc_storage.h"
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
//#include "pendsv.h"
#include "usb.h"
#ifdef USE_DEVICE_MODE
......@@ -26,12 +21,12 @@ static int dev_is_enabled = 0;
uint32_t APP_dev_is_connected = 0; /* used by usbd_cdc_vcp */
mp_obj_t mp_const_vcp_interrupt = MP_OBJ_NULL;
void pyb_usb_dev_init(int usb_dev_type) {
void pyb_usb_dev_init(usbd_device_kind_t device_kind, usbd_storage_medium_kind_t medium_kind) {
#ifdef USE_DEVICE_MODE
if (!dev_is_enabled) {
// only init USB once in the device's power-lifetime
switch (usb_dev_type) {
case PYB_USB_DEV_VCP_MSC:
switch (device_kind) {
case USBD_DEVICE_CDC:
// XXX USBD_CDC_Init (called by one of these functions below) uses malloc,
// so the memory is invalid after a soft reset (which resets the GC).
USBD_Init(&hUSBDDevice, &VCP_Desc, 0);
......@@ -41,7 +36,20 @@ void pyb_usb_dev_init(int usb_dev_type) {
//USBD_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_PYB_cb, &USR_cb);
break;
case PYB_USB_DEV_HID:
case USBD_DEVICE_MSC:
// XXX USBD_CDC_Init (called by one of these functions below) uses malloc,
// so the memory is invalid after a soft reset (which resets the GC).
USBD_Init(&hUSBDDevice, &MSC_Desc, 0);
USBD_RegisterClass(&hUSBDDevice, &USBD_MSC);
if (medium_kind == USBD_STORAGE_MEDIUM_FLASH) {
USBD_MSC_RegisterStorage(&hUSBDDevice, (USBD_StorageTypeDef*)&USBD_FLASH_STORAGE_fops);
} else {
USBD_MSC_RegisterStorage(&hUSBDDevice, (USBD_StorageTypeDef*)&USBD_SDCARD_STORAGE_fops);
}
USBD_Start(&hUSBDDevice);
break;
case USBD_DEVICE_HID:
//USBD_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_PYB_HID_cb, &USR_cb);
// TODO
break;
......
......@@ -4,10 +4,18 @@
#define VCP_CHAR_CTRL_C (3)
#define VCP_CHAR_CTRL_D (4)
#define PYB_USB_DEV_VCP_MSC (0)
#define PYB_USB_DEV_HID (1)
typedef enum {
USBD_DEVICE_CDC,
USBD_DEVICE_MSC,
USBD_DEVICE_HID,
} usbd_device_kind_t;
void pyb_usb_dev_init(int usb_dev_type);
typedef enum {
USBD_STORAGE_MEDIUM_FLASH,
USBD_STORAGE_MEDIUM_SDCARD,
} usbd_storage_medium_kind_t;
void pyb_usb_dev_init(usbd_device_kind_t device_kind, usbd_storage_medium_kind_t medium_kind);
bool usb_vcp_is_enabled(void);
bool usb_vcp_is_connected(void);
void usb_vcp_set_interrupt_char(int c);
......
......@@ -48,6 +48,9 @@
#define USBD_SELF_POWERED 0
#define USBD_DEBUG_LEVEL 0
// for MSC device
#define MSC_MEDIA_PACKET 8192
/* Exported macro ------------------------------------------------------------*/
/* Memory management macros */
#define USBD_malloc gc_alloc
......
/**
******************************************************************************
* @file USB_Device/CDC_Standalone/Inc/usbd_desc.h
* @author MCD Application Team
* @version V1.0.1
* @date 26-February-2014
* @brief Header for usbd_desc.c module
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_DESC_H
#define __USBD_DESC_H
/* Includes ------------------------------------------------------------------*/
#include "usbd_def.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
extern USBD_DescriptorsTypeDef VCP_Desc;
#endif /* __USBD_DESC_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
extern USBD_DescriptorsTypeDef VCP_Desc;
extern USBD_DescriptorsTypeDef MSC_Desc;
/**
******************************************************************************
* @file USB_Device/MSC_Standalone/Src/usbd_desc.c
* @author MCD Application Team
* @version V1.0.1
* @date 26-February-2014
* @brief This file provides the USBD descriptors and string formating method.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_conf.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define USBD_VID 0x0483
#define USBD_PID 0x5720
#define USBD_LANGID_STRING 0x409
#define USBD_MANUFACTURER_STRING "STMicroelectronics"
#define USBD_PRODUCT_HS_STRING "Mass Storage in HS Mode"
#define USBD_SERIALNUMBER_HS_STRING "00000000001A"
#define USBD_PRODUCT_FS_STRING "Mass Storage in FS Mode"
#define USBD_SERIALNUMBER_FS_STRING "00000000001B"
#define USBD_CONFIGURATION_HS_STRING "MSC Config"
#define USBD_INTERFACE_HS_STRING "MSC Interface"
#define USBD_CONFIGURATION_FS_STRING "MSC Config"
#define USBD_INTERFACE_FS_STRING "MSC Interface"
/* Private macro -------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
uint8_t *USBD_MSC_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_MSC_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_MSC_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_MSC_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_MSC_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_MSC_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
uint8_t *USBD_MSC_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length);
#ifdef USB_SUPPORT_USER_STRING_DESC
uint8_t *USBD_MSC_USRStringDesc(USBD_SpeedTypeDef speed, uint8_t idx, uint16_t *length);
#endif /* USB_SUPPORT_USER_STRING_DESC */
/* Private variables ---------------------------------------------------------*/
USBD_DescriptorsTypeDef MSC_Desc = {
USBD_MSC_DeviceDescriptor,
USBD_MSC_LangIDStrDescriptor,
USBD_MSC_ManufacturerStrDescriptor,
USBD_MSC_ProductStrDescriptor,
USBD_MSC_SerialStrDescriptor,
USBD_MSC_ConfigStrDescriptor,
USBD_MSC_InterfaceStrDescriptor,
};
/* USB Standard Device Descriptor */
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
__ALIGN_BEGIN static uint8_t USBD_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = {
0x12, /* bLength */
USB_DESC_TYPE_DEVICE, /* bDescriptorType */
0x00, /* bcdUSB */
0x02,
0x00, /* bDeviceClass */
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
USB_MAX_EP0_SIZE, /* bMaxPacketSize */
LOBYTE(USBD_VID), /* idVendor */
HIBYTE(USBD_VID), /* idVendor */
LOBYTE(USBD_PID), /* idVendor */
HIBYTE(USBD_PID), /* idVendor */
0x00, /* bcdDevice rel. 2.00 */
0x02,
USBD_IDX_MFC_STR, /* Index of manufacturer string */
USBD_IDX_PRODUCT_STR, /* Index of product string */
USBD_IDX_SERIAL_STR, /* Index of serial number string */
USBD_MAX_NUM_CONFIGURATION /* bNumConfigurations */
}; /* USB_DeviceDescriptor */
/* USB Standard Device Descriptor */
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
__ALIGN_BEGIN static uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = {
USB_LEN_LANGID_STR_DESC,
USB_DESC_TYPE_STRING,
LOBYTE(USBD_LANGID_STRING),
HIBYTE(USBD_LANGID_STRING),
};
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
__ALIGN_BEGIN static uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
/* Private functions ---------------------------------------------------------*/
/**
* @brief Returns the device descriptor.
* @param speed: Current device speed
* @param length: Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_MSC_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
*length = sizeof(USBD_DeviceDesc);
return USBD_DeviceDesc;
}
/**
* @brief Returns the LangID string descriptor.
* @param speed: Current device speed
* @param length: Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_MSC_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
*length = sizeof(USBD_LangIDDesc);
return USBD_LangIDDesc;
}
/**
* @brief Returns the product string descriptor.
* @param speed: Current device speed
* @param length: Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_MSC_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if(speed == 0)
{
USBD_GetString((uint8_t *)(uint8_t *)USBD_PRODUCT_HS_STRING, USBD_StrDesc, length);
}
else
{
USBD_GetString((uint8_t *)(uint8_t *)USBD_PRODUCT_FS_STRING, USBD_StrDesc, length);
}
return USBD_StrDesc;
}
/**
* @brief Returns the manufacturer string descriptor.
* @param speed: Current device speed
* @param length: Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_MSC_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
USBD_GetString((uint8_t *)(uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
return USBD_StrDesc;
}
/**
* @brief Returns the serial number string descriptor.
* @param speed: Current device speed
* @param length: Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_MSC_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if(speed == USBD_SPEED_HIGH)
{
USBD_GetString((uint8_t *)(uint8_t *)USBD_SERIALNUMBER_HS_STRING, USBD_StrDesc, length);
}
else
{
USBD_GetString((uint8_t *)(uint8_t *)USBD_SERIALNUMBER_FS_STRING, USBD_StrDesc, length);
}
return USBD_StrDesc;
}
/**
* @brief Returns the configuration string descriptor.
* @param speed: Current device speed
* @param length: Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_MSC_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if(speed == USBD_SPEED_HIGH)
{
USBD_GetString((uint8_t *)(uint8_t *)USBD_CONFIGURATION_HS_STRING, USBD_StrDesc, length);
}
else
{
USBD_GetString((uint8_t *)(uint8_t *)USBD_CONFIGURATION_FS_STRING, USBD_StrDesc, length);
}
return USBD_StrDesc;
}
/**
* @brief Returns the interface string descriptor.
* @param speed: Current device speed
* @param length: Pointer to data length variable
* @retval Pointer to descriptor buffer
*/
uint8_t *USBD_MSC_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
if(speed == 0)
{
USBD_GetString((uint8_t *)(uint8_t *)USBD_INTERFACE_HS_STRING, USBD_StrDesc, length);
}
else
{
USBD_GetString((uint8_t *)(uint8_t *)USBD_INTERFACE_FS_STRING, USBD_StrDesc, length);
}
return USBD_StrDesc;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
......@@ -73,7 +73,7 @@ USBD_DescriptorsTypeDef VCP_Desc = {
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
__ALIGN_BEGIN uint8_t hUSBDDeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = {
__ALIGN_BEGIN static uint8_t hUSBDDeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = {
0x12, /* bLength */
USB_DESC_TYPE_DEVICE, /* bDescriptorType */
0x00, /* bcdUSB */
......@@ -98,7 +98,7 @@ __ALIGN_BEGIN uint8_t hUSBDDeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = {
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = {
__ALIGN_BEGIN static uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = {
USB_LEN_LANGID_STR_DESC,
USB_DESC_TYPE_STRING,
LOBYTE(USBD_LANGID_STRING),
......@@ -108,7 +108,7 @@ __ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = {
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
__ALIGN_BEGIN static uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
/* Private functions ---------------------------------------------------------*/
......
/**
******************************************************************************
* @file usbd_storage_msd.c
* @author MCD application Team
* @version V1.1.0
* @date 19-March-2012
* @brief This file provides the disk operations functions.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2012 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Heavily modified by dpgeorge for Micro Python.
*
******************************************************************************
*/
#include "usbd_msc.h"
#include "usbd_msc_storage.h"
#include "misc.h"
#include "storage.h"
#include "diskio.h"
#include "sdcard.h"
/******************************************************************************/
// Callback functions for when the internal flash is the mass storage device
static const int8_t FLASH_STORAGE_Inquirydata[] = { // 36 bytes
// LUN 0
0x00,
0x00, // 0x00 for a fixed drive, 0x80 for a removable drive
0x02,
0x02,
(STANDARD_INQUIRY_DATA_LEN - 5),
0x00,
0x00,
0x00,
'u', 'P', 'y', ' ', ' ', ' ', ' ', ' ', // Manufacturer : 8 bytes
'm', 'i', 'c', 'r', 'o', 'S', 'D', ' ', // Product : 16 Bytes
'F', 'l', 'a', 's', 'h', ' ', ' ', ' ',
'1', '.', '0' ,'0', // Version : 4 Bytes
};
/**
* @brief Initialize the storage medium
* @param lun : logical unit number
* @retval Status
*/
int8_t FLASH_STORAGE_Init(uint8_t lun) {
storage_init();
return 0;
}
/**
* @brief return medium capacity and block size
* @param lun : logical unit number
* @param block_num : number of physical block
* @param block_size : size of a physical block
* @retval Status
*/
int8_t FLASH_STORAGE_GetCapacity(uint8_t lun, uint32_t *block_num, uint16_t *block_size) {
*block_size = storage_get_block_size();
*block_num = storage_get_block_count();
return 0;
}
/**
* @brief check whether the medium is ready
* @param lun : logical unit number
* @retval Status
*/
int8_t FLASH_STORAGE_IsReady(uint8_t lun) {
return 0;
}
/**
* @brief check whether the medium is write-protected
* @param lun : logical unit number
* @retval Status
*/
int8_t FLASH_STORAGE_IsWriteProtected(uint8_t lun) {
return 0;
}
/**
* @brief Read data from the medium
* @param lun : logical unit number
* @param buf : Pointer to the buffer to save data
* @param blk_addr : address of 1st block to be read
* @param blk_len : nmber of blocks to be read
* @retval Status
*/
int8_t FLASH_STORAGE_Read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) {
disk_read(0, buf, blk_addr, blk_len);
/*
for (int i = 0; i < blk_len; i++) {
if (!storage_read_block(buf + i * FLASH_BLOCK_SIZE, blk_addr + i)) {
return -1;
}
}
*/
return 0;
}
/**
* @brief Write data to the medium
* @param lun : logical unit number
* @param buf : Pointer to the buffer to write from
* @param blk_addr : address of 1st block to be written
* @param blk_len : nmber of blocks to be read
* @retval Status
*/
int8_t FLASH_STORAGE_Write (uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) {
disk_write(0, buf, blk_addr, blk_len);
/*
for (int i = 0; i < blk_len; i++) {
if (!storage_write_block(buf + i * FLASH_BLOCK_SIZE, blk_addr + i)) {
return -1;
}
}
*/
storage_flush(); // XXX hack for now so that the cache is always flushed
return 0;
}
/**
* @brief Return number of supported logical unit
* @param None
* @retval number of logical unit
*/
int8_t FLASH_STORAGE_GetMaxLun(void) {
return 0;
}
const USBD_StorageTypeDef USBD_FLASH_STORAGE_fops = {
FLASH_STORAGE_Init,
FLASH_STORAGE_GetCapacity,
FLASH_STORAGE_IsReady,
FLASH_STORAGE_IsWriteProtected,
FLASH_STORAGE_Read,
FLASH_STORAGE_Write,
FLASH_STORAGE_GetMaxLun,
(int8_t *)FLASH_STORAGE_Inquirydata,
};
/******************************************************************************/
// Callback functions for when the SD card is the mass storage device
static const int8_t SDCARD_STORAGE_Inquirydata[] = { // 36 bytes
// LUN 0
0x00,
0x80, // 0x00 for a fixed drive, 0x80 for a removable drive
0x02,
0x02,
(STANDARD_INQUIRY_DATA_LEN - 5),
0x00,
0x00,
0x00,
'u', 'P', 'y', ' ', ' ', ' ', ' ', ' ', // Manufacturer : 8 bytes
'm', 'i', 'c', 'r', 'o', 'S', 'D', ' ', // Product : 16 Bytes
'S', 'D', ' ', 'c', 'a', 'r', 'd', ' ',
'1', '.', '0' ,'0', // Version : 4 Bytes
};