diff --git a/include/unicore-mx/usb/byteorder.h b/include/unicore-mx/usb/byteorder.h new file mode 100644 index 00000000..06c1e64c --- /dev/null +++ b/include/unicore-mx/usb/byteorder.h @@ -0,0 +1,47 @@ +#ifndef _USB_BYTEORDER_H +#define _USB_BYTEORDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __LITTLE_ENDIAN_BITFIELD +#define __LITTLE_ENDIAN_BITFIELD +#endif + +#ifndef HTONS + +#include +static inline +uint32_t usb_ntohl(uint32_t x){ + return ((x)>> 24 & 0xff) + | ((x)>>8 & 0xff00) + | ((x)<<8 & 0xff0000L) + | ((x)<<24 & 0xff000000L) + ; +} + +static inline +uint16_t usb_ntohs(uint16_t x){ + return ((x)>>8 & 0xff) | ((x)<<8 & 0xff00); +} + +static inline +uint32_t usb_htonl(uint32_t x) { return usb_ntohl(x); }; + +static inline +uint16_t usb_htons(uint16_t x) {return usb_ntohs(x); }; + +#define HTONS(x) usb_htons(x) +#define HTONL(x) usb_htonl(x) +#define NTOHS(x) usb_ntohs(x) +#define NTOHL(x) usb_ntohl(x) + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/unicore-mx/usb/class/msc.h b/include/unicore-mx/usb/class/msc.h index db3f0f00..13e96db8 100644 --- a/include/unicore-mx/usb/class/msc.h +++ b/include/unicore-mx/usb/class/msc.h @@ -86,35 +86,12 @@ LGPL License Terms @ref lgpl_license #define USB_MSC_CSW_STATUS_FAILED 1 #define USB_MSC_CSW_STATUS_PHASE_ERROR 2 -/* Implemented SCSI Commands */ -#define USB_MSC_SCSI_TEST_UNIT_READY 0x00 -#define USB_MSC_SCSI_REQUEST_SENSE 0x03 -#define USB_MSC_SCSI_FORMAT_UNIT 0x04 -#define USB_MSC_SCSI_READ_6 0x08 -#define USB_MSC_SCSI_WRITE_6 0x0A -#define USB_MSC_SCSI_INQUIRY 0x12 -#define USB_MSC_SCSI_MODE_SENSE_6 0x1A -#define USB_MSC_SCSI_SEND_DIAGNOSTIC 0x1D -#define USB_MSC_SCSI_READ_CAPACITY 0x25 -#define USB_MSC_SCSI_READ_10 0x28 - - -/* Required SCSI Commands */ - -/* Optional SCSI Commands */ -#define USB_MSC_SCSI_REPORT_LUNS 0xA0 -#define USB_MSC_SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E -#define USB_MSC_SCSI_MODE_SELECT_6 0x15 -#define USB_MSC_SCSI_MODE_SELECT_10 0x55 -#define USB_MSC_SCSI_MODE_SENSE_10 0x5A -#define USB_MSC_SCSI_READ_12 0xA8 -#define USB_MSC_SCSI_READ_FORMAT_CAPACITIES 0x23 -#define USB_MSC_SCSI_READ_TOC_PMA_ATIP 0x43 -#define USB_MSC_SCSI_START_STOP_UNIT 0x1B -#define USB_MSC_SCSI_SYNCHRONIZE_CACHE 0x35 -#define USB_MSC_SCSI_VERIFY 0x2F -#define USB_MSC_SCSI_WRITE_10 0x2A -#define USB_MSC_SCSI_WRITE_12 0xAA +#include + +#include +#ifdef __cplusplus + extern "C" { +#endif struct usb_msc_cbw { uint32_t dCBWSignature; @@ -133,6 +110,12 @@ struct usb_msc_csw { uint8_t bCSWStatus; } __attribute__((packed)); + + +#ifdef __cplusplus + } +#endif + #endif /**@}*/ diff --git a/include/unicore-mx/usb/class/msc_scsi.h b/include/unicore-mx/usb/class/msc_scsi.h new file mode 100644 index 00000000..5ee3e7cc --- /dev/null +++ b/include/unicore-mx/usb/class/msc_scsi.h @@ -0,0 +1,164 @@ +/** @defgroup usb_msc_scsi_defines USB MSC SCSI API Definitions + +@brief Defined Constants and Types for the USB MSC SCSI API Definitions + +@ingroup USB_defines + +@version 1.0.0 + +@author @htmlonly © @endhtmlonly 2013 +alexrayne +@date 30 ecember 2016 + +LGPL License Terms @ref lgpl_license +*/ +/* + * Copyright (C) 2016 alexrayne + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#ifndef UNICORE_USB_CLASS_MSC_SCSI_H +#define UNICORE_USB_CLASS_MSC_SCSI_H + +#include + +/* Implemented SCSI Commands */ +#define USB_MSC_SCSI_TEST_UNIT_READY 0x00 +#define USB_MSC_SCSI_REQUEST_SENSE 0x03 +#define USB_MSC_SCSI_FORMAT_UNIT 0x04 +#define USB_MSC_SCSI_READ_6 0x08 +#define USB_MSC_SCSI_WRITE_6 0x0A +#define USB_MSC_SCSI_INQUIRY 0x12 +#define USB_MSC_SCSI_MODE_SENSE_6 0x1A +#define USB_MSC_SCSI_SEND_DIAGNOSTIC 0x1D +#define USB_MSC_SCSI_READ_FORMAT_CAPACITIES 0x23 +#define USB_MSC_SCSI_READ_CAPACITY 0x25 +#define USB_MSC_SCSI_READ_10 0x28 +/* Required SCSI Commands */ + +/* Optional SCSI Commands */ +#define USB_MSC_SCSI_REPORT_LUNS 0xA0 +#define USB_MSC_SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E +#define USB_MSC_SCSI_MODE_SELECT_6 0x15 +#define USB_MSC_SCSI_MODE_SELECT_10 0x55 +#define USB_MSC_SCSI_MODE_SENSE_10 0x5A +#define USB_MSC_SCSI_READ_12 0xA8 +#define USB_MSC_SCSI_READ_TOC_PMA_ATIP 0x43 +#define USB_MSC_SCSI_START_STOP_UNIT 0x1B +#define USB_MSC_SCSI_SYNCHRONIZE_CACHE 0x35 +#define USB_MSC_SCSI_VERIFY 0x2F +#define USB_MSC_SCSI_WRITE_10 0x2A +#define USB_MSC_SCSI_WRITE_12 0xAA + +#ifdef __cplusplus + extern "C" { +#endif + +//* structires uses net order (big_endian) +typedef uint32_t net_u32_t; +typedef uint16_t net_u16_t; +typedef uint8_t net_u24_t[3]; + +static inline +void u24_assign(net_u24_t dst, uint32_t x){ + dst[2] = x & 0xff; + x >>= 8; + dst[1] = x & 0xff; + x >>= 8; + dst[0] = x & 0xff; +}; + +static inline +uint32_t u24_asul(net_u24_t x) +{ + uint32_t res = (x[0] << 8) | x[1]; + res = (res << 8) | x[2]; + return res; +}; + +typedef enum{ + scsi_vpd_Supported = 0 //* < Supported Vital Product Data pages + , scsi_vpd_Serial = 0x80 //* < Unit Serial Number page + , scsi_vpd_DevIdentification = 0x83 //* < Device Identification +} scsi_VPD_page; + +//* SCSI - INQUIRY structures +typedef struct { + uint8_t op_code; + uint8_t evpd; + uint8_t page_code; //* \see scsi_VPD_page + net_u16_t alloc_len; +} __attribute__((packed)) usb_inquiry_cmd ; + + +typedef enum { +/** A peripheral device having the specified peripheral device type is connected to this logical unit. If the +device server is unable to determine whether or not a peripheral device is connected, it also shall use +this peripheral qualifier. This peripheral qualifier does not mean that the peripheral device connected +to the logical unit is ready for access.*/ + scsi_pqAvail = 0 +/** A peripheral device having the specified peripheral device type is not connected to this logical unit. +However, the device server is capable of supporting the specified peripheral device type on this logi- +cal unit. */ + , scsi_pqRemoved = 1 +/** The device server is not capable of supporting a peripheral device on this logical unit. For this periph- +eral qualifier the peripheral device type shall be set to 1Fh. All other peripheral device type values are +reserved for this peripheral qualifier */ + , scsi_pqNoSupport = 3 +} scsi_periferial_qualify; + +typedef enum { + scsi_dtDirectBlock = 0 //* < Direct access block device (e.g., magnetic disk) + , scsi_dtSeqBlock = 1 //* < Sequential-access device (e.g., magnetic tape) + , scsi_dtWriteOnce = 4 //* < Write-once device (e.g., some optical disks) + , scsi_dtCDDVD = 5 //* < CD/DVD device + , scsi_dtOptical = 7 //* #include +#ifdef __cplusplus + extern "C" { +#endif + typedef struct usbd_msc usbd_msc; typedef struct usbd_msc_backend usbd_msc_backend; @@ -64,18 +68,28 @@ typedef struct usbd_msc_backend usbd_msc_backend; * @param lock Lock. Optional - can be NULL * @param unlock Unlock. Optional - can be NULL */ +typedef uint32_t msc_lba_t; +typedef unsigned msc_lun_t; + struct usbd_msc_backend { const char *vendor_id; const char *product_id; const char *product_rev; - uint32_t block_count; + msc_lba_t block_count; int (*read_block)(const usbd_msc_backend *backend, - uint32_t lba, void *copy_to); + msc_lba_t lba, void *copy_to); int (*write_block)(const usbd_msc_backend *backend, - uint32_t lba, const void *copy_from); + msc_lba_t lba, const void *copy_from); int (*format_unit)(const usbd_msc_backend *backend); int (*lock)(void); int (*unlock)(void); + msc_lba_t (*unit_blocks_count)(const usbd_msc_backend *self); + int (*inquiry_page)(const usbd_msc_backend *self + //, usb_inquiry_cmd* cmd + , int vpd_page //* < \value -1 request standart iquiry page (EVPD=0) + , unsigned alloc_limit //* < TODO limited by sector size now, due use MCS sector buffer as buf + , void* buf //* < buffer for inquiry data fill to + ); }; usbd_msc *usbd_msc_init(usbd_device *dev, @@ -91,6 +105,36 @@ void usbd_msc_set_config(usbd_msc *ms, void usbd_msc_start(usbd_msc *ms); +static inline +msc_lba_t usbd_msc_blocks(const usbd_msc_backend *u) +{ + if (u->unit_blocks_count != NULL) + return (u->unit_blocks_count)(u); + return u->block_count; +} + + + +//* INQUIRY support routines. +//* this resources linked as weak, and can be ovverriden in user code. +int usbd_scsi_inquiry_page(const usbd_msc_backend *self + //, usb_inquiry_cmd* cmd + , int vpd_page //* < \value -1 request standart iquiry page (EVPD=0) + , unsigned alloc_limit //* < TODO limited by sector size now, due use MCS sector buffer as buf + , void* buf //* < buffer for inquiry data fill to + ); +int usbd_scsi_inquiry_standart_page(const usbd_msc_backend *self, unsigned alloc_limit, void* buf); +int usbd_scsi_inquiry_evpd_supports(const usbd_msc_backend *self, unsigned alloc_limit, void* buf); +int usbd_scsi_inquiry_evpd_serial(const usbd_msc_backend *self, unsigned alloc_limit, void* buf); + +extern const uint8_t usbd_scsi_inquiry_evpd_supports_Data[]; +extern const uint8_t usbd_scsi_inquiry_evpd_serial_Data[]; + + +#ifdef __cplusplus + } +#endif + #endif /**@}*/ diff --git a/lib/usbd/backend/usbd_dwc_otg.c b/lib/usbd/backend/usbd_dwc_otg.c index ebb42f89..f93202fd 100644 --- a/lib/usbd/backend/usbd_dwc_otg.c +++ b/lib/usbd/backend/usbd_dwc_otg.c @@ -332,7 +332,7 @@ void dwc_otg_set_ep_stall(usbd_device *dev, uint8_t addr, bool stall) { uint8_t num = ENDPOINT_NUMBER(addr); - LOGF_LN("STALL endpoint 0x%"PRIx8" = %s", addr, stall ? "Yes" : "No"); + USBD_LOGF_LN(USB_VIO, "STALL ep0x%"PRIx8" = %s", addr, stall ? "Yes" : "No"); /* DIEP0CTL, DIEPxCTL, DOEP0CTL, DOEPxCTL have same STALL layout */ volatile uint32_t *reg_ptr = IS_IN_ENDPOINT(addr) ? @@ -389,7 +389,7 @@ static void urb_to_fifo_1pkt(usbd_device *dev, usbd_urb *urb) size_t rem_len = transfer->length - transfer->transferred; if (!rem_len) { - LOGF_LN("No more data to send URB %"PRIu64" (endpoint 0x%"PRIx8") " + USBD_LOGF_LN(USB_VURB, "No more data to send URB %"PRIu64" (ep0x%"PRIx8") " "(intending ZLP?)", urb->id, transfer->ep_addr); return; } @@ -727,7 +727,7 @@ static void fifo_to_urb_1pkt(usbd_device *dev, usbd_urb *urb, uint16_t bcnt) if (bcnt < transfer->ep_size) { if (transfer->ep_type == USBD_EP_BULK) { - LOGF_LN("Short packet received for Bulk endpoint 0x%"PRIx8, + USBD_LOGF_LN(USB_VIO, "Short packet received for Bulk endpoint 0x%"PRIx8, transfer->ep_addr); if (transfer->flags & USBD_FLAG_SHORT_PACKET) { @@ -775,7 +775,7 @@ static void handle_rxflvl_interrupt(usbd_device *dev) [15] = "RESERVED_15" }; - LOGF_LN("GRXSTSP: rxstsp = %s, ep_num = %"PRIu8", bcnt = %"PRIu16, + USBD_LOGF_LN(USB_VIO, "GRXSTSP: %s, ep%"PRIu8", bcnt = %"PRIu16, map_pktsts[DWC_OTG_GRXSTSP_PKTSTS_GET(rxstsp)], ep_num, bcnt); #endif @@ -790,7 +790,7 @@ static void handle_rxflvl_interrupt(usbd_device *dev) } break; case DWC_OTG_GRXSTSP_PKTSTS_SETUP: { if (bcnt != 8) { - LOG_LN("SETUP packet in FIFO not equal to 8"); + USBD_LOG_LN(USB_VSETUP,"SETUP packet in FIFO not equal to 8"); break; } @@ -798,11 +798,13 @@ static void handle_rxflvl_interrupt(usbd_device *dev) uint32_t *io = (void *) setup_data; io[0] = REBASE(DWC_OTG_FIFO, 0); io[1] = REBASE(DWC_OTG_FIFO, 0); - LOGF_LN("bmRequestType: 0x%02"PRIx8, setup_data->bmRequestType); - LOGF_LN("bRequest: 0x%02"PRIx8, setup_data->bRequest); - LOGF_LN("wValue: 0x%04"PRIx16, setup_data->wValue); - LOGF_LN("wIndex: 0x%04"PRIx16, setup_data->wIndex); - LOGF_LN("wLength: %"PRIu16, setup_data->wLength); + USBD_LOGF_LN(USB_VSETUP, "SETUP:reqType 0x%02"PRIx8"; Request 0x%02"PRIx8 + ";Value 0x%04"PRIx16";Index 0x%04"PRIx16 + ";Length: %"PRIu16 + , setup_data->bmRequestType, setup_data->bRequest + , setup_data->wValue, setup_data->wIndex + , setup_data->wLength + ); } break; case DWC_OTG_GRXSTSP_PKTSTS_SETUP_COMP: { /* Enable Interrupt to receive the SETUP packet */ @@ -824,7 +826,7 @@ static void process_in_endpoint_interrupt(usbd_device *dev, uint8_t ep_num) if (REBASE(DWC_OTG_DIEPxINT, ep_num) & DWC_OTG_DIEPINT_EPDISD) { REBASE(DWC_OTG_DIEPxINT, ep_num) = DWC_OTG_DIEPINT_EPDISD; - LOGF_LN("Endpoint disabled 0x%"PRIx8, ep_addr); + USBD_LOGF_LN(USB_VIO, "ep0x%"PRIx8" disabled", ep_addr); } usbd_urb *urb = usbd_find_active_urb(dev, ep_addr); @@ -832,7 +834,7 @@ static void process_in_endpoint_interrupt(usbd_device *dev, uint8_t ep_num) if (REBASE(DWC_OTG_DIEPxINT, ep_num) & DWC_OTG_DIEPINT_XFRC) { REBASE(DWC_OTG_DIEPxINT, ep_num) = DWC_OTG_DIEPINT_XFRC; - LOGF_LN("Transfer Complete: endpoint 0x%"PRIx8, ep_addr); + USBD_LOGF_LN(USB_VIO, "Transfer Complete: ep0x%"PRIx8, ep_addr); if (!ep_num && urb != NULL && dev->private_data.ep0tsiz_pktcnt) { /* We are still sending data! */ @@ -871,7 +873,7 @@ static void process_in_endpoint_interrupt(usbd_device *dev, uint8_t ep_num) if (REBASE(DWC_OTG_DIEPxINT, ep_num) & DWC_OTG_DIEPINT_TXFE) { /* Send more data */ - LOGF_LN("Sending more data for endpoint 0x%"PRIx8, ep_addr); + USBD_LOGF_LN(USB_VIO2, "Sending more data for endpoint 0x%"PRIx8, ep_addr); if (urb != NULL) { /* As per doc, before writing to FIFO, we need to write to CTL register. @@ -883,7 +885,7 @@ static void process_in_endpoint_interrupt(usbd_device *dev, uint8_t ep_num) } if (REBASE(DWC_OTG_DIEPxINT, ep_num) & DWC_OTG_DIEPINT_ITTXFE) { - LOGF_LN("Data IN Token received when endpoint 0x%"PRIx8" FIFO was empty", + USBD_LOGF_LN(USB_VIO2, "Data IN Token received when ep0x%"PRIx8" FIFO was empty", ep_addr); REBASE(DWC_OTG_DIEPxINT, ep_num) = DWC_OTG_DIEPINT_ITTXFE; } @@ -901,13 +903,12 @@ static void process_out_endpoint_interrupt(usbd_device *dev, uint8_t ep_num) const uint8_t ep_addr = ep_num; if (REBASE(DWC_OTG_DOEPxINT, ep_num) & DWC_OTG_DOEPINT_EPDISD) { - LOGF_LN("Endpoint disabled 0x%"PRIx8, ep_addr); + USBD_LOGF_LN(USB_VIO, "ep0x%"PRIx8" disabled", ep_addr); REBASE(DWC_OTG_DOEPxINT, ep_num) = DWC_OTG_DOEPINT_EPDISD; } if (REBASE(DWC_OTG_DOEPxINT, ep_num) & DWC_OTG_DOEPINT_BBLERR) { - LOGF_LN("Received more data than expected on endpoint 0x%"PRIx8, - ep_addr); + USBD_LOGF_LN(USB_VIO, "Received more data than expected on ep0x%"PRIx8,ep_addr); usbd_urb *urb = usbd_find_active_urb(dev, ep_addr); REBASE(DWC_OTG_DOEPxINT, ep_num) = DWC_OTG_DOEPINT_BBLERR; premature_urb_complete(dev, urb, USBD_ERR_BABBLE); @@ -916,7 +917,7 @@ static void process_out_endpoint_interrupt(usbd_device *dev, uint8_t ep_num) if (REBASE(DWC_OTG_DOEPxINT, ep_num) & DWC_OTG_DOEPINT_XFRC) { REBASE(DWC_OTG_DOEPxINT, ep_num) = DWC_OTG_DOEPINT_XFRC; - LOGF_LN("Transfer Complete: endpoint 0x%"PRIx8, ep_addr); + USBD_LOGF_LN(USB_VIO, "Transfer Complete: ep0x%"PRIx8, ep_addr); usbd_urb *urb = usbd_find_active_urb(dev, ep_addr); if (!ep_num && urb != NULL && dev->private_data.ep0tsiz_pktcnt) { @@ -946,7 +947,7 @@ static void process_out_endpoint_interrupt(usbd_device *dev, uint8_t ep_num) } if (REBASE(DWC_OTG_DOEPxINT, ep_num) & DWC_OTG_DOEPINT_STUP) { - LOGF_LN("Setup phase done for endpoint 0x%"PRIx8, ep_addr); + USBD_LOGF_LN(USB_VSETUP, "Setup phase done for ep0x%"PRIx8, ep_addr); REBASE(DWC_OTG_DOEPxINT, ep_num) = DWC_OTG_DOEPINT_STUP; REBASE(DWC_OTG_DOEPxTSIZ, ep_num) |= DWC_OTG_DOEPTSIZ_STUPCNT_3; @@ -955,8 +956,7 @@ static void process_out_endpoint_interrupt(usbd_device *dev, uint8_t ep_num) if (REBASE(DWC_OTG_DOEPxINT, ep_num) & DWC_OTG_DOEPINT_OTEPDIS) { REBASE(DWC_OTG_DOEPxINT, ep_num) = DWC_OTG_DOEPINT_OTEPDIS; - LOGF_LN("Data OUT Token received when endpoint 0x%"PRIx8" was disable", - ep_addr); + USBD_LOGF_LN(USB_VIO, "Data OUT Token received when ep0x%"PRIx8" was disable", ep_addr); } } diff --git a/lib/usbd/class/usbd_msc.c b/lib/usbd/class/usbd_msc.c index 5b5d7d53..d9d342b0 100644 --- a/lib/usbd/class/usbd_msc.c +++ b/lib/usbd/class/usbd_msc.c @@ -26,6 +26,7 @@ #include #include #include "../usbd_private.h" +#include /* * TODO: @@ -92,6 +93,8 @@ struct sbc_sense_info { uint8_t ascq; }; + +#define USBD_MSC_SEC_SIZE 512 struct usb_msc_trans { struct usb_msc_cbw cbw; @@ -103,7 +106,7 @@ struct usb_msc_trans { uint32_t block_count; uint32_t current_block; - uint8_t msd_buf[512]; + uint8_t msd_buf[USBD_MSC_SEC_SIZE]; struct usb_msc_csw csw; }; @@ -257,7 +260,7 @@ static void scsi_read_capacity(usbd_msc *ms, enum trans_event event) { if (EVENT_CBW_VALID == event) { - uint32_t last_logical_addr = ms->backend->block_count - 1; + msc_lba_t last_logical_addr = usbd_msc_blocks(ms->backend)-1; trans->msd_buf[0] = last_logical_addr >> 24; trans->msd_buf[1] = 0xff & (last_logical_addr >> 16); trans->msd_buf[2] = 0xff & (last_logical_addr >> 8); @@ -273,6 +276,30 @@ static void scsi_read_capacity(usbd_msc *ms, } } + + +static +void scsi_read_format_capacities(usbd_msc *ms, + struct usb_msc_trans *trans, + enum trans_event event) +{ + if (EVENT_CBW_VALID == event) { + usb_msc_rfc_capacity_list_header* h = (usb_msc_rfc_capacity_list_header*)trans->msd_buf; + usb_msc_rfc_capacity_descriptor* descr = (usb_msc_rfc_capacity_descriptor*) (trans->msd_buf+sizeof(*h)); + + u24_assign(h->dummy, 0); + h->list_len = sizeof(*descr); + + msc_lba_t size = usbd_msc_blocks(ms->backend); + descr->blocks_count = HTONL(size); + descr->code = rfc_dc_Fomatted; + u24_assign(descr->block_size, USBD_MSC_SEC_SIZE); + + trans->bytes_to_send = sizeof(*h) + h->list_len; + set_sbc_status_good(ms); + } +} + static void fallback_format_unit(usbd_msc *ms, struct usb_msc_trans *trans) { uint32_t i; @@ -355,41 +382,160 @@ static void scsi_mode_sense_6(usbd_msc *ms, } } + + + +int usbd_scsi_inquiry_page(const usbd_msc_backend *self + //, usb_inquiry_cmd* cmd + , int vpd_page //* < \value -1 request standart iquiry page (EVPD=0) + , unsigned alloc_limit //* < TODO limited by sector size now, due use MCS sector buffer as buf + , void* buf //* < buffer for inquiry data fill to + ); + static void scsi_inquiry(usbd_msc *ms, struct usb_msc_trans *trans, enum trans_event event) { + const usbd_msc_backend* u = ms->backend; if (EVENT_CBW_VALID == event) { - uint8_t *buf = trans->cbw.CBWCB; - uint8_t evpd = 1 & buf[1]; + usb_inquiry_cmd* cmd = (usb_inquiry_cmd*)trans->cbw.CBWCB; + uint8_t evpd = cmd->evpd & 1; + unsigned alloc_len = NTOHS(cmd->alloc_len); + if (alloc_len > sizeof(trans->msd_buf)) + alloc_len = sizeof(trans->msd_buf); + int page; if (0 == evpd) { + page = -1; + } else { + page = cmd->page_code; + } + int len = usbd_scsi_inquiry_page(u, page, alloc_len, trans->msd_buf); + if (len > 0) { + trans->bytes_to_send = len; + trans->csw.dCSWDataResidue = len; + set_sbc_status_good(ms); + USBD_LOGF_LN(USB_VSETUP_MSC, "SCSI:INQUIRY page%3x ok", page); + } + else{ + /* Error */ + USBD_LOGF_LN(USB_VSETUP_MSC, "SCSI:INQUIRY page%3x fail", page); + trans->csw.bCSWStatus = USB_MSC_CSW_STATUS_FAILED; + set_sbc_status(ms, + SBC_SENSE_KEY_ILLEGAL_REQUEST, + SBC_ASC_INVALID_FIELD_IN_CDB, + SBC_ASCQ_NA); + } + } +} + +int usbd_scsi_inquiry_standart_page(const usbd_msc_backend *self, unsigned alloc_limit, void* buf); +int usbd_scsi_inquiry_evpd_supports(const usbd_msc_backend *self, unsigned alloc_limit, void* buf); +int usbd_scsi_inquiry_evpd_serial(const usbd_msc_backend *self, unsigned alloc_limit, void* buf); + +__attribute__((weak)) +int usbd_scsi_inquiry_page(const usbd_msc_backend *self + //, usb_inquiry_cmd* cmd + , int vpd_page //* < \value -1 request standart iquiry page (EVPD=0) + , unsigned alloc_limit //* < TODO limited by sector size now, due use MCS sector buffer as buf + , void* buf //* < buffer for inquiry data fill to + ) +{ + int res = 0; + if (self->inquiry_page != NULL) + res = self->inquiry_page(self, vpd_page, alloc_limit, buf); + if (res > 0) + return res; + + if (vpd_page < 0) + return usbd_scsi_inquiry_standart_page(self, alloc_limit, buf); + + switch (vpd_page){ + case scsi_vpd_Supported : + res = usbd_scsi_inquiry_evpd_supports(self, alloc_limit, buf); + break; + case scsi_vpd_Serial : + res = usbd_scsi_inquiry_evpd_serial(self, alloc_limit, buf); + break; +//* TODO page 83 - Demanded by SCSI reference!!! +// case scsi_vpd_DevIdentification : +// res = usbd_scsi_inquiry_evpd83(self, alloc_limit, buf); +// break; + default: return -1; + } + return res; +} + +__attribute__((weak)) +int usbd_scsi_inquiry_standart_page(const usbd_msc_backend *u, unsigned alloc_limit, void* dst) +{ + int res; size_t len; - trans->bytes_to_send = sizeof(_spc3_inquiry_response); - memcpy(trans->msd_buf, _spc3_inquiry_response, sizeof(_spc3_inquiry_response)); + uint8_t* buf = (uint8_t*)dst; + memcpy(buf, _spc3_inquiry_response, sizeof(_spc3_inquiry_response)); + res = sizeof(_spc3_inquiry_response); - len = strlen(ms->backend->vendor_id); + len = strlen(u->vendor_id); len = MIN(len, 8); - memcpy(&trans->msd_buf[8], ms->backend->vendor_id, len); + memcpy(&buf[8], u->vendor_id, len); - len = strlen(ms->backend->product_id); + len = strlen(u->product_id); len = MIN(len, 16); - memcpy(&trans->msd_buf[16], ms->backend->product_id, len); + memcpy(&buf[16], u->product_id, len); - len = strlen(ms->backend->product_rev); + len = strlen(u->product_rev); len = MIN(len, 4); - memcpy(&trans->msd_buf[32], ms->backend->product_rev, len); + memcpy(&buf[32], u->product_rev, len); - trans->csw.dCSWDataResidue = sizeof(_spc3_inquiry_response); + return res; +} - set_sbc_status_good(ms); - } else { - /* TODO: Add VPD 0x83 support */ - /* TODO: Add VPD 0x00 support */ - } +__attribute__((weak)) +const uint8_t usbd_scsi_inquiry_evpd_supports_Data[] += { + 0x00, + 0x00, + 0x00, + 2, + 0x00, + 0x80 +// 0x83 +}; + +__attribute__((weak)) +int usbd_scsi_inquiry_evpd_supports(const usbd_msc_backend *self, unsigned alloc_limit, void* buf) +{ + memcpy(buf, usbd_scsi_inquiry_evpd_supports_Data, sizeof(usbd_scsi_inquiry_evpd_supports_Data)); + return sizeof(usbd_scsi_inquiry_evpd_supports_Data); +} + +__attribute__((weak)) +const uint8_t usbd_scsi_inquiry_evpd_serial_Data[] += { + 0x00, + 0x80, + 0x00, + 16 + , ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' // dummy product serial + , ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' // dummy LUN serial +}; + +__attribute__((weak)) +int usbd_scsi_inquiry_evpd_serial(const usbd_msc_backend *self, unsigned alloc_limit, void* buf) +{ + const unsigned serial_size = sizeof(usbd_scsi_inquiry_evpd_serial_Data); + if ( (alloc_limit == 4) + ||(alloc_limit >= serial_size) + ) + { + memcpy(buf, usbd_scsi_inquiry_evpd_serial_Data, serial_size); + return serial_size; } + return -1; } + + static void scsi_command(usbd_msc *ms, struct usb_msc_trans *trans, enum trans_event event) @@ -406,6 +552,7 @@ static void scsi_command(usbd_msc *ms, trans->byte_count = 0; } + USBD_LOGF_LN(USB_VIO_MSC, "SCSI:cmd %x", trans->cbw.CBWCB[0]); switch (trans->cbw.CBWCB[0]) { case USB_MSC_SCSI_TEST_UNIT_READY: case USB_MSC_SCSI_SEND_DIAGNOSTIC: @@ -439,7 +586,11 @@ static void scsi_command(usbd_msc *ms, case USB_MSC_SCSI_WRITE_10: scsi_write_10(ms, trans, event); break; + case USB_MSC_SCSI_READ_FORMAT_CAPACITIES: + scsi_read_format_capacities(ms, trans, event); + break; default: + USBD_LOGF_LN(USB_VIO_MSC, "SCSI:cmd %x uncknown", trans->cbw.CBWCB[0]); set_sbc_status(ms, SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_COMMAND_OPERATION_CODE, SBC_ASCQ_NA); @@ -449,6 +600,10 @@ static void scsi_command(usbd_msc *ms, trans->csw.bCSWStatus = USB_MSC_CSW_STATUS_FAILED; break; } + + if (event == EVENT_NEED_STATUS){ + USBD_LOGF_LN(USB_VIO_MSC, "SCSI:status %x", trans->csw.bCSWStatus); + } } /*-- USB Mass Storage Layer --------------------------------------------------*/ @@ -791,18 +946,22 @@ bool usbd_msc_setup_ep0(usbd_msc *ms, const uint8_t value = USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE; if ((setup_data->bmRequestType & mask) == value) { + USBD_LOGF(USB_VSETUP, "USB:MSC:Req %x ", (int)setup_data->bRequest); switch (setup_data->bRequest) { case USB_MSC_REQ_BULK_ONLY_RESET: + USBD_LOG(USB_VSETUP,"BULK_ONLY_RESET\n"); /* Do any special reset code here. */ usbd_ep0_transfer(dev, setup_data, NULL, 0, NULL); return true; case USB_MSC_REQ_GET_MAX_LUN: { + USBD_LOG(USB_VSETUP,"MAX_LUN 0\n"); /* Return the number of LUNs. We use 0. */ static const uint8_t res = 0; usbd_ep0_transfer(dev, setup_data, (void *) &res, sizeof(res), NULL); return true; - }} + } + }//switch (setup_data->bRequest) } return false; diff --git a/lib/usbd/usbd.c b/lib/usbd/usbd.c index cd382b91..8cb7d32d 100644 --- a/lib/usbd/usbd.c +++ b/lib/usbd/usbd.c @@ -210,3 +210,10 @@ usbd_speed usbd_get_speed(usbd_device *dev) /**@}*/ +#if defined(USBD_DEBUG) +void usbd_log_call(const char *fname){ + USBD_LOG(USB_VALL, "inside "); + USBD_LOG_LN(USB_VALL, fname); +} +#endif + diff --git a/lib/usbd/usbd_private.h b/lib/usbd/usbd_private.h index dc6cc74d..a6b24d6a 100644 --- a/lib/usbd/usbd_private.h +++ b/lib/usbd/usbd_private.h @@ -211,23 +211,73 @@ struct usbd_backend { #endif }; +#define USB_VALL 0 +#define USB_VFAIL 1 +#define USB_VINFO 2 +#define USB_VNOTE 3 +#define USB_VDEBUG 4 +#define USB_VTRACE 5 + +#define USB_VCALL USB_VTRACE +#define USB_VIO USB_VDEBUG +#define USB_VIO2 USB_VTRACE +#define USB_VSETUP USB_VDEBUG +#define USB_VSETUP_MSC USB_VDEBUG +#define USB_VURB USB_VDEBUG +#define USB_VURBQUE USB_VTRACE +#define USB_VURBFAIL USB_VDEBUG +#define USB_VIO_MSC USB_VDEBUG + +#if !defined(USBD_DEBUG) +# define USBD_DEBUG USB_VDEBUG +#endif + +#define NEW_LINE "\n" + #if defined(USBD_DEBUG) extern void usbd_log_puts(const char *arg); extern void usbd_log_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); +extern void usbd_log_call(const char *fname); + # include -# define LOG(str) usbd_log_puts(str) -# define LOGF(fmt,...) usbd_log_printf(fmt, ##__VA_ARGS__) +# define USBD_STR(s) s +# define USBD_LOG(level, str) if (level <= USBD_DEBUG) usbd_log_puts(str) +# define USBD_LOGF(level, fmt,...) if (level <= USBD_DEBUG) usbd_log_printf(fmt, ##__VA_ARGS__) + +# define USBD_LOG_LN(level, str) USBD_LOG(level, str); USBD_LOG(level, NEW_LINE ); +//# define USBD_LOGF_LN(level, fmt,...) USBD_LOGF(level, fmt, __VA_ARGS__); USBD_LOG(level, NEW_LINE ); +# define USBD_LOGF_LN(level, fmt,...) USBD_LOGF(level, USBD_STR(fmt)NEW_LINE, __VA_ARGS__) + +# if USBD_DEBUG >= USB_VCALL +# define USBD_LOG_CALL usbd_log_call(__func__); +# else +# define USBD_LOG_CALL +# endif + +//temps for backport +# define LOG(str) USBD_LOG(USB_VALL, str) +# define LOGF(fmt,...) USBD_LOGF(USB_VALL, fmt, __VA_ARGS__) + +# define LOG_LN(str) USBD_LOG_LN(USB_VALL, str) +# define LOGF_LN(fmt,...) USBD_LOGF_LN(USB_VALL, fmt, __VA_ARGS__) + +# define LOG_CALL USBD_LOG_CALL + #else +# define USBD_LOG(level, str) +# define USBD_LOGF(level, fmt,...) +# define USBD_LOG_LN(level, str) +# define USBD_LOGF_LN(level, fmt,...) +# define USBD_LOG_CALL + # define LOG(str) # define LOGF(fmt,...) +# define LOG_LN(str) +# define LOGF_LN(fmt,...) +# define LOG_CALL #endif -#define NEW_LINE "\n" -#define LOG_LN(str) LOG(str); LOG(NEW_LINE) -#define LOGF_LN(fmt,...) LOGF(fmt, __VA_ARGS__); LOG(NEW_LINE) -#define LOG_CALL LOG("inside "); LOG_LN(__func__); - #define IS_URB_ID_INVALID(urb_id) ((urb_id) == USBD_INVALID_URB_ID) #define IS_URB_INVALID(urb) IS_URB_ID_INVALID((urb)->id) diff --git a/lib/usbd/usbd_transfer.c b/lib/usbd/usbd_transfer.c index fccc0d22..1e7a7bfa 100644 --- a/lib/usbd/usbd_transfer.c +++ b/lib/usbd/usbd_transfer.c @@ -177,7 +177,7 @@ static void queue_item_append(struct usbd_urb_queue *queue, usbd_urb *urb) queue->tail = urb; } else { /* Problem! */ - LOGF_LN("URB Queue %p corrupt", queue); + USBD_LOGF_LN(USB_VURBFAIL, "URB Queue %p corrupt", queue); queue->head = queue->tail = urb; } } @@ -298,8 +298,7 @@ usbd_urb_id usbd_transfer_submit(usbd_device *dev, if (transfer->ep_type == USBD_EP_CONTROL) { if (!ENDPOINT_NUMBER(transfer->ep_addr) && !ctrl_ep0_size_acceptable(transfer->ep_size)) { - LOGF_LN("Invalid control endpoint size %"PRIu16" for EP0", - transfer->ep_size); + USBD_LOGF_LN(USB_VURBFAIL, "Invalid control endpoint size %"PRIu16" for EP0", transfer->ep_size); TRANSFER_INVALID(dev, transfer); return USBD_INVALID_URB_ID; } @@ -321,6 +320,8 @@ usbd_urb_id usbd_transfer_submit(usbd_device *dev, (dev->last_poll + MS2US(transfer->timeout)) : 0; #endif + bool to_active = !dev->urbs.force_all_new_urb_to_waiting && + try_alloc_ep_for_urb(dev, urb); #if defined(USBD_DEBUG) const char *ep_type_map_str[] = { @@ -330,19 +331,15 @@ usbd_urb_id usbd_transfer_submit(usbd_device *dev, [USBD_EP_BULK] = "Bulk", }; - LOGF_LN("Created URB %"PRIu64": %s %s %"PRIu8": data=%p, length=%u", + USBD_LOGF_LN(USB_VURB, "Created URB %"PRIu64": %s %s %"PRIu8": data=%p, length=%u is %s", urb->id, ep_type_map_str[urb->transfer.ep_type], IS_IN_ENDPOINT(urb->transfer.ep_addr) ? "IN" : "OUT", ENDPOINT_NUMBER(urb->transfer.ep_addr), - urb->transfer.buffer, urb->transfer.length); + urb->transfer.buffer, urb->transfer.length + , ( (to_active) ? "active" : "waiting" ) + ); #endif - bool to_active = !dev->urbs.force_all_new_urb_to_waiting && - try_alloc_ep_for_urb(dev, urb); - - LOGF_LN("[new] URB id=%"PRIu64" is %s", urb->id, - to_active ? "active" : "waiting"); - if (to_active) { mark_ep_as_free(dev, urb->transfer.ep_addr, false); queue_item_append(&dev->urbs.active, urb); @@ -365,7 +362,7 @@ static void urb_callback(usbd_device *dev, usbd_urb *urb, { LOG_CALL - LOGF_LN("URB %"PRIu64" transfer status = %s", urb->id, + USBD_LOGF_LN(USB_VURB, "URB %"PRIu64" transfer status = %s", urb->id, stringify_transfer_status(status)); /* callback provided */ @@ -388,7 +385,7 @@ bool usbd_transfer_cancel(usbd_device *dev, usbd_urb_id urb_id) usbd_urb *urb, *prev; if (IS_URB_ID_INVALID(urb_id)) { - LOG_LN("invalid urb id passed to transfer_cancel"); + USBD_LOG_LN(USB_VURBFAIL, "invalid urb id passed to transfer_cancel"); return false; } @@ -421,7 +418,7 @@ bool usbd_transfer_cancel(usbd_device *dev, usbd_urb_id urb_id) return true; } - LOGF_LN("WARN: urb with id = %"PRIu64" not found", urb_id); + USBD_LOGF_LN(USB_VURBFAIL, "WARN: urb with id = %"PRIu64" not found", urb_id); return false; } @@ -472,7 +469,7 @@ unsigned usbd_transfer_cancel_ep(usbd_device *dev, uint8_t ep_addr) void usbd_urb_schedule(usbd_device *dev) { if (dev->urbs.force_all_new_urb_to_waiting) { - LOG_LN("Could not schedule (force_all_new_urb_to_waiting = true)"); + USBD_LOG_LN(USB_VURBFAIL, "Could not schedule (force_all_new_urb_to_waiting = true)"); return; } @@ -489,7 +486,7 @@ void usbd_urb_schedule(usbd_device *dev) urb = queue_item_detach(&dev->urbs.waiting, prev, tmp); queue_item_append(&dev->urbs.active, tmp); - LOGF_LN("[waiting] URB id=%"PRIu64" is now active", tmp->id); + USBD_LOGF_LN(USB_VURB, "[waiting] URB id=%"PRIu64" is now active", tmp->id); dev->backend->urb_submit(dev, tmp); } } @@ -516,7 +513,7 @@ static void detach_from_active(usbd_device *dev, usbd_urb *item) return; } - LOGF_LN("WARNING: Found not find URB %"PRIu64" in active list to detach it", + USBD_LOGF_LN(USB_VURBFAIL, "WARNING: Found not find URB %"PRIu64" in active list to detach it", urb->id); } @@ -547,8 +544,7 @@ usbd_urb *usbd_find_active_urb(usbd_device *dev, uint8_t ep_addr) { usbd_urb *urb = NULL; - LOGF_LN("Searching for URB which is active and has " - "ep_addr=0x%"PRIx8, ep_addr); + USBD_LOGF_LN(USB_VURBQUE, "Searching URB on ep0x%"PRIx8, ep_addr); for (urb = dev->urbs.active.head; urb != NULL; urb = urb->next) { if (urb->transfer.ep_addr == ep_addr) { @@ -556,8 +552,7 @@ usbd_urb *usbd_find_active_urb(usbd_device *dev, uint8_t ep_addr) } } - LOGF_LN("Unable to find the current processing URB for " - "endpoint 0x%"PRIx8, ep_addr); + USBD_LOGF_LN(USB_VURB,"Unable to find the current processing URB for ep0x%"PRIx8, ep_addr); return NULL; }