1beacf11bSopenharmony_ci/* ---------------------------------------------------------------------------- 2beacf11bSopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2015-2019. All rights reserved. 3beacf11bSopenharmony_ci * Description: LiteOS USB Driver Mass Storage Protocol 4beacf11bSopenharmony_ci * Author: huangjieliang 5beacf11bSopenharmony_ci * Create: 2015-07-30 6beacf11bSopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 7beacf11bSopenharmony_ci * are permitted provided that the following conditions are met: 8beacf11bSopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of 9beacf11bSopenharmony_ci * conditions and the following disclaimer. 10beacf11bSopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list 11beacf11bSopenharmony_ci * of conditions and the following disclaimer in the documentation and/or other materials 12beacf11bSopenharmony_ci * provided with the distribution. 13beacf11bSopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used 14beacf11bSopenharmony_ci * to endorse or promote products derived from this software without specific prior written 15beacf11bSopenharmony_ci * permission. 16beacf11bSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17beacf11bSopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 18beacf11bSopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19beacf11bSopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20beacf11bSopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21beacf11bSopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22beacf11bSopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23beacf11bSopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24beacf11bSopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25beacf11bSopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26beacf11bSopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27beacf11bSopenharmony_ci * --------------------------------------------------------------------------- */ 28beacf11bSopenharmony_ci/* ---------------------------------------------------------------------------- 29beacf11bSopenharmony_ci * Notice of Export Control Law 30beacf11bSopenharmony_ci * =============================================== 31beacf11bSopenharmony_ci * Huawei LiteOS may be subject to applicable export control laws and regulations, which might 32beacf11bSopenharmony_ci * include those applicable to Huawei LiteOS of U.S. and the country in which you are located. 33beacf11bSopenharmony_ci * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such 34beacf11bSopenharmony_ci * applicable export control laws and regulations. 35beacf11bSopenharmony_ci * --------------------------------------------------------------------------- */ 36beacf11bSopenharmony_ci 37beacf11bSopenharmony_ci#include <linux/wait.h> 38beacf11bSopenharmony_ci#include "gadget/f_mass_storage.h" 39beacf11bSopenharmony_ci#include "implementation/global_implementation.h" 40beacf11bSopenharmony_ci 41beacf11bSopenharmony_ci#ifdef __cplusplus 42beacf11bSopenharmony_ci#if __cplusplus 43beacf11bSopenharmony_ciextern "C" { 44beacf11bSopenharmony_ci#endif /* __cplusplus */ 45beacf11bSopenharmony_ci#endif /* __cplusplus */ 46beacf11bSopenharmony_ci 47beacf11bSopenharmony_ci#undef USB_DEBUG_VAR 48beacf11bSopenharmony_ci#define USB_DEBUG_VAR g_fmass_debug 49beacf11bSopenharmony_ci#ifdef LOSCFG_USB_DEBUG 50beacf11bSopenharmony_cistatic int g_fmass_debug = 0; 51beacf11bSopenharmony_ci 52beacf11bSopenharmony_civoid fmass_debug_func(int level) 53beacf11bSopenharmony_ci{ 54beacf11bSopenharmony_ci g_fmass_debug = level; 55beacf11bSopenharmony_ci PRINTK("The level of usb fmass debug is %d\n", level); 56beacf11bSopenharmony_ci} 57beacf11bSopenharmony_ciDEBUG_MODULE(fmass, fmass_debug_func); 58beacf11bSopenharmony_ci#endif 59beacf11bSopenharmony_ci 60beacf11bSopenharmony_ciextern void __init_waitqueue_head(wait_queue_head_t *wait); 61beacf11bSopenharmony_ciextern void __wake_up_interruptible(wait_queue_head_t *wait); 62beacf11bSopenharmony_ci 63beacf11bSopenharmony_ciint usbdev_mass_initialize(struct module *mod, int n, void *arg); 64beacf11bSopenharmony_ci 65beacf11bSopenharmony_cistatic devclass_t g_fmass_devclass; 66beacf11bSopenharmony_cistatic struct mass_softc *g_fmass = NULL; 67beacf11bSopenharmony_ci 68beacf11bSopenharmony_cistatic const driver_t g_fmass_driver = 69beacf11bSopenharmony_ci{ 70beacf11bSopenharmony_ci .name = "fmass", 71beacf11bSopenharmony_ci .methods = NULL, 72beacf11bSopenharmony_ci .size = sizeof(struct mass_softc), 73beacf11bSopenharmony_ci}; 74beacf11bSopenharmony_ci 75beacf11bSopenharmony_ciDRIVER_MODULE(fmass, simple, g_fmass_driver, g_fmass_devclass, usbdev_mass_initialize, 0); 76beacf11bSopenharmony_ci 77beacf11bSopenharmony_cistatic int usbclass_mass_bind(struct usbdevclass_driver_s *driver, struct usbdev_s *dev); 78beacf11bSopenharmony_cistatic int usbclass_mass_unbind(struct usbdevclass_driver_s *driver, struct usbdev_s *dev); 79beacf11bSopenharmony_cistatic int usbclass_mass_setup(struct usbdevclass_driver_s *driver, struct usbdev_s *dev, 80beacf11bSopenharmony_ci const struct usb_device_request *ctrl, uint8_t *dataout, size_t outlen); 81beacf11bSopenharmony_cistatic void usbclass_mass_disconnect(struct usbdevclass_driver_s *driver, struct usbdev_s *dev); 82beacf11bSopenharmony_ci 83beacf11bSopenharmony_ci/* USB driver operations */ 84beacf11bSopenharmony_ci 85beacf11bSopenharmony_cistatic const struct usbdevclass_driverops_s g_mass_driverops = 86beacf11bSopenharmony_ci{ 87beacf11bSopenharmony_ci usbclass_mass_bind, 88beacf11bSopenharmony_ci usbclass_mass_unbind, 89beacf11bSopenharmony_ci usbclass_mass_setup, 90beacf11bSopenharmony_ci usbclass_mass_disconnect, 91beacf11bSopenharmony_ci NULL, 92beacf11bSopenharmony_ci NULL 93beacf11bSopenharmony_ci}; 94beacf11bSopenharmony_ci 95beacf11bSopenharmony_cistatic int fmass_thread_init(struct mass_dev_s *fmass, struct usbdev_s *dev); 96beacf11bSopenharmony_cistatic void fmass_main_thread_signal(struct mass_dev_s *fmass, fmass_task_state state); 97beacf11bSopenharmony_cistatic void fmass_task_change_state(struct mass_dev_s *fmass, fmass_task_state new_state); 98beacf11bSopenharmony_ci 99beacf11bSopenharmony_cistatic int fmass_dev_open(struct mass_dev_s *fmass); 100beacf11bSopenharmony_cistatic int fmass_dev_close(struct mass_dev_s *fmass); 101beacf11bSopenharmony_cistatic void fmass_dev_capacity(struct mass_dev_s *fmass); 102beacf11bSopenharmony_ci 103beacf11bSopenharmony_cistatic size_t fmass_dev_read(struct mass_dev_s *fmass, 104beacf11bSopenharmony_ci uint8_t *buffer, 105beacf11bSopenharmony_ci size_t stsector, 106beacf11bSopenharmony_ci uint32_t nsectors); 107beacf11bSopenharmony_ci 108beacf11bSopenharmony_cistatic size_t fmass_dev_write(struct mass_dev_s *fmass, 109beacf11bSopenharmony_ci uint8_t *buffer, 110beacf11bSopenharmony_ci size_t stsector, 111beacf11bSopenharmony_ci uint32_t nsectors); 112beacf11bSopenharmony_ci 113beacf11bSopenharmony_cistatic void fmass_report_usb_status(struct mass_dev_s *fmass); 114beacf11bSopenharmony_cistatic void fmass_notify_report(struct mass_dev_s *fmass, int status); 115beacf11bSopenharmony_ci 116beacf11bSopenharmony_ci#define fmass_wait_intr(fm, cond, tm) \ 117beacf11bSopenharmony_ci wait_event_interruptible_timeout((((struct mass_dev_s *)fm)->xfer_wait), cond, tm) 118beacf11bSopenharmony_ci 119beacf11bSopenharmony_ci#define fmass_wakeup(fm) \ 120beacf11bSopenharmony_ci wake_up_interruptible(&(((struct mass_dev_s *)fm)->xfer_wait)) 121beacf11bSopenharmony_ci 122beacf11bSopenharmony_cistatic const char *g_mass_device_type[] = 123beacf11bSopenharmony_ci{ 124beacf11bSopenharmony_ci "/dev/mmcblk0p", 125beacf11bSopenharmony_ci "/dev/mmcblk1p", 126beacf11bSopenharmony_ci "/dev/uramp", 127beacf11bSopenharmony_ci}; 128beacf11bSopenharmony_ci 129beacf11bSopenharmony_cistruct fmass_notify_cb 130beacf11bSopenharmony_ci{ 131beacf11bSopenharmony_ci struct fmass_notify notify[MAX_NOFIFY_NUM]; 132beacf11bSopenharmony_ci struct mtx notify_mtx; 133beacf11bSopenharmony_ci bool init; 134beacf11bSopenharmony_ci} g_notify = { .notify_mtx = PTHREAD_MUTEX_INITIALIZER, .init = false }; 135beacf11bSopenharmony_ci 136beacf11bSopenharmony_cistatic inline void fmass_notify_init(void) 137beacf11bSopenharmony_ci{ 138beacf11bSopenharmony_ci mtx_lock(&g_notify.notify_mtx); 139beacf11bSopenharmony_ci if (g_notify.init == false) 140beacf11bSopenharmony_ci { 141beacf11bSopenharmony_ci g_notify.init = true; 142beacf11bSopenharmony_ci (void)memset_s(g_notify.notify, sizeof(struct fmass_notify) * MAX_NOFIFY_NUM, 143beacf11bSopenharmony_ci 0, sizeof(struct fmass_notify) * MAX_NOFIFY_NUM); 144beacf11bSopenharmony_ci } 145beacf11bSopenharmony_ci mtx_unlock(&g_notify.notify_mtx); 146beacf11bSopenharmony_ci} 147beacf11bSopenharmony_ci 148beacf11bSopenharmony_ci#ifdef LOSCFG_DRIVERS_USB3_DEVICE_CONTROLLER 149beacf11bSopenharmony_ci#define FMASS_MAX_PACKET_SIZE 0x0400 150beacf11bSopenharmony_ci#else 151beacf11bSopenharmony_ci#define FMASS_MAX_PACKET_SIZE 0x0200 152beacf11bSopenharmony_ci#endif 153beacf11bSopenharmony_ci 154beacf11bSopenharmony_ci#define DEIVICE_VENDOR_ID 0x0525 155beacf11bSopenharmony_ci#define DEIVICE_PRODUCT_ID 0xa4a5 156beacf11bSopenharmony_ci#define DEIVICE_VERSION 0x0100 157beacf11bSopenharmony_ci 158beacf11bSopenharmony_cistatic const struct usb_device_descriptor g_fmass_device_desc = 159beacf11bSopenharmony_ci{ 160beacf11bSopenharmony_ci .bLength = sizeof(struct usb_device_descriptor), 161beacf11bSopenharmony_ci .bDescriptorType = UDESC_DEVICE, 162beacf11bSopenharmony_ci HSETW(.bcdUSB, UD_BCD_USB), /* USB version 0x0200 */ 163beacf11bSopenharmony_ci .bDeviceClass = UDCLASS_IN_INTERFACE, 164beacf11bSopenharmony_ci .bDeviceSubClass = 0, 165beacf11bSopenharmony_ci .bDeviceProtocol = 0, 166beacf11bSopenharmony_ci .bMaxPacketSize = UD_USB_MPS, 167beacf11bSopenharmony_ci HSETW(.idVendor, DEIVICE_VENDOR_ID), /* vendor */ 168beacf11bSopenharmony_ci HSETW(.idProduct, DEIVICE_PRODUCT_ID), /* product */ 169beacf11bSopenharmony_ci HSETW(.bcdDevice, 0x0318), /* device version */ 170beacf11bSopenharmony_ci .iManufacturer = 0, 171beacf11bSopenharmony_ci .iProduct = 0, 172beacf11bSopenharmony_ci .iSerialNumber = 0, 173beacf11bSopenharmony_ci .bNumConfigurations = 1, 174beacf11bSopenharmony_ci}; 175beacf11bSopenharmony_ci 176beacf11bSopenharmony_cistruct fmass_config_desc 177beacf11bSopenharmony_ci{ 178beacf11bSopenharmony_ci struct usb_config_descriptor confd; 179beacf11bSopenharmony_ci struct usb_interface_descriptor ifcd; 180beacf11bSopenharmony_ci struct usb_endpoint_descriptor iepd; 181beacf11bSopenharmony_ci#ifdef LOSCFG_DRIVERS_USB3_DEVICE_CONTROLLER 182beacf11bSopenharmony_ci struct usb_endpoint_ss_comp_descriptor icompd; 183beacf11bSopenharmony_ci#endif 184beacf11bSopenharmony_ci struct usb_endpoint_descriptor oepd; 185beacf11bSopenharmony_ci#ifdef LOSCFG_DRIVERS_USB3_DEVICE_CONTROLLER 186beacf11bSopenharmony_ci struct usb_endpoint_ss_comp_descriptor ocompd; 187beacf11bSopenharmony_ci#endif 188beacf11bSopenharmony_ci} __packed; 189beacf11bSopenharmony_ci 190beacf11bSopenharmony_cistatic struct fmass_config_desc g_fmass_confd = 191beacf11bSopenharmony_ci{ 192beacf11bSopenharmony_ci .confd = 193beacf11bSopenharmony_ci { 194beacf11bSopenharmony_ci .bLength = sizeof(struct usb_config_descriptor), 195beacf11bSopenharmony_ci .bDescriptorType = UDESC_CONFIG, 196beacf11bSopenharmony_ci HSETW(.wTotalLength, sizeof(g_fmass_confd)), 197beacf11bSopenharmony_ci .bNumInterface = 1, 198beacf11bSopenharmony_ci .bConfigurationValue = 1, 199beacf11bSopenharmony_ci .iConfiguration = 0, 200beacf11bSopenharmony_ci .bmAttributes = UC_SELF_POWERED | UC_BUS_POWERED, 201beacf11bSopenharmony_ci .bMaxPower = 1 /* max power */ 202beacf11bSopenharmony_ci }, 203beacf11bSopenharmony_ci .ifcd = 204beacf11bSopenharmony_ci { 205beacf11bSopenharmony_ci .bLength = sizeof(struct usb_interface_descriptor), 206beacf11bSopenharmony_ci .bDescriptorType = UDESC_INTERFACE, 207beacf11bSopenharmony_ci .bInterfaceNumber = 0, 208beacf11bSopenharmony_ci .bAlternateSetting = 0, 209beacf11bSopenharmony_ci .bNumEndpoints = 2, 210beacf11bSopenharmony_ci .bInterfaceClass = UICLASS_MASS, 211beacf11bSopenharmony_ci .bInterfaceSubClass = UISUBCLASS_SCSI, 212beacf11bSopenharmony_ci .bInterfaceProtocol = UIPROTO_MASS_BULK, 213beacf11bSopenharmony_ci .iInterface = 1 214beacf11bSopenharmony_ci }, 215beacf11bSopenharmony_ci .iepd = 216beacf11bSopenharmony_ci { 217beacf11bSopenharmony_ci .bLength = sizeof(struct usb_endpoint_descriptor), 218beacf11bSopenharmony_ci .bDescriptorType = UDESC_ENDPOINT, 219beacf11bSopenharmony_ci .bEndpointAddress = UE_DIR_IN, 220beacf11bSopenharmony_ci .bmAttributes = UE_BULK, 221beacf11bSopenharmony_ci HSETW(.wMaxPacketSize, FMASS_MAX_PACKET_SIZE), 222beacf11bSopenharmony_ci .bInterval = 0 223beacf11bSopenharmony_ci }, 224beacf11bSopenharmony_ci#ifdef LOSCFG_DRIVERS_USB3_DEVICE_CONTROLLER 225beacf11bSopenharmony_ci .icompd = 226beacf11bSopenharmony_ci { 227beacf11bSopenharmony_ci .bLength = 6, 228beacf11bSopenharmony_ci .bDescriptorType = 0x30, 229beacf11bSopenharmony_ci .bMaxBurst = 0xf, 230beacf11bSopenharmony_ci .bmAttributes = 0, 231beacf11bSopenharmony_ci .wBytesPerInterval = {0} 232beacf11bSopenharmony_ci }, 233beacf11bSopenharmony_ci#endif 234beacf11bSopenharmony_ci .oepd = 235beacf11bSopenharmony_ci { 236beacf11bSopenharmony_ci .bLength = sizeof(struct usb_endpoint_descriptor), 237beacf11bSopenharmony_ci .bDescriptorType = UDESC_ENDPOINT, 238beacf11bSopenharmony_ci .bEndpointAddress = UE_DIR_OUT, 239beacf11bSopenharmony_ci .bmAttributes = UE_BULK, 240beacf11bSopenharmony_ci HSETW(.wMaxPacketSize, FMASS_MAX_PACKET_SIZE), 241beacf11bSopenharmony_ci .bInterval = 0 242beacf11bSopenharmony_ci }, 243beacf11bSopenharmony_ci#ifdef LOSCFG_DRIVERS_USB3_DEVICE_CONTROLLER 244beacf11bSopenharmony_ci .ocompd = 245beacf11bSopenharmony_ci { 246beacf11bSopenharmony_ci .bLength = 6, 247beacf11bSopenharmony_ci .bDescriptorType = 0x30, 248beacf11bSopenharmony_ci .bMaxBurst = 0xf, 249beacf11bSopenharmony_ci .bmAttributes = 0, 250beacf11bSopenharmony_ci .wBytesPerInterval = {0} 251beacf11bSopenharmony_ci }, 252beacf11bSopenharmony_ci#endif 253beacf11bSopenharmony_ci}; 254beacf11bSopenharmony_ci 255beacf11bSopenharmony_ci#define DT_STRING_ID_LEN 4 256beacf11bSopenharmony_cistatic const char g_dt_string_id[DT_STRING_ID_LEN] = 257beacf11bSopenharmony_ci{ 258beacf11bSopenharmony_ci DT_STRING_ID_LEN, 259beacf11bSopenharmony_ci UDESC_STRING, 260beacf11bSopenharmony_ci 0x09, 0x04, 261beacf11bSopenharmony_ci}; 262beacf11bSopenharmony_ci 263beacf11bSopenharmony_ci#define DT_STRING_VID_LEN 16 264beacf11bSopenharmony_cistatic const char g_dt_string_vid[DT_STRING_VID_LEN] = 265beacf11bSopenharmony_ci{ 266beacf11bSopenharmony_ci DT_STRING_VID_LEN, 267beacf11bSopenharmony_ci UDESC_STRING, 268beacf11bSopenharmony_ci 'D', 0, 'W', 0, 'C', 0, '-', 0, 'O', 0, 'T', 0, 'G', 0 269beacf11bSopenharmony_ci}; 270beacf11bSopenharmony_ci 271beacf11bSopenharmony_ci#define DT_STRING_PID_LEN 16 272beacf11bSopenharmony_cistatic const char g_dt_string_pid[DT_STRING_PID_LEN] = 273beacf11bSopenharmony_ci{ 274beacf11bSopenharmony_ci DT_STRING_PID_LEN, 275beacf11bSopenharmony_ci UDESC_STRING, 276beacf11bSopenharmony_ci 'M', 0, 8, 0, '-', 0, 'C', 0, 'H', 0, 'I', 0, 'P', 0 277beacf11bSopenharmony_ci 278beacf11bSopenharmony_ci}; 279beacf11bSopenharmony_ci 280beacf11bSopenharmony_ci#define DT_STRING_SERIAL_LEN 18 281beacf11bSopenharmony_cistatic const char g_dt_string_serial[DT_STRING_SERIAL_LEN] = 282beacf11bSopenharmony_ci{ 283beacf11bSopenharmony_ci DT_STRING_SERIAL_LEN, 284beacf11bSopenharmony_ci UDESC_STRING, 285beacf11bSopenharmony_ci '2', 0, '0', 0, '1', 0, '5', 0, '0', 0, '7', 0, '3', 0, '0', 0 286beacf11bSopenharmony_ci}; 287beacf11bSopenharmony_ci 288beacf11bSopenharmony_cistatic char g_dt_string_buf[40] = 289beacf11bSopenharmony_ci{ 290beacf11bSopenharmony_ci 0x28, 3, 0x4d, 0, 0x61, 0, 0x73, 0, 0x73, 0, 291beacf11bSopenharmony_ci 0x20, 0, 0x53, 0, 0x74, 0, 0x6f, 0, 0x72, 0, 292beacf11bSopenharmony_ci 0x61, 0, 0x67, 0, 0x65, 0, 0x20, 0, 0x47, 0, 293beacf11bSopenharmony_ci 0x61, 0, 0x64, 0, 0x67, 0, 0x65, 0, 0x74, 0 294beacf11bSopenharmony_ci}; 295beacf11bSopenharmony_ci 296beacf11bSopenharmony_ciinline static bool taskstate_match(struct mass_dev_s *fmass, fmass_task_state tarstate) 297beacf11bSopenharmony_ci{ 298beacf11bSopenharmony_ci return fmass->task_state & tarstate; 299beacf11bSopenharmony_ci} 300beacf11bSopenharmony_ci 301beacf11bSopenharmony_ciinline static bool taskstate_unmatch(struct mass_dev_s *fmass, fmass_task_state tarstate) 302beacf11bSopenharmony_ci{ 303beacf11bSopenharmony_ci return (!(fmass->task_state & tarstate)); 304beacf11bSopenharmony_ci} 305beacf11bSopenharmony_ci 306beacf11bSopenharmony_cistatic int fmass_device_status(struct mass_dev_s *fmass) 307beacf11bSopenharmony_ci{ 308beacf11bSopenharmony_ci return fmass->dev_status; 309beacf11bSopenharmony_ci} 310beacf11bSopenharmony_ci 311beacf11bSopenharmony_cistatic void fmass_handle_bulkin_callback(struct usbdev_ep_s *ep, 312beacf11bSopenharmony_ci struct usbdev_req_s *req) 313beacf11bSopenharmony_ci{ 314beacf11bSopenharmony_ci struct mass_dev_s *fmass = (struct mass_dev_s *)(ep->priv); 315beacf11bSopenharmony_ci if (taskstate_match(fmass, FMASS_TASK_REQ_DATA_PHASE)) 316beacf11bSopenharmony_ci { 317beacf11bSopenharmony_ci fmass_task_change_state(fmass, FMASS_TASK_DONE_DATA_PHASE); 318beacf11bSopenharmony_ci } 319beacf11bSopenharmony_ci else if (taskstate_match(fmass, FMASS_TASK_REQ_STATUS_PHASE)) 320beacf11bSopenharmony_ci { 321beacf11bSopenharmony_ci fmass_task_change_state(fmass, FMASS_TASK_DONE_STATUS_PHASE); 322beacf11bSopenharmony_ci } 323beacf11bSopenharmony_ci fmass_wakeup(fmass); 324beacf11bSopenharmony_ci} 325beacf11bSopenharmony_ci 326beacf11bSopenharmony_cistatic void fmass_handle_bulkout_callback(struct usbdev_ep_s *ep, 327beacf11bSopenharmony_ci struct usbdev_req_s *req) 328beacf11bSopenharmony_ci{ 329beacf11bSopenharmony_ci struct mass_dev_s *fmass = (struct mass_dev_s *)(ep->priv); 330beacf11bSopenharmony_ci if (taskstate_match(fmass, FMASS_TASK_REQ_COMMAND_PHASE)) 331beacf11bSopenharmony_ci { 332beacf11bSopenharmony_ci fmass_task_change_state(fmass, FMASS_TASK_DONE_COMMAND_PHASE); 333beacf11bSopenharmony_ci } 334beacf11bSopenharmony_ci else if (taskstate_match(fmass, FMASS_TASK_REQ_DATA_PHASE)) 335beacf11bSopenharmony_ci { 336beacf11bSopenharmony_ci fmass_task_change_state(fmass, FMASS_TASK_DONE_DATA_PHASE); 337beacf11bSopenharmony_ci } 338beacf11bSopenharmony_ci fmass_wakeup(fmass); 339beacf11bSopenharmony_ci} 340beacf11bSopenharmony_ci 341beacf11bSopenharmony_cistatic int fmass_bulkin_request(struct mass_dev_s *fmass, 342beacf11bSopenharmony_ci struct usbdev_req_s *req) 343beacf11bSopenharmony_ci{ 344beacf11bSopenharmony_ci struct usbdev_ep_s *ep = fmass->bulkin; 345beacf11bSopenharmony_ci req->callback = fmass_handle_bulkin_callback; 346beacf11bSopenharmony_ci return EP_SUBMIT(ep, req); 347beacf11bSopenharmony_ci} 348beacf11bSopenharmony_ci 349beacf11bSopenharmony_cistatic int fmass_bulkout_request(struct mass_dev_s *fmass, 350beacf11bSopenharmony_ci struct usbdev_req_s *req) 351beacf11bSopenharmony_ci{ 352beacf11bSopenharmony_ci struct usbdev_ep_s *ep = fmass->bulkout; 353beacf11bSopenharmony_ci req->callback = fmass_handle_bulkout_callback; 354beacf11bSopenharmony_ci return EP_SUBMIT(ep, req); 355beacf11bSopenharmony_ci} 356beacf11bSopenharmony_ci 357beacf11bSopenharmony_cistatic void report_scsi_command_error(struct mass_dev_s *fmass, uint32_t sense_data) 358beacf11bSopenharmony_ci{ 359beacf11bSopenharmony_ci fmass->sense_data = sense_data; 360beacf11bSopenharmony_ci fmass->sense_data_info = 0; 361beacf11bSopenharmony_ci fmass->info_valid = 1; 362beacf11bSopenharmony_ci fmass->csw.bCSWStatus = BULK_CSW_STAT_FAIL; 363beacf11bSopenharmony_ci} 364beacf11bSopenharmony_ci 365beacf11bSopenharmony_ciint done_scsi_test_unit_ready(struct mass_dev_s *fmass) 366beacf11bSopenharmony_ci{ 367beacf11bSopenharmony_ci if (fmass_device_status(fmass)) 368beacf11bSopenharmony_ci { 369beacf11bSopenharmony_ci if (fmass->nluns == 0) 370beacf11bSopenharmony_ci { 371beacf11bSopenharmony_ci (void)fmass_dev_open(fmass); 372beacf11bSopenharmony_ci fmass_dev_capacity(fmass); 373beacf11bSopenharmony_ci fmass->sense_data = SCSI_NOT_READY_TO_READY_TRANSITION; 374beacf11bSopenharmony_ci fmass->csw.bCSWStatus = BULK_CSW_STAT_FAIL; 375beacf11bSopenharmony_ci DPRINTFN(1, "this unint is not ready\n"); 376beacf11bSopenharmony_ci } 377beacf11bSopenharmony_ci } 378beacf11bSopenharmony_ci else 379beacf11bSopenharmony_ci { 380beacf11bSopenharmony_ci fmass->sense_data = SCSI_MEDIUM_NOT_PRESENT; 381beacf11bSopenharmony_ci fmass->csw.bCSWStatus = BULK_CSW_STAT_FAIL; 382beacf11bSopenharmony_ci } 383beacf11bSopenharmony_ci return 0; 384beacf11bSopenharmony_ci} 385beacf11bSopenharmony_ci 386beacf11bSopenharmony_ciint done_scsi_request_sense(struct mass_dev_s *fmass) 387beacf11bSopenharmony_ci{ 388beacf11bSopenharmony_ci uint8_t *buf = (uint8_t *)fmass->bulkreq.buf; 389beacf11bSopenharmony_ci uint32_t sd, sdinfo; 390beacf11bSopenharmony_ci uint32_t valid; 391beacf11bSopenharmony_ci int ret; 392beacf11bSopenharmony_ci 393beacf11bSopenharmony_ci ret = memset_s(buf, (MAX_BLOCK_RW_SECTORS << 9), 0, 18); 394beacf11bSopenharmony_ci if (ret != EOK) 395beacf11bSopenharmony_ci { 396beacf11bSopenharmony_ci return 0; 397beacf11bSopenharmony_ci } 398beacf11bSopenharmony_ci 399beacf11bSopenharmony_ci if (!fmass->nluns && fmass_device_status(fmass)) /* Unsupported LUNs are okay */ 400beacf11bSopenharmony_ci { 401beacf11bSopenharmony_ci sd = SCSI_LOGICAL_UNIT_NOT_SUPPORTED; 402beacf11bSopenharmony_ci sdinfo = 0; 403beacf11bSopenharmony_ci valid = 0; 404beacf11bSopenharmony_ci } 405beacf11bSopenharmony_ci else 406beacf11bSopenharmony_ci { 407beacf11bSopenharmony_ci sd = fmass->sense_data; 408beacf11bSopenharmony_ci sdinfo = fmass->sense_data_info; 409beacf11bSopenharmony_ci valid = fmass->info_valid << 7; 410beacf11bSopenharmony_ci fmass->sense_data = SCSI_NO_SENSE; 411beacf11bSopenharmony_ci fmass->sense_data_info = 0; 412beacf11bSopenharmony_ci fmass->info_valid = 0; 413beacf11bSopenharmony_ci } 414beacf11bSopenharmony_ci 415beacf11bSopenharmony_ci buf[0] = valid | 0x70; /* Valid, current error */ 416beacf11bSopenharmony_ci buf[2] = SK(sd); 417beacf11bSopenharmony_ci put_unaligned_be32((&buf[3]), sdinfo); /* Sense information */ 418beacf11bSopenharmony_ci buf[7] = 10; /* Additional sense length: 18 - 8 */ 419beacf11bSopenharmony_ci buf[12] = ASC(sd); 420beacf11bSopenharmony_ci buf[13] = ASCQ(sd); 421beacf11bSopenharmony_ci return 18; 422beacf11bSopenharmony_ci} 423beacf11bSopenharmony_ci 424beacf11bSopenharmony_ciint done_scsi_mode_select(struct mass_dev_s *fmass) 425beacf11bSopenharmony_ci{ 426beacf11bSopenharmony_ci (void)fmass; 427beacf11bSopenharmony_ci return 0; 428beacf11bSopenharmony_ci} 429beacf11bSopenharmony_ci 430beacf11bSopenharmony_ciint done_scsi_mode_sense(struct mass_dev_s *fmass) 431beacf11bSopenharmony_ci{ 432beacf11bSopenharmony_ci uint8_t *buf = (uint8_t *)fmass->bulkreq.buf; 433beacf11bSopenharmony_ci int len; 434beacf11bSopenharmony_ci 435beacf11bSopenharmony_ci buf[0] = 0x03; /* mode data length */ 436beacf11bSopenharmony_ci buf[1] = 0x00; 437beacf11bSopenharmony_ci buf[2] = 0x00; 438beacf11bSopenharmony_ci buf[3] = 0x00; 439beacf11bSopenharmony_ci len = 4; 440beacf11bSopenharmony_ci fmass->residue = len; 441beacf11bSopenharmony_ci return len; 442beacf11bSopenharmony_ci} 443beacf11bSopenharmony_ci 444beacf11bSopenharmony_ciint done_scsi_read_format_capacities(struct mass_dev_s *fmass) 445beacf11bSopenharmony_ci{ 446beacf11bSopenharmony_ci uint8_t *buf = (uint8_t *)fmass->bulkreq.buf; 447beacf11bSopenharmony_ci 448beacf11bSopenharmony_ci buf[0] = 0; 449beacf11bSopenharmony_ci buf[1] = 0; 450beacf11bSopenharmony_ci buf[2] = 0; 451beacf11bSopenharmony_ci buf[3] = 8; /* Only the Current/Maximum Capacity Descriptor */ 452beacf11bSopenharmony_ci buf += 4; 453beacf11bSopenharmony_ci 454beacf11bSopenharmony_ci put_unaligned_be32((&buf[0]), fmass->caps[fmass->lun].nsectors); 455beacf11bSopenharmony_ci put_unaligned_be32((&buf[4]), fmass->caps[fmass->lun].sectorsize); /* Block length */ 456beacf11bSopenharmony_ci buf[4] = 0x02; /* Current capacity */ 457beacf11bSopenharmony_ci 458beacf11bSopenharmony_ci return 12; 459beacf11bSopenharmony_ci} 460beacf11bSopenharmony_ci 461beacf11bSopenharmony_ciint done_scsi_read_capacity(struct mass_dev_s *fmass) 462beacf11bSopenharmony_ci{ 463beacf11bSopenharmony_ci uint8_t *buf = (uint8_t *)fmass->bulkreq.buf; 464beacf11bSopenharmony_ci uint32_t sectors; 465beacf11bSopenharmony_ci uint32_t blksizes; 466beacf11bSopenharmony_ci 467beacf11bSopenharmony_ci if (!fmass->nluns) 468beacf11bSopenharmony_ci { 469beacf11bSopenharmony_ci (void)fmass_dev_open(fmass); 470beacf11bSopenharmony_ci fmass_dev_capacity(fmass); 471beacf11bSopenharmony_ci fmass->sense_data = SCSI_NOT_READY_TO_READY_TRANSITION; 472beacf11bSopenharmony_ci fmass->csw.bCSWStatus = BULK_CSW_STAT_FAIL; 473beacf11bSopenharmony_ci DPRINTFN(0, "fmass->fileNode is not exist\n"); 474beacf11bSopenharmony_ci return 0; 475beacf11bSopenharmony_ci } 476beacf11bSopenharmony_ci 477beacf11bSopenharmony_ci sectors = fmass->caps[fmass->lun].nsectors - 1; 478beacf11bSopenharmony_ci blksizes = fmass->caps[fmass->lun].sectorsize; 479beacf11bSopenharmony_ci 480beacf11bSopenharmony_ci put_unaligned_be32(buf, sectors); 481beacf11bSopenharmony_ci put_unaligned_be32((buf + 4), blksizes); 482beacf11bSopenharmony_ci 483beacf11bSopenharmony_ci return 8; 484beacf11bSopenharmony_ci} 485beacf11bSopenharmony_ci 486beacf11bSopenharmony_ciint done_scsi_read(struct mass_dev_s *fmass) 487beacf11bSopenharmony_ci{ 488beacf11bSopenharmony_ci uint8_t *buf = (uint8_t *)fmass->bulkreq.buf; 489beacf11bSopenharmony_ci uint32_t lba; 490beacf11bSopenharmony_ci uint32_t amount_left; 491beacf11bSopenharmony_ci uint32_t amount; 492beacf11bSopenharmony_ci uint32_t nreadsector; 493beacf11bSopenharmony_ci uintptr_t num_sectors = fmass->caps[fmass->lun].nsectors; 494beacf11bSopenharmony_ci struct fmass_data_buf_t *db; 495beacf11bSopenharmony_ci uint32_t doread ; 496beacf11bSopenharmony_ci 497beacf11bSopenharmony_ci if (fmass->cmd[0] == SCSI_READ_6) 498beacf11bSopenharmony_ci { 499beacf11bSopenharmony_ci lba = ((((uint32_t)fmass->cmd[1]) << 16) | 500beacf11bSopenharmony_ci get_unaligned_be16(&fmass->cmd[2])); 501beacf11bSopenharmony_ci } 502beacf11bSopenharmony_ci else 503beacf11bSopenharmony_ci { 504beacf11bSopenharmony_ci lba = get_unaligned_be32(&fmass->cmd[2]); 505beacf11bSopenharmony_ci 506beacf11bSopenharmony_ci /* 507beacf11bSopenharmony_ci * We allow DPO (Disable Page Out = don't save data in the 508beacf11bSopenharmony_ci * cache) and FUA (Force Unit Access = write directly to the 509beacf11bSopenharmony_ci * medium). We don't implement DPO; we implement FUA by 510beacf11bSopenharmony_ci * performing synchronous output. 511beacf11bSopenharmony_ci */ 512beacf11bSopenharmony_ci 513beacf11bSopenharmony_ci if ((fmass->cmd[1] & ~0x18) != 0) 514beacf11bSopenharmony_ci { 515beacf11bSopenharmony_ci report_scsi_command_error(fmass, SCSI_INVALID_FIELD_IN_CDB); 516beacf11bSopenharmony_ci return -EIO; 517beacf11bSopenharmony_ci } 518beacf11bSopenharmony_ci } 519beacf11bSopenharmony_ci 520beacf11bSopenharmony_ci if (lba >= num_sectors) 521beacf11bSopenharmony_ci { 522beacf11bSopenharmony_ci report_scsi_command_error(fmass, SCSI_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE); 523beacf11bSopenharmony_ci return -1; 524beacf11bSopenharmony_ci } 525beacf11bSopenharmony_ci 526beacf11bSopenharmony_ci if (unlikely(fmass->data_size_from_cmd == 0)) 527beacf11bSopenharmony_ci { 528beacf11bSopenharmony_ci report_scsi_command_error(fmass, SCSI_UNRECOVERED_READ_ERROR); 529beacf11bSopenharmony_ci return -EIO; 530beacf11bSopenharmony_ci } 531beacf11bSopenharmony_ci 532beacf11bSopenharmony_ci nreadsector = fmass->data_size_from_cmd; 533beacf11bSopenharmony_ci 534beacf11bSopenharmony_ci amount_left = nreadsector; 535beacf11bSopenharmony_ci 536beacf11bSopenharmony_ci fmass->bulkreq.is_complete = 1; 537beacf11bSopenharmony_ci 538beacf11bSopenharmony_ci db = fmass->databuf_fill; 539beacf11bSopenharmony_ci 540beacf11bSopenharmony_ci for (; ;) 541beacf11bSopenharmony_ci { 542beacf11bSopenharmony_ci uint32_t data_size; 543beacf11bSopenharmony_ci 544beacf11bSopenharmony_ci amount = min(MAX_BLOCK_RW_SECTORS, amount_left); 545beacf11bSopenharmony_ci db = fmass->databuf_fill; 546beacf11bSopenharmony_ci if (!fmass_wait_intr(fmass, ((fmass->bulkreq.is_complete != 0) || 547beacf11bSopenharmony_ci taskstate_match(fmass, FMASS_TASK_DISCONNECT)), (2 * HZ))) 548beacf11bSopenharmony_ci { 549beacf11bSopenharmony_ci fmass->bulkreq.is_complete = 1; 550beacf11bSopenharmony_ci report_scsi_command_error(fmass, SCSI_UNRECOVERED_READ_ERROR); 551beacf11bSopenharmony_ci return -EIO; 552beacf11bSopenharmony_ci } 553beacf11bSopenharmony_ci 554beacf11bSopenharmony_ci if (taskstate_match(fmass, FMASS_TASK_DISCONNECT)) 555beacf11bSopenharmony_ci { 556beacf11bSopenharmony_ci report_scsi_command_error(fmass, SCSI_UNRECOVERED_READ_ERROR); 557beacf11bSopenharmony_ci return -EIO; 558beacf11bSopenharmony_ci } 559beacf11bSopenharmony_ci 560beacf11bSopenharmony_ci buf = (uint8_t *)db->buf; 561beacf11bSopenharmony_ci doread = fmass_dev_read(fmass, buf, lba, amount); 562beacf11bSopenharmony_ci data_size = doread << 9; 563beacf11bSopenharmony_ci lba += doread; 564beacf11bSopenharmony_ci amount_left -= doread; 565beacf11bSopenharmony_ci fmass->residue -= data_size; /* doread * 512 */ 566beacf11bSopenharmony_ci fmass->bulkreq.len = data_size; 567beacf11bSopenharmony_ci fmass->bulkreq.buf = buf; 568beacf11bSopenharmony_ci DPRINTFN(1, "read: db= 0x%x buf= 0x%x lba= %x doread= %u nread= %u amount_left = %u residue= %u\n", 569beacf11bSopenharmony_ci db, buf, lba - doread , doread, amount, amount_left, fmass->residue); 570beacf11bSopenharmony_ci 571beacf11bSopenharmony_ci if (doread < amount) 572beacf11bSopenharmony_ci { 573beacf11bSopenharmony_ci report_scsi_command_error(fmass, SCSI_UNRECOVERED_READ_ERROR); 574beacf11bSopenharmony_ci break; 575beacf11bSopenharmony_ci } 576beacf11bSopenharmony_ci 577beacf11bSopenharmony_ci if (amount_left == 0) 578beacf11bSopenharmony_ci { 579beacf11bSopenharmony_ci break; 580beacf11bSopenharmony_ci } 581beacf11bSopenharmony_ci 582beacf11bSopenharmony_ci (void)fmass_bulkin_request(fmass, &fmass->bulkreq); 583beacf11bSopenharmony_ci fmass->databuf_fill = db->next; 584beacf11bSopenharmony_ci } 585beacf11bSopenharmony_ci fmass->bulkreq.is_complete = 1; 586beacf11bSopenharmony_ci return -EIO; 587beacf11bSopenharmony_ci} 588beacf11bSopenharmony_ci 589beacf11bSopenharmony_ciint done_scsi_write(struct mass_dev_s *fmass) 590beacf11bSopenharmony_ci{ 591beacf11bSopenharmony_ci uint8_t *buf = (uint8_t *)fmass->bulkreq.buf; 592beacf11bSopenharmony_ci uint32_t lba; 593beacf11bSopenharmony_ci uint32_t idx; 594beacf11bSopenharmony_ci uint32_t amount, amount_left; 595beacf11bSopenharmony_ci uint32_t nwritesector; 596beacf11bSopenharmony_ci uintptr_t num_sectors = fmass->caps[fmass->lun].nsectors; 597beacf11bSopenharmony_ci uint32_t total_do_write; 598beacf11bSopenharmony_ci uint32_t do_write = 0; 599beacf11bSopenharmony_ci 600beacf11bSopenharmony_ci if (fmass->caps[fmass->lun].read_only) 601beacf11bSopenharmony_ci { 602beacf11bSopenharmony_ci report_scsi_command_error(fmass,SCSI_WRITE_PROTECTED); 603beacf11bSopenharmony_ci return -EINVAL; 604beacf11bSopenharmony_ci } 605beacf11bSopenharmony_ci 606beacf11bSopenharmony_ci if (fmass->cmd[0] == SCSI_WRITE_6) 607beacf11bSopenharmony_ci { 608beacf11bSopenharmony_ci lba = ((((uint32_t)fmass->cmd[1]) << 16) | 609beacf11bSopenharmony_ci get_unaligned_be16(&fmass->cmd[2])); 610beacf11bSopenharmony_ci } 611beacf11bSopenharmony_ci else 612beacf11bSopenharmony_ci { 613beacf11bSopenharmony_ci lba = get_unaligned_be32(&fmass->cmd[2]); 614beacf11bSopenharmony_ci 615beacf11bSopenharmony_ci /* 616beacf11bSopenharmony_ci * We allow DPO (Disable Page Out = don't save data in the 617beacf11bSopenharmony_ci * cache) and FUA (Force Unit Access = write directly to the 618beacf11bSopenharmony_ci * medium). We don't implement DPO; we implement FUA by 619beacf11bSopenharmony_ci * performing synchronous output. 620beacf11bSopenharmony_ci */ 621beacf11bSopenharmony_ci 622beacf11bSopenharmony_ci if ((fmass->cmd[1] & ~0x18) != 0) 623beacf11bSopenharmony_ci { 624beacf11bSopenharmony_ci report_scsi_command_error(fmass, SCSI_INVALID_FIELD_IN_CDB); 625beacf11bSopenharmony_ci return -EIO; 626beacf11bSopenharmony_ci } 627beacf11bSopenharmony_ci if (fmass->cmd[1] & 0x08) 628beacf11bSopenharmony_ci { 629beacf11bSopenharmony_ci /* FUA */ 630beacf11bSopenharmony_ci /* XXX set SYNC flag here */ 631beacf11bSopenharmony_ci 632beacf11bSopenharmony_ci } 633beacf11bSopenharmony_ci } 634beacf11bSopenharmony_ci 635beacf11bSopenharmony_ci if (lba >= num_sectors) 636beacf11bSopenharmony_ci { 637beacf11bSopenharmony_ci report_scsi_command_error(fmass, SCSI_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE); 638beacf11bSopenharmony_ci return -1; 639beacf11bSopenharmony_ci } 640beacf11bSopenharmony_ci 641beacf11bSopenharmony_ci if (unlikely(fmass->data_size_from_cmd == 0)) 642beacf11bSopenharmony_ci { 643beacf11bSopenharmony_ci return -EIO; /* No default reply */ 644beacf11bSopenharmony_ci } 645beacf11bSopenharmony_ci 646beacf11bSopenharmony_ci fmass_task_change_state(fmass, FMASS_TASK_REQ_DATA_PHASE); 647beacf11bSopenharmony_ci DPRINTFN(1, "------ Direct Data Phase ------\n"); 648beacf11bSopenharmony_ci fmass->bulkreq.len = fmass->data_size; 649beacf11bSopenharmony_ci (void)fmass_bulkout_request(fmass, &fmass->bulkreq); 650beacf11bSopenharmony_ci 651beacf11bSopenharmony_ci if (!fmass_wait_intr(fmass, (taskstate_match(fmass, FMASS_TASK_DONE_DATA_PHASE) || 652beacf11bSopenharmony_ci taskstate_match(fmass, FMASS_TASK_DISCONNECT)), (5*HZ))) 653beacf11bSopenharmony_ci { 654beacf11bSopenharmony_ci DPRINTFN(0, "error wait intr\n"); 655beacf11bSopenharmony_ci return -EIO; 656beacf11bSopenharmony_ci } 657beacf11bSopenharmony_ci 658beacf11bSopenharmony_ci if (taskstate_unmatch(fmass, FMASS_TASK_DONE_DATA_PHASE)) 659beacf11bSopenharmony_ci { 660beacf11bSopenharmony_ci DPRINTFN(0, "invalid task state : %u, unfinish transfer Data packet\n", fmass->task_state); 661beacf11bSopenharmony_ci return -EIO; 662beacf11bSopenharmony_ci } 663beacf11bSopenharmony_ci 664beacf11bSopenharmony_ci nwritesector = fmass->bulkreq.xfrd >> 9; /* bytes -> sectors */ 665beacf11bSopenharmony_ci nwritesector = min(nwritesector, fmass->data_size_from_cmd); 666beacf11bSopenharmony_ci 667beacf11bSopenharmony_ci amount = nwritesector / MAX_BLOCK_RW_SECTORS; 668beacf11bSopenharmony_ci amount_left = nwritesector % MAX_BLOCK_RW_SECTORS; 669beacf11bSopenharmony_ci 670beacf11bSopenharmony_ci total_do_write = 0; 671beacf11bSopenharmony_ci for (idx = 0; idx < amount ; idx++) 672beacf11bSopenharmony_ci { 673beacf11bSopenharmony_ci do_write = fmass_dev_write(fmass, buf, lba, MAX_BLOCK_RW_SECTORS); 674beacf11bSopenharmony_ci 675beacf11bSopenharmony_ci lba += MAX_BLOCK_RW_SECTORS; 676beacf11bSopenharmony_ci buf += (MAX_BLOCK_RW_SECTORS << 9); 677beacf11bSopenharmony_ci fmass->residue -= do_write << 9; /* doread * 512 */ 678beacf11bSopenharmony_ci total_do_write += do_write; 679beacf11bSopenharmony_ci } 680beacf11bSopenharmony_ci 681beacf11bSopenharmony_ci if (amount == 0 || do_write > 0) 682beacf11bSopenharmony_ci { 683beacf11bSopenharmony_ci do_write = fmass_dev_write(fmass, buf, lba, amount_left); 684beacf11bSopenharmony_ci 685beacf11bSopenharmony_ci if (do_write > 0) 686beacf11bSopenharmony_ci { 687beacf11bSopenharmony_ci fmass->residue -= do_write << 9; /* doread * 512 */ 688beacf11bSopenharmony_ci total_do_write += do_write; 689beacf11bSopenharmony_ci } 690beacf11bSopenharmony_ci } 691beacf11bSopenharmony_ci 692beacf11bSopenharmony_ci if (total_do_write < nwritesector) 693beacf11bSopenharmony_ci { 694beacf11bSopenharmony_ci fmass->sense_data = SCSI_UNRECOVERED_READ_ERROR; 695beacf11bSopenharmony_ci fmass->csw.bCSWStatus = BULK_CSW_STAT_FAIL; 696beacf11bSopenharmony_ci } 697beacf11bSopenharmony_ci 698beacf11bSopenharmony_ci fmass->data_size = 0; 699beacf11bSopenharmony_ci return -EIO; 700beacf11bSopenharmony_ci} 701beacf11bSopenharmony_ci 702beacf11bSopenharmony_ciint done_scsi_inquiry(struct mass_dev_s *fmass) 703beacf11bSopenharmony_ci{ 704beacf11bSopenharmony_ci errno_t ret; 705beacf11bSopenharmony_ci uint8_t *buf = (uint8_t *)fmass->bulkreq.buf; 706beacf11bSopenharmony_ci buf[0] = 0; /* Peripheral Qualifier && Device Type */ 707beacf11bSopenharmony_ci buf[1] = 0x80; /* Removable Medium */ 708beacf11bSopenharmony_ci buf[2] = 0; /* ANSI SCSI level 2 */ 709beacf11bSopenharmony_ci buf[3] = 1; /* SCSI-2 INQUIRY data format */ 710beacf11bSopenharmony_ci buf[4] = 31; /* Additional length */ 711beacf11bSopenharmony_ci buf[5] = 0; /* SCCS SCC Support: 0 */ 712beacf11bSopenharmony_ci buf[6] = 0; 713beacf11bSopenharmony_ci buf[7] = 0; 714beacf11bSopenharmony_ci 715beacf11bSopenharmony_ci ret = memcpy_s(buf + 8, ((MAX_BLOCK_RW_SECTORS << 9) - 8), fmass->inquiry_str, sizeof(fmass->inquiry_str)); 716beacf11bSopenharmony_ci if (ret != EOK) 717beacf11bSopenharmony_ci { 718beacf11bSopenharmony_ci return -EIO; 719beacf11bSopenharmony_ci } 720beacf11bSopenharmony_ci 721beacf11bSopenharmony_ci fmass->bulkreq.len = 36; 722beacf11bSopenharmony_ci fmass->residue = 0; 723beacf11bSopenharmony_ci return -EIO; 724beacf11bSopenharmony_ci} 725beacf11bSopenharmony_ci 726beacf11bSopenharmony_ciint done_scsi_allow_medium_removal(struct mass_dev_s *fmass) 727beacf11bSopenharmony_ci{ 728beacf11bSopenharmony_ci fmass->sense_data = SCSI_INVALID_COM; 729beacf11bSopenharmony_ci fmass->csw.bCSWStatus = BULK_CSW_STAT_FAIL; 730beacf11bSopenharmony_ci return 0; 731beacf11bSopenharmony_ci} 732beacf11bSopenharmony_ci 733beacf11bSopenharmony_cistatic int fmass_check_receive_cbw(struct mass_dev_s *fmass) 734beacf11bSopenharmony_ci{ 735beacf11bSopenharmony_ci struct bulk_cbw *cbw = (struct bulk_cbw *)fmass->bulkreq.buf; 736beacf11bSopenharmony_ci errno_t ret; 737beacf11bSopenharmony_ci 738beacf11bSopenharmony_ci DPRINTFN(1, "\t -----Received CBW packet -----dCBWTag: 0x%x bCBWLUN:%u\n", cbw->dCBWTag, cbw->bCBWLUN); 739beacf11bSopenharmony_ci 740beacf11bSopenharmony_ci /* Check the CBW is validid */ 741beacf11bSopenharmony_ci 742beacf11bSopenharmony_ci if (fmass->bulkreq.xfrd != BULK_CBW_WRAP_LEN || 743beacf11bSopenharmony_ci cbw->dCBWSignature != BULK_CBW_SIGN) 744beacf11bSopenharmony_ci { 745beacf11bSopenharmony_ci DPRINTFN(0, "invalid CBW: len %u sig 0x%x ,cvt_sig 0x%x lct_sig 0x%x\n", 746beacf11bSopenharmony_ci fmass->bulkreq.xfrd, cbw->dCBWSignature, cbw->dCBWSignature, BULK_CBW_SIGN); 747beacf11bSopenharmony_ci return -1; 748beacf11bSopenharmony_ci } 749beacf11bSopenharmony_ci 750beacf11bSopenharmony_ci /* Check the CBW is meaningful */ 751beacf11bSopenharmony_ci 752beacf11bSopenharmony_ci if (cbw->bCBWLUN >= FMASS_MAX_LUNS || cbw->bmCBWFlags & ~BULK_CBW_FLAG_IN || 753beacf11bSopenharmony_ci cbw->bCBWLEN == 0 || cbw->bCBWLEN > MAX_COMMAND_SIZE) 754beacf11bSopenharmony_ci { 755beacf11bSopenharmony_ci DPRINTFN(0, "non-meaningful CBW: lun = %u, flags = 0x%x, cmdlen = %u\n", 756beacf11bSopenharmony_ci cbw->bCBWLUN, cbw->bmCBWFlags, cbw->bCBWLEN); 757beacf11bSopenharmony_ci return -1; 758beacf11bSopenharmony_ci } 759beacf11bSopenharmony_ci 760beacf11bSopenharmony_ci /* Save the command for later */ 761beacf11bSopenharmony_ci 762beacf11bSopenharmony_ci fmass->cmd_size = cbw->bCBWLEN; 763beacf11bSopenharmony_ci ret = memcpy_s(fmass->cmd, MAX_COMMAND_SIZE, cbw->CDB, fmass->cmd_size); 764beacf11bSopenharmony_ci if (ret != EOK) 765beacf11bSopenharmony_ci { 766beacf11bSopenharmony_ci DPRINTFN(0, "memcpy_s failed, %d\n", ret); 767beacf11bSopenharmony_ci return -1; 768beacf11bSopenharmony_ci } 769beacf11bSopenharmony_ci if (cbw->bmCBWFlags & BULK_CBW_FLAG_IN) 770beacf11bSopenharmony_ci { 771beacf11bSopenharmony_ci fmass->data_dir = DATA_DIRECT_TO_HOST; 772beacf11bSopenharmony_ci } 773beacf11bSopenharmony_ci else 774beacf11bSopenharmony_ci { 775beacf11bSopenharmony_ci fmass->data_dir = DATA_DIRECT_FROM_HOST; 776beacf11bSopenharmony_ci } 777beacf11bSopenharmony_ci fmass->data_size = cbw->dCBWDataTransferLength; 778beacf11bSopenharmony_ci if (fmass->data_size == 0) 779beacf11bSopenharmony_ci { 780beacf11bSopenharmony_ci fmass->data_dir = DATA_DIRECT_NONE; 781beacf11bSopenharmony_ci } 782beacf11bSopenharmony_ci 783beacf11bSopenharmony_ci fmass->tag = cbw->dCBWTag; 784beacf11bSopenharmony_ci 785beacf11bSopenharmony_ci if (fmass->data_size < fmass->data_size_from_cmd) 786beacf11bSopenharmony_ci { 787beacf11bSopenharmony_ci fmass->data_size_from_cmd = fmass->data_size; 788beacf11bSopenharmony_ci } 789beacf11bSopenharmony_ci fmass->residue = fmass->data_size; 790beacf11bSopenharmony_ci 791beacf11bSopenharmony_ci return 0; 792beacf11bSopenharmony_ci} 793beacf11bSopenharmony_ci 794beacf11bSopenharmony_cistatic void fmass_do_scsi_command(struct mass_dev_s *fmass) 795beacf11bSopenharmony_ci{ 796beacf11bSopenharmony_ci int i; 797beacf11bSopenharmony_ci int reply = -1; 798beacf11bSopenharmony_ci uint32_t reply_temp; 799beacf11bSopenharmony_ci 800beacf11bSopenharmony_ci uint8_t cmd = fmass->cmd[0]; 801beacf11bSopenharmony_ci 802beacf11bSopenharmony_ci switch (cmd) 803beacf11bSopenharmony_ci { 804beacf11bSopenharmony_ci case SCSI_TEST_UNIT_READY: 805beacf11bSopenharmony_ci fmass->data_size_from_cmd = 0; 806beacf11bSopenharmony_ci reply = done_scsi_test_unit_ready(fmass); 807beacf11bSopenharmony_ci break; 808beacf11bSopenharmony_ci 809beacf11bSopenharmony_ci case SCSI_REQUEST_SENSE: 810beacf11bSopenharmony_ci fmass->data_size_from_cmd = fmass->cmd[4]; 811beacf11bSopenharmony_ci reply = done_scsi_request_sense(fmass); 812beacf11bSopenharmony_ci break; 813beacf11bSopenharmony_ci 814beacf11bSopenharmony_ci case SCSI_INQUIRY: 815beacf11bSopenharmony_ci fmass->data_size_from_cmd = fmass->cmd[4]; 816beacf11bSopenharmony_ci reply = done_scsi_inquiry(fmass); 817beacf11bSopenharmony_ci break; 818beacf11bSopenharmony_ci 819beacf11bSopenharmony_ci case SCSI_MODE_SELECT_6: 820beacf11bSopenharmony_ci fmass->data_size_from_cmd = fmass->cmd[4]; 821beacf11bSopenharmony_ci reply = done_scsi_mode_select(fmass); 822beacf11bSopenharmony_ci break; 823beacf11bSopenharmony_ci 824beacf11bSopenharmony_ci case SCSI_MODE_SELECT_10: 825beacf11bSopenharmony_ci fmass->data_size_from_cmd = get_unaligned_be16(&fmass->cmd[7]); 826beacf11bSopenharmony_ci reply = done_scsi_mode_select(fmass); 827beacf11bSopenharmony_ci break; 828beacf11bSopenharmony_ci 829beacf11bSopenharmony_ci case SCSI_MODE_SENSE_6: 830beacf11bSopenharmony_ci fmass->data_size_from_cmd = fmass->cmd[4]; 831beacf11bSopenharmony_ci reply = done_scsi_mode_sense(fmass); 832beacf11bSopenharmony_ci break; 833beacf11bSopenharmony_ci 834beacf11bSopenharmony_ci case SCSI_MODE_SENSE_10: 835beacf11bSopenharmony_ci fmass->data_size_from_cmd = get_unaligned_be16(&fmass->cmd[7]); 836beacf11bSopenharmony_ci reply = done_scsi_mode_sense(fmass); 837beacf11bSopenharmony_ci break; 838beacf11bSopenharmony_ci 839beacf11bSopenharmony_ci case SCSI_READ_FORMAT_CAPACITIES: 840beacf11bSopenharmony_ci fmass->data_size_from_cmd = get_unaligned_be16(&fmass->cmd[7]); 841beacf11bSopenharmony_ci reply = done_scsi_read_format_capacities(fmass); 842beacf11bSopenharmony_ci break; 843beacf11bSopenharmony_ci 844beacf11bSopenharmony_ci case SCSI_READ_CAPACITY: 845beacf11bSopenharmony_ci fmass->data_size_from_cmd = 8; 846beacf11bSopenharmony_ci if (fmass_device_status(fmass)) 847beacf11bSopenharmony_ci { 848beacf11bSopenharmony_ci reply = done_scsi_read_capacity(fmass); 849beacf11bSopenharmony_ci } 850beacf11bSopenharmony_ci else 851beacf11bSopenharmony_ci { 852beacf11bSopenharmony_ci reply = 0; 853beacf11bSopenharmony_ci } 854beacf11bSopenharmony_ci break; 855beacf11bSopenharmony_ci 856beacf11bSopenharmony_ci case SCSI_READ_6: 857beacf11bSopenharmony_ci i = fmass->cmd[4]; 858beacf11bSopenharmony_ci fmass->data_size_from_cmd = (i == 0) ? 256 : i; 859beacf11bSopenharmony_ci reply = done_scsi_read(fmass); 860beacf11bSopenharmony_ci break; 861beacf11bSopenharmony_ci 862beacf11bSopenharmony_ci case SCSI_READ_10: 863beacf11bSopenharmony_ci fmass->data_size_from_cmd = get_unaligned_be16(&fmass->cmd[7]); 864beacf11bSopenharmony_ci reply = done_scsi_read(fmass); 865beacf11bSopenharmony_ci break; 866beacf11bSopenharmony_ci 867beacf11bSopenharmony_ci case SCSI_READ_12: 868beacf11bSopenharmony_ci fmass->data_size_from_cmd = get_unaligned_be32(&fmass->cmd[6]); 869beacf11bSopenharmony_ci reply = done_scsi_read(fmass); 870beacf11bSopenharmony_ci break; 871beacf11bSopenharmony_ci 872beacf11bSopenharmony_ci case SCSI_WRITE_6: 873beacf11bSopenharmony_ci i = fmass->cmd[4]; 874beacf11bSopenharmony_ci fmass->data_size_from_cmd = (i == 0) ? 256 : i; 875beacf11bSopenharmony_ci reply = done_scsi_write(fmass); 876beacf11bSopenharmony_ci break; 877beacf11bSopenharmony_ci 878beacf11bSopenharmony_ci case SCSI_WRITE_10: 879beacf11bSopenharmony_ci fmass->data_size_from_cmd = get_unaligned_be16(&fmass->cmd[7]); 880beacf11bSopenharmony_ci reply = done_scsi_write(fmass); 881beacf11bSopenharmony_ci break; 882beacf11bSopenharmony_ci 883beacf11bSopenharmony_ci case SCSI_WRITE_12: 884beacf11bSopenharmony_ci fmass->data_size_from_cmd = get_unaligned_be32(&fmass->cmd[6]); 885beacf11bSopenharmony_ci reply = done_scsi_write(fmass); 886beacf11bSopenharmony_ci break; 887beacf11bSopenharmony_ci 888beacf11bSopenharmony_ci case SCSI_ALLOW_MEDIUM_REMOVAL: 889beacf11bSopenharmony_ci fmass->data_size_from_cmd = 0; 890beacf11bSopenharmony_ci reply = done_scsi_allow_medium_removal(fmass); 891beacf11bSopenharmony_ci break; 892beacf11bSopenharmony_ci 893beacf11bSopenharmony_ci case START_STOP: 894beacf11bSopenharmony_ci fmass->data_size_from_cmd = 0; 895beacf11bSopenharmony_ci reply = 0; 896beacf11bSopenharmony_ci fmass->dev_status = DEV_ST_DISCONNECT; 897beacf11bSopenharmony_ci (void)fmass_dev_close(fmass); 898beacf11bSopenharmony_ci break; 899beacf11bSopenharmony_ci 900beacf11bSopenharmony_ci default: 901beacf11bSopenharmony_ci DPRINTFN(0, "********[invalid SCSI command! %x]***********\n", cmd); 902beacf11bSopenharmony_ci fmass->data_size_from_cmd = 0; 903beacf11bSopenharmony_ci report_scsi_command_error(fmass, SCSI_INVALID_COMMAND); 904beacf11bSopenharmony_ci break; 905beacf11bSopenharmony_ci } 906beacf11bSopenharmony_ci 907beacf11bSopenharmony_ci if (reply >= 0 && fmass->data_dir == DATA_DIRECT_TO_HOST) 908beacf11bSopenharmony_ci { 909beacf11bSopenharmony_ci fmass->bulkreq.len = reply; 910beacf11bSopenharmony_ci reply_temp = min((uint32_t)reply, fmass->data_size_from_cmd); 911beacf11bSopenharmony_ci fmass->residue -= reply_temp; 912beacf11bSopenharmony_ci } 913beacf11bSopenharmony_ci } 914beacf11bSopenharmony_ci 915beacf11bSopenharmony_civoid fmass_handle_scsi_data(struct mass_dev_s *fmass) 916beacf11bSopenharmony_ci{ 917beacf11bSopenharmony_ci int is_data_phase = 0; 918beacf11bSopenharmony_ci 919beacf11bSopenharmony_ci DPRINTFN(1, "\t-----REQ DATA PHASE-----\n"); 920beacf11bSopenharmony_ci switch (fmass->data_dir) 921beacf11bSopenharmony_ci { 922beacf11bSopenharmony_ci case DATA_DIRECT_NONE: 923beacf11bSopenharmony_ci break; /* Nothing to send */ 924beacf11bSopenharmony_ci 925beacf11bSopenharmony_ci case DATA_DIRECT_UNKNOWN: 926beacf11bSopenharmony_ci break; 927beacf11bSopenharmony_ci 928beacf11bSopenharmony_ci /* All but the last buffer of data must have already been sent */ 929beacf11bSopenharmony_ci 930beacf11bSopenharmony_ci case DATA_DIRECT_TO_HOST: 931beacf11bSopenharmony_ci if (fmass->data_size == 0) 932beacf11bSopenharmony_ci { 933beacf11bSopenharmony_ci /* do nothing */ 934beacf11bSopenharmony_ci 935beacf11bSopenharmony_ci } 936beacf11bSopenharmony_ci else if (fmass->residue == 0) 937beacf11bSopenharmony_ci { 938beacf11bSopenharmony_ci (void)fmass_bulkin_request(fmass, &fmass->bulkreq); 939beacf11bSopenharmony_ci } 940beacf11bSopenharmony_ci else 941beacf11bSopenharmony_ci { 942beacf11bSopenharmony_ci (void)fmass_bulkin_request(fmass, &fmass->bulkreq); 943beacf11bSopenharmony_ci if (!fmass_wait_intr(fmass, taskstate_unmatch(fmass, FMASS_TASK_REQ_DATA_PHASE), (2*HZ))) 944beacf11bSopenharmony_ci { 945beacf11bSopenharmony_ci DPRINTFN(0, "--- [Data Phase] timeout! state: %u residue : %u ---\n", 946beacf11bSopenharmony_ci fmass->task_state, fmass->residue); 947beacf11bSopenharmony_ci if (taskstate_match(fmass, FMASS_TASK_REQ_DATA_PHASE)) 948beacf11bSopenharmony_ci { 949beacf11bSopenharmony_ci fmass_task_change_state(fmass, FMASS_TASK_IDLE); 950beacf11bSopenharmony_ci } 951beacf11bSopenharmony_ci return ; 952beacf11bSopenharmony_ci } 953beacf11bSopenharmony_ci 954beacf11bSopenharmony_ci (void)EP_RESUME(fmass->bulkin); 955beacf11bSopenharmony_ci fmass_task_change_state(fmass, FMASS_TASK_REQ_STATUS_PHASE); 956beacf11bSopenharmony_ci return ; 957beacf11bSopenharmony_ci } 958beacf11bSopenharmony_ci is_data_phase = 1; 959beacf11bSopenharmony_ci break; 960beacf11bSopenharmony_ci 961beacf11bSopenharmony_ci case DATA_DIRECT_FROM_HOST: 962beacf11bSopenharmony_ci break; 963beacf11bSopenharmony_ci } 964beacf11bSopenharmony_ci 965beacf11bSopenharmony_ci if (is_data_phase) 966beacf11bSopenharmony_ci { 967beacf11bSopenharmony_ci /* wait for the data transfer done */ 968beacf11bSopenharmony_ci 969beacf11bSopenharmony_ci if (!fmass_wait_intr(fmass, taskstate_unmatch(fmass, FMASS_TASK_REQ_DATA_PHASE), (5*HZ))) 970beacf11bSopenharmony_ci { 971beacf11bSopenharmony_ci DPRINTFN(0, "--- [Data Phase] timeout! state: %u ---\n", fmass->task_state); 972beacf11bSopenharmony_ci if (taskstate_match(fmass, FMASS_TASK_REQ_DATA_PHASE)) 973beacf11bSopenharmony_ci { 974beacf11bSopenharmony_ci fmass_task_change_state(fmass, FMASS_TASK_IDLE); 975beacf11bSopenharmony_ci } 976beacf11bSopenharmony_ci return ; 977beacf11bSopenharmony_ci } 978beacf11bSopenharmony_ci if (taskstate_unmatch(fmass, FMASS_TASK_DONE_DATA_PHASE)) 979beacf11bSopenharmony_ci { 980beacf11bSopenharmony_ci DPRINTFN(0, "--- [Data Phase] unmatch! unexpect state: %u ---\n", fmass->task_state); 981beacf11bSopenharmony_ci return ; 982beacf11bSopenharmony_ci } 983beacf11bSopenharmony_ci fmass_task_change_state(fmass, FMASS_TASK_REQ_STATUS_PHASE); 984beacf11bSopenharmony_ci } 985beacf11bSopenharmony_ci else 986beacf11bSopenharmony_ci { 987beacf11bSopenharmony_ci fmass_task_change_state(fmass, FMASS_TASK_REQ_STATUS_PHASE); 988beacf11bSopenharmony_ci } 989beacf11bSopenharmony_ci} 990beacf11bSopenharmony_ci 991beacf11bSopenharmony_civoid fmass_set_scsi_status(struct mass_dev_s *fmass) 992beacf11bSopenharmony_ci{ 993beacf11bSopenharmony_ci struct bulk_csw *csw = (struct bulk_csw *)(fmass->bulkreq.buf); 994beacf11bSopenharmony_ci uint8_t status = fmass->csw.bCSWStatus; 995beacf11bSopenharmony_ci 996beacf11bSopenharmony_ci DPRINTFN(1, "\t -----Response CSW packet -------dCBWTag:0x%x residue: %u status: %u\n", 997beacf11bSopenharmony_ci fmass->tag, fmass->residue, status); 998beacf11bSopenharmony_ci 999beacf11bSopenharmony_ci /* Store and send the Bulk-only CSW */ 1000beacf11bSopenharmony_ci 1001beacf11bSopenharmony_ci csw->dCSWSignature = BULK_CSW_SIGN; 1002beacf11bSopenharmony_ci csw->dCSWTag = fmass->tag; 1003beacf11bSopenharmony_ci csw->dCSWResidue = fmass->residue; 1004beacf11bSopenharmony_ci csw->bCSWStatus = status; 1005beacf11bSopenharmony_ci 1006beacf11bSopenharmony_ci /* submit csw packet to controller */ 1007beacf11bSopenharmony_ci 1008beacf11bSopenharmony_ci fmass->bulkreq.len = BULK_CSW_WRAP_LEN; 1009beacf11bSopenharmony_ci (void)fmass_bulkin_request(fmass, &fmass->bulkreq); 1010beacf11bSopenharmony_ci 1011beacf11bSopenharmony_ci /* wait csw packet transfer finish */ 1012beacf11bSopenharmony_ci 1013beacf11bSopenharmony_ci if (!fmass_wait_intr(fmass, taskstate_unmatch(fmass, FMASS_TASK_REQ_STATUS_PHASE), (5 * HZ))) 1014beacf11bSopenharmony_ci { 1015beacf11bSopenharmony_ci DPRINTFN(0, "--- [CSW Phase] timeout! state: %u ---\n", fmass->task_state); 1016beacf11bSopenharmony_ci if (taskstate_match(fmass, FMASS_TASK_REQ_STATUS_PHASE)) 1017beacf11bSopenharmony_ci { 1018beacf11bSopenharmony_ci fmass_task_change_state(fmass, FMASS_TASK_IDLE); 1019beacf11bSopenharmony_ci } 1020beacf11bSopenharmony_ci return ; 1021beacf11bSopenharmony_ci } 1022beacf11bSopenharmony_ci 1023beacf11bSopenharmony_ci if (taskstate_unmatch(fmass, FMASS_TASK_DONE_STATUS_PHASE)) 1024beacf11bSopenharmony_ci { 1025beacf11bSopenharmony_ci DPRINTFN(0, "--- [CSW Phase] unmatch! unexpect state: %u ---\n", fmass->task_state); 1026beacf11bSopenharmony_ci return ; 1027beacf11bSopenharmony_ci } 1028beacf11bSopenharmony_ci 1029beacf11bSopenharmony_ci DPRINTFN(1, "\t -----CSW Transfer Finish -----\n"); 1030beacf11bSopenharmony_ci fmass_task_change_state(fmass, FMASS_TASK_REQ_COMMAND_PHASE); 1031beacf11bSopenharmony_ci fmass->csw.bCSWStatus = BULK_CSW_STAT_OK; 1032beacf11bSopenharmony_ci} 1033beacf11bSopenharmony_ci 1034beacf11bSopenharmony_cistatic void fmass_parts_registered(struct mass_dev_s *fmass, const char *dev_path) 1035beacf11bSopenharmony_ci{ 1036beacf11bSopenharmony_ci#define NODE_NAME_LEN 0x10 1037beacf11bSopenharmony_ci char node_name[NODE_NAME_LEN]; 1038beacf11bSopenharmony_ci struct inode *inode; 1039beacf11bSopenharmony_ci los_part *part; 1040beacf11bSopenharmony_ci int i; 1041beacf11bSopenharmony_ci 1042beacf11bSopenharmony_ci for (i = 0; i < MAX_FILE_STORAGE_LUNS; i++) 1043beacf11bSopenharmony_ci { 1044beacf11bSopenharmony_ci inode = NULL; 1045beacf11bSopenharmony_ci (void)snprintf_s(node_name, sizeof(node_name), sizeof(node_name) - 1, "%s%0d", dev_path, i); 1046beacf11bSopenharmony_ci (void)open_blockdriver(node_name, O_RDWR, &inode); 1047beacf11bSopenharmony_ci if (inode == NULL) 1048beacf11bSopenharmony_ci { 1049beacf11bSopenharmony_ci return; 1050beacf11bSopenharmony_ci } 1051beacf11bSopenharmony_ci part = los_part_find(inode); 1052beacf11bSopenharmony_ci if (part == NULL) 1053beacf11bSopenharmony_ci { 1054beacf11bSopenharmony_ci (void)close_blockdriver(inode); 1055beacf11bSopenharmony_ci continue; 1056beacf11bSopenharmony_ci } 1057beacf11bSopenharmony_ci 1058beacf11bSopenharmony_ci if (fmass->nluns == MAX_FILE_STORAGE_LUNS) 1059beacf11bSopenharmony_ci { 1060beacf11bSopenharmony_ci break; 1061beacf11bSopenharmony_ci } 1062beacf11bSopenharmony_ci 1063beacf11bSopenharmony_ci fmass->fileNode[fmass->nluns] = inode; 1064beacf11bSopenharmony_ci fmass->parts[fmass->nluns] = part; 1065beacf11bSopenharmony_ci fmass->nluns++; 1066beacf11bSopenharmony_ci } 1067beacf11bSopenharmony_ci 1068beacf11bSopenharmony_ci return; 1069beacf11bSopenharmony_ci} 1070beacf11bSopenharmony_ci 1071beacf11bSopenharmony_cistatic int fmass_dev_open(struct mass_dev_s *fmass) 1072beacf11bSopenharmony_ci{ 1073beacf11bSopenharmony_ci uint32_t i; 1074beacf11bSopenharmony_ci 1075beacf11bSopenharmony_ci for (i = 0; i < sizeof(g_mass_device_type) / sizeof(g_mass_device_type[0]); i++) 1076beacf11bSopenharmony_ci { 1077beacf11bSopenharmony_ci fmass_parts_registered(fmass, g_mass_device_type[i]); 1078beacf11bSopenharmony_ci } 1079beacf11bSopenharmony_ci 1080beacf11bSopenharmony_ci if (fmass->nluns == 0) 1081beacf11bSopenharmony_ci { 1082beacf11bSopenharmony_ci usb_err("device inode is unavailable!\n"); 1083beacf11bSopenharmony_ci return -1; 1084beacf11bSopenharmony_ci } 1085beacf11bSopenharmony_ci 1086beacf11bSopenharmony_ci for (i = 0 ; i < MAX_DATA_BUFFER_NUM; i++) 1087beacf11bSopenharmony_ci { 1088beacf11bSopenharmony_ci struct fmass_data_buf_t *db = &fmass->databuf[i]; 1089beacf11bSopenharmony_ci 1090beacf11bSopenharmony_ci if (db->buf != NULL) 1091beacf11bSopenharmony_ci { 1092beacf11bSopenharmony_ci continue; 1093beacf11bSopenharmony_ci } 1094beacf11bSopenharmony_ci 1095beacf11bSopenharmony_ci db->buf = memalign(64, SKB_DATA_ALIGN(MAX_BLOCK_RW_SECTORS << 9)); 1096beacf11bSopenharmony_ci if (db->buf == NULL) 1097beacf11bSopenharmony_ci { 1098beacf11bSopenharmony_ci return -1; 1099beacf11bSopenharmony_ci } 1100beacf11bSopenharmony_ci db->state = DBUF_STATE_EMPTY; 1101beacf11bSopenharmony_ci db->next = db + 1; 1102beacf11bSopenharmony_ci } 1103beacf11bSopenharmony_ci fmass->databuf[i - 1].next = &fmass->databuf[0]; 1104beacf11bSopenharmony_ci 1105beacf11bSopenharmony_ci fmass->dev_status = DEV_ST_CONNECTTED; 1106beacf11bSopenharmony_ci fmass_notify_report(fmass, fmass->dev_status); 1107beacf11bSopenharmony_ci 1108beacf11bSopenharmony_ci return 0; 1109beacf11bSopenharmony_ci} 1110beacf11bSopenharmony_ci 1111beacf11bSopenharmony_cistatic int fmass_dev_close(struct mass_dev_s *fmass) 1112beacf11bSopenharmony_ci{ 1113beacf11bSopenharmony_ci uint32_t i; 1114beacf11bSopenharmony_ci FAR struct inode *inode; 1115beacf11bSopenharmony_ci 1116beacf11bSopenharmony_ci if (fmass->nluns == 0) 1117beacf11bSopenharmony_ci { 1118beacf11bSopenharmony_ci return -1; 1119beacf11bSopenharmony_ci } 1120beacf11bSopenharmony_ci 1121beacf11bSopenharmony_ci for (i = 0 ; i < fmass->nluns ; i++) 1122beacf11bSopenharmony_ci { 1123beacf11bSopenharmony_ci inode = fmass->fileNode[i]; 1124beacf11bSopenharmony_ci (void)close_blockdriver(inode); 1125beacf11bSopenharmony_ci fmass->fileNode[i] = NULL; 1126beacf11bSopenharmony_ci fmass->parts[i] = NULL; 1127beacf11bSopenharmony_ci } 1128beacf11bSopenharmony_ci 1129beacf11bSopenharmony_ci for (i = 0 ; i < MAX_DATA_BUFFER_NUM; i++) 1130beacf11bSopenharmony_ci { 1131beacf11bSopenharmony_ci free(fmass->databuf[i].buf); 1132beacf11bSopenharmony_ci fmass->databuf[i].buf = NULL; 1133beacf11bSopenharmony_ci } 1134beacf11bSopenharmony_ci fmass->nluns = 0; 1135beacf11bSopenharmony_ci return 0; 1136beacf11bSopenharmony_ci} 1137beacf11bSopenharmony_ci 1138beacf11bSopenharmony_cistatic void fmass_dev_capacity(struct mass_dev_s *fmass) 1139beacf11bSopenharmony_ci{ 1140beacf11bSopenharmony_ci uint32_t i; 1141beacf11bSopenharmony_ci los_part *part; 1142beacf11bSopenharmony_ci struct fmass_capacity *cap; 1143beacf11bSopenharmony_ci 1144beacf11bSopenharmony_ci for (i = 0; i < fmass->nluns; i++) 1145beacf11bSopenharmony_ci { 1146beacf11bSopenharmony_ci part = fmass->parts[i]; 1147beacf11bSopenharmony_ci cap = &fmass->caps[i]; 1148beacf11bSopenharmony_ci cap->sectorsize = 0; 1149beacf11bSopenharmony_ci cap->nsectors = 0; 1150beacf11bSopenharmony_ci 1151beacf11bSopenharmony_ci (void)los_part_ioctl(part->part_id, GET_SECTOR_COUNT, &cap->nsectors); 1152beacf11bSopenharmony_ci cap->nsectors += part->sector_start; 1153beacf11bSopenharmony_ci (void)los_part_ioctl(part->part_id, GET_SECTOR_SIZE, &cap->sectorsize); 1154beacf11bSopenharmony_ci PRINTK("*** %d %d Bytes/Sector, Total %d Sectors ***\n", i, (int)cap->sectorsize, (int)cap->nsectors); 1155beacf11bSopenharmony_ci } 1156beacf11bSopenharmony_ci} 1157beacf11bSopenharmony_ci 1158beacf11bSopenharmony_cistatic size_t fmass_dev_read(struct mass_dev_s *fmass, 1159beacf11bSopenharmony_ci uint8_t *buffer, 1160beacf11bSopenharmony_ci size_t stsector, 1161beacf11bSopenharmony_ci uint32_t nsectors) 1162beacf11bSopenharmony_ci{ 1163beacf11bSopenharmony_ci size_t rsectors = 0; 1164beacf11bSopenharmony_ci los_part *part = fmass->parts[fmass->lun]; 1165beacf11bSopenharmony_ci 1166beacf11bSopenharmony_ci if (part != NULL) 1167beacf11bSopenharmony_ci { 1168beacf11bSopenharmony_ci int ret = los_part_read(part->part_id, buffer, stsector, nsectors); 1169beacf11bSopenharmony_ci if (ret == 0) 1170beacf11bSopenharmony_ci { 1171beacf11bSopenharmony_ci rsectors = nsectors; 1172beacf11bSopenharmony_ci } 1173beacf11bSopenharmony_ci } 1174beacf11bSopenharmony_ci return rsectors; 1175beacf11bSopenharmony_ci} 1176beacf11bSopenharmony_ci 1177beacf11bSopenharmony_cistatic size_t fmass_dev_write(struct mass_dev_s *fmass, 1178beacf11bSopenharmony_ci uint8_t *buffer, 1179beacf11bSopenharmony_ci size_t stsector, 1180beacf11bSopenharmony_ci uint32_t nsectors) 1181beacf11bSopenharmony_ci{ 1182beacf11bSopenharmony_ci size_t wsectors = 0; 1183beacf11bSopenharmony_ci los_part *part = fmass->parts[fmass->lun]; 1184beacf11bSopenharmony_ci 1185beacf11bSopenharmony_ci if (part != NULL) 1186beacf11bSopenharmony_ci { 1187beacf11bSopenharmony_ci int ret = los_part_write(part->part_id, buffer, stsector, nsectors); 1188beacf11bSopenharmony_ci if (ret == 0) 1189beacf11bSopenharmony_ci { 1190beacf11bSopenharmony_ci wsectors = nsectors; 1191beacf11bSopenharmony_ci } 1192beacf11bSopenharmony_ci } 1193beacf11bSopenharmony_ci return wsectors; 1194beacf11bSopenharmony_ci} 1195beacf11bSopenharmony_ci 1196beacf11bSopenharmony_civoid fmass_set_config(struct mass_dev_s *fmass, struct usbdev_s *dev) 1197beacf11bSopenharmony_ci{ 1198beacf11bSopenharmony_ci struct usbdev_ep_s *ep0; 1199beacf11bSopenharmony_ci struct usbdev_req_s *req; 1200beacf11bSopenharmony_ci 1201beacf11bSopenharmony_ci if (dev->ep0 == NULL || dev->ep0->handle_req == NULL) 1202beacf11bSopenharmony_ci { 1203beacf11bSopenharmony_ci usb_err("set config fail!\n"); 1204beacf11bSopenharmony_ci return; 1205beacf11bSopenharmony_ci } 1206beacf11bSopenharmony_ci ep0 = dev->ep0; 1207beacf11bSopenharmony_ci req = ep0->handle_req; 1208beacf11bSopenharmony_ci 1209beacf11bSopenharmony_ci if (fmass->nluns == 0) 1210beacf11bSopenharmony_ci { 1211beacf11bSopenharmony_ci if (fmass_dev_open(fmass) == 0) 1212beacf11bSopenharmony_ci { 1213beacf11bSopenharmony_ci fmass_dev_capacity(fmass); 1214beacf11bSopenharmony_ci } 1215beacf11bSopenharmony_ci else 1216beacf11bSopenharmony_ci { 1217beacf11bSopenharmony_ci usb_err("can not found inode!\n"); 1218beacf11bSopenharmony_ci return; 1219beacf11bSopenharmony_ci } 1220beacf11bSopenharmony_ci } 1221beacf11bSopenharmony_ci 1222beacf11bSopenharmony_ci if (fmass->bulk_in_enabled) 1223beacf11bSopenharmony_ci { 1224beacf11bSopenharmony_ci fmass->bulk_in_enabled = 0; 1225beacf11bSopenharmony_ci (void)EP_DISABLE(fmass->bulkin); 1226beacf11bSopenharmony_ci } 1227beacf11bSopenharmony_ci 1228beacf11bSopenharmony_ci if (fmass->bulk_out_enabled) 1229beacf11bSopenharmony_ci { 1230beacf11bSopenharmony_ci fmass->bulk_out_enabled = 0; 1231beacf11bSopenharmony_ci (void)EP_DISABLE(fmass->bulkout); 1232beacf11bSopenharmony_ci } 1233beacf11bSopenharmony_ci 1234beacf11bSopenharmony_ci usbd_configep_byspeed(dev, &g_fmass_confd.iepd); 1235beacf11bSopenharmony_ci (void)EP_CONFIGURE(fmass->bulkin, (const usb_endpoint_descriptor_t *)&g_fmass_confd.iepd, 0); 1236beacf11bSopenharmony_ci fmass->bulk_in_enabled = 1; 1237beacf11bSopenharmony_ci 1238beacf11bSopenharmony_ci usbd_configep_byspeed(dev, &g_fmass_confd.oepd); 1239beacf11bSopenharmony_ci (void)EP_CONFIGURE(fmass->bulkout, (const usb_endpoint_descriptor_t *)&g_fmass_confd.oepd, 0); 1240beacf11bSopenharmony_ci fmass->bulk_out_enabled = 1; 1241beacf11bSopenharmony_ci 1242beacf11bSopenharmony_ci fmass->databuf_fill = &fmass->databuf[0]; 1243beacf11bSopenharmony_ci fmass->bulkreq.buf = (uint8_t *)fmass->databuf[0].buf; 1244beacf11bSopenharmony_ci fmass->bulkreq.is_complete = 1; 1245beacf11bSopenharmony_ci 1246beacf11bSopenharmony_ci req->len = 0; 1247beacf11bSopenharmony_ci (void)EP_SUBMIT(ep0, req); 1248beacf11bSopenharmony_ci 1249beacf11bSopenharmony_ci fmass_task_change_state(fmass, FMASS_TASK_REQ_COMMAND_PHASE); 1250beacf11bSopenharmony_ci} 1251beacf11bSopenharmony_ci 1252beacf11bSopenharmony_civoid fmass_set_next_command(struct mass_dev_s *fmass) 1253beacf11bSopenharmony_ci{ 1254beacf11bSopenharmony_ci fmass_task_state next_state; 1255beacf11bSopenharmony_ci 1256beacf11bSopenharmony_ci DPRINTFN(1, "\n\t -----REQUEST CBW packet -------\n"); 1257beacf11bSopenharmony_ci 1258beacf11bSopenharmony_ci fmass->bulkreq.len = BULK_CBW_WRAP_LEN; 1259beacf11bSopenharmony_ci 1260beacf11bSopenharmony_ci /* start a request to receive a CBW packet */ 1261beacf11bSopenharmony_ci 1262beacf11bSopenharmony_ci (void)fmass_bulkout_request(fmass, &fmass->bulkreq); 1263beacf11bSopenharmony_ci 1264beacf11bSopenharmony_ci /* wait for the CBW packet */ 1265beacf11bSopenharmony_ci 1266beacf11bSopenharmony_ci if (!fmass_wait_intr(fmass, taskstate_unmatch(fmass, FMASS_TASK_REQ_COMMAND_PHASE), osWaitForever)) 1267beacf11bSopenharmony_ci { 1268beacf11bSopenharmony_ci DPRINTFN(0, "--- [CBW Phase] error! state: %u ---\n", fmass->task_state); 1269beacf11bSopenharmony_ci if (taskstate_match(fmass, FMASS_TASK_REQ_COMMAND_PHASE)) 1270beacf11bSopenharmony_ci { 1271beacf11bSopenharmony_ci fmass_task_change_state(fmass, FMASS_TASK_IDLE); 1272beacf11bSopenharmony_ci } 1273beacf11bSopenharmony_ci return; 1274beacf11bSopenharmony_ci } 1275beacf11bSopenharmony_ci 1276beacf11bSopenharmony_ci if (taskstate_unmatch(fmass, FMASS_TASK_DONE_COMMAND_PHASE)) 1277beacf11bSopenharmony_ci { 1278beacf11bSopenharmony_ci DPRINTFN(0, "--- [CBW Phase] unmatch! unexpect state: %u ---\n", fmass->task_state); 1279beacf11bSopenharmony_ci return ; 1280beacf11bSopenharmony_ci } 1281beacf11bSopenharmony_ci 1282beacf11bSopenharmony_ci /* check and receive CBW packet */ 1283beacf11bSopenharmony_ci 1284beacf11bSopenharmony_ci if (fmass_check_receive_cbw(fmass) < 0) 1285beacf11bSopenharmony_ci { 1286beacf11bSopenharmony_ci return ; 1287beacf11bSopenharmony_ci } 1288beacf11bSopenharmony_ci 1289beacf11bSopenharmony_ci /* handle CBW packet */ 1290beacf11bSopenharmony_ci 1291beacf11bSopenharmony_ci fmass_do_scsi_command(fmass); 1292beacf11bSopenharmony_ci if (taskstate_unmatch(fmass, FMASS_TASK_DISCONNECT)) 1293beacf11bSopenharmony_ci { 1294beacf11bSopenharmony_ci if (fmass->data_size) 1295beacf11bSopenharmony_ci { 1296beacf11bSopenharmony_ci next_state = FMASS_TASK_REQ_DATA_PHASE; 1297beacf11bSopenharmony_ci } 1298beacf11bSopenharmony_ci else 1299beacf11bSopenharmony_ci { 1300beacf11bSopenharmony_ci next_state = FMASS_TASK_REQ_STATUS_PHASE; 1301beacf11bSopenharmony_ci } 1302beacf11bSopenharmony_ci fmass_task_change_state(fmass, next_state); 1303beacf11bSopenharmony_ci } 1304beacf11bSopenharmony_ci} 1305beacf11bSopenharmony_ci 1306beacf11bSopenharmony_cistatic void *fmass_main_thread(UINTPTR para, UINTPTR para1) 1307beacf11bSopenharmony_ci{ 1308beacf11bSopenharmony_ci struct mass_dev_s *fmass = (struct mass_dev_s *)para; 1309beacf11bSopenharmony_ci struct usbdev_s *dev = (struct usbdev_s *)para1; 1310beacf11bSopenharmony_ci uint32_t oldstate = FMASS_TASK_IDLE; 1311beacf11bSopenharmony_ci uint32_t curstate = fmass->task_state; 1312beacf11bSopenharmony_ci PEVENT_CB_S fmass_event = &fmass->task_event; 1313beacf11bSopenharmony_ci uint32_t ret; 1314beacf11bSopenharmony_ci 1315beacf11bSopenharmony_ci while (1) 1316beacf11bSopenharmony_ci { 1317beacf11bSopenharmony_ci if (oldstate == curstate) 1318beacf11bSopenharmony_ci { 1319beacf11bSopenharmony_ci DPRINTFN(1, "\n -- process thread wait --(curstate:%u)\n", fmass->task_state); 1320beacf11bSopenharmony_ci ret = LOS_EventRead(fmass_event, (FMASS_DATA_PROC | FMASS_NEED_EXIT), 1321beacf11bSopenharmony_ci LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER); 1322beacf11bSopenharmony_ci if (ret & FMASS_NEED_EXIT) 1323beacf11bSopenharmony_ci { 1324beacf11bSopenharmony_ci break; 1325beacf11bSopenharmony_ci } 1326beacf11bSopenharmony_ci curstate = fmass->task_state; 1327beacf11bSopenharmony_ci } 1328beacf11bSopenharmony_ci oldstate = curstate; 1329beacf11bSopenharmony_ci 1330beacf11bSopenharmony_ci if (taskstate_match(fmass, FMASS_TASK_DISCONNECT)) 1331beacf11bSopenharmony_ci { 1332beacf11bSopenharmony_ci fmass_report_usb_status(fmass); 1333beacf11bSopenharmony_ci fmass->task_state &= ~FMASS_TASK_DISCONNECT; 1334beacf11bSopenharmony_ci ret = LOS_EventPoll(&(fmass_event->uwEventID), FMASS_NEED_EXIT, 1335beacf11bSopenharmony_ci LOS_WAITMODE_OR | LOS_WAITMODE_CLR); 1336beacf11bSopenharmony_ci if (ret == FMASS_NEED_EXIT) 1337beacf11bSopenharmony_ci { 1338beacf11bSopenharmony_ci break; 1339beacf11bSopenharmony_ci } 1340beacf11bSopenharmony_ci } 1341beacf11bSopenharmony_ci else 1342beacf11bSopenharmony_ci { 1343beacf11bSopenharmony_ci switch (curstate) 1344beacf11bSopenharmony_ci { 1345beacf11bSopenharmony_ci case FMASS_TASK_CONFIG_CHANGE: 1346beacf11bSopenharmony_ci fmass_set_config(fmass, dev); 1347beacf11bSopenharmony_ci break; 1348beacf11bSopenharmony_ci 1349beacf11bSopenharmony_ci case FMASS_TASK_REQ_COMMAND_PHASE: 1350beacf11bSopenharmony_ci fmass_set_next_command(fmass); 1351beacf11bSopenharmony_ci break; 1352beacf11bSopenharmony_ci 1353beacf11bSopenharmony_ci case FMASS_TASK_REQ_DATA_PHASE: 1354beacf11bSopenharmony_ci fmass_handle_scsi_data(fmass); 1355beacf11bSopenharmony_ci break; 1356beacf11bSopenharmony_ci 1357beacf11bSopenharmony_ci case FMASS_TASK_REQ_STATUS_PHASE: 1358beacf11bSopenharmony_ci fmass_set_scsi_status(fmass); 1359beacf11bSopenharmony_ci break; 1360beacf11bSopenharmony_ci 1361beacf11bSopenharmony_ci default: 1362beacf11bSopenharmony_ci break; 1363beacf11bSopenharmony_ci } 1364beacf11bSopenharmony_ci } 1365beacf11bSopenharmony_ci 1366beacf11bSopenharmony_ci curstate = fmass->task_state; 1367beacf11bSopenharmony_ci } 1368beacf11bSopenharmony_ci 1369beacf11bSopenharmony_ci (void)LOS_EventWrite(&(fmass->task_event), FMASS_THREAD_EXITED); 1370beacf11bSopenharmony_ci 1371beacf11bSopenharmony_ci return NULL; 1372beacf11bSopenharmony_ci} 1373beacf11bSopenharmony_ci 1374beacf11bSopenharmony_cistatic void fmass_task_change_state(struct mass_dev_s *fmass, fmass_task_state new_state) 1375beacf11bSopenharmony_ci{ 1376beacf11bSopenharmony_ci uint32_t flags; 1377beacf11bSopenharmony_ci uint32_t old_state = fmass->task_state; 1378beacf11bSopenharmony_ci 1379beacf11bSopenharmony_ci spin_lock_irqsave(&fmass->lock, flags); 1380beacf11bSopenharmony_ci 1381beacf11bSopenharmony_ci if (taskstate_unmatch(fmass, FMASS_TASK_DISCONNECT)) 1382beacf11bSopenharmony_ci { 1383beacf11bSopenharmony_ci fmass->task_state &= ~old_state; 1384beacf11bSopenharmony_ci } 1385beacf11bSopenharmony_ci fmass->task_state |= new_state; 1386beacf11bSopenharmony_ci 1387beacf11bSopenharmony_ci spin_unlock_irqrestore(&fmass->lock, flags); 1388beacf11bSopenharmony_ci} 1389beacf11bSopenharmony_ci 1390beacf11bSopenharmony_cistatic void fmass_main_thread_signal(struct mass_dev_s *fmass, fmass_task_state state) 1391beacf11bSopenharmony_ci{ 1392beacf11bSopenharmony_ci DPRINTFN(1, " - process thread signal -(curstate:%u newstate: %d)\n", fmass->task_state, state); 1393beacf11bSopenharmony_ci fmass_task_change_state(fmass, state); 1394beacf11bSopenharmony_ci (void)LOS_EventWrite(&(fmass->task_event), FMASS_DATA_PROC); 1395beacf11bSopenharmony_ci} 1396beacf11bSopenharmony_ci 1397beacf11bSopenharmony_cistatic uint32_t usb_task_creat(uint32_t *taskid, TSK_ENTRY_FUNC func, uint16_t prio, 1398beacf11bSopenharmony_ci const char *nm, UINTPTR para, UINTPTR para1) 1399beacf11bSopenharmony_ci{ 1400beacf11bSopenharmony_ci uint32_t ret; 1401beacf11bSopenharmony_ci TSK_INIT_PARAM_S attr; 1402beacf11bSopenharmony_ci 1403beacf11bSopenharmony_ci (void)memset_s(&attr, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); 1404beacf11bSopenharmony_ci 1405beacf11bSopenharmony_ci attr.pfnTaskEntry = func; 1406beacf11bSopenharmony_ci attr.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; 1407beacf11bSopenharmony_ci attr.auwArgs[0] = (UINTPTR)para; 1408beacf11bSopenharmony_ci attr.auwArgs[1] = (UINTPTR)para1; 1409beacf11bSopenharmony_ci attr.usTaskPrio = prio; 1410beacf11bSopenharmony_ci attr.pcName = (char *)nm; 1411beacf11bSopenharmony_ci attr.uwResved = LOS_TASK_STATUS_DETACHED; 1412beacf11bSopenharmony_ci 1413beacf11bSopenharmony_ci ret = LOS_TaskCreate(taskid, &attr); 1414beacf11bSopenharmony_ci if (ret != LOS_OK) 1415beacf11bSopenharmony_ci { 1416beacf11bSopenharmony_ci usb_err("create %s task error!\n", nm); 1417beacf11bSopenharmony_ci } 1418beacf11bSopenharmony_ci return ret; 1419beacf11bSopenharmony_ci} 1420beacf11bSopenharmony_ci 1421beacf11bSopenharmony_cistatic int fmass_thread_init(struct mass_dev_s *fmass, struct usbdev_s *dev) 1422beacf11bSopenharmony_ci{ 1423beacf11bSopenharmony_ci uint32_t td = 0; 1424beacf11bSopenharmony_ci uint32_t ret; 1425beacf11bSopenharmony_ci 1426beacf11bSopenharmony_ci (void)LOS_EventInit(&fmass->task_event); 1427beacf11bSopenharmony_ci mtx_init(&fmass->task_mtx, "tmtx", NULL, 0); 1428beacf11bSopenharmony_ci init_waitqueue_head(&fmass->xfer_wait); 1429beacf11bSopenharmony_ci 1430beacf11bSopenharmony_ci fmass_task_change_state(fmass, FMASS_TASK_IDLE); 1431beacf11bSopenharmony_ci 1432beacf11bSopenharmony_ci ret = usb_task_creat(&td, (TSK_ENTRY_FUNC)fmass_main_thread, 10, "USB_FMASS_Task", (UINTPTR)fmass, (UINTPTR)dev); 1433beacf11bSopenharmony_ci return (ret == 0) ? (0) : (-1); 1434beacf11bSopenharmony_ci} 1435beacf11bSopenharmony_ci 1436beacf11bSopenharmony_cistatic int fmass_thread_delete(struct mass_dev_s *fmass) 1437beacf11bSopenharmony_ci{ 1438beacf11bSopenharmony_ci uint32_t ret; 1439beacf11bSopenharmony_ci 1440beacf11bSopenharmony_ci (void)LOS_EventWrite(&(fmass->task_event), FMASS_NEED_EXIT); 1441beacf11bSopenharmony_ci ret = LOS_EventRead(&fmass->task_event, FMASS_THREAD_EXITED, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, (10 * HZ)); 1442beacf11bSopenharmony_ci if (ret == LOS_ERRNO_EVENT_READ_TIMEOUT) 1443beacf11bSopenharmony_ci { 1444beacf11bSopenharmony_ci usb_err("fmass, wait thread exit timeout\n"); 1445beacf11bSopenharmony_ci return -1; 1446beacf11bSopenharmony_ci } 1447beacf11bSopenharmony_ci 1448beacf11bSopenharmony_ci (void)LOS_EventDestroy(&fmass->task_event); 1449beacf11bSopenharmony_ci mtx_destroy(&fmass->task_mtx); 1450beacf11bSopenharmony_ci 1451beacf11bSopenharmony_ci return 0; 1452beacf11bSopenharmony_ci} 1453beacf11bSopenharmony_ci 1454beacf11bSopenharmony_cistatic void fmass_notify_report(struct mass_dev_s *fmass, int status) 1455beacf11bSopenharmony_ci{ 1456beacf11bSopenharmony_ci int i ; 1457beacf11bSopenharmony_ci struct fmass_notify *notify; 1458beacf11bSopenharmony_ci 1459beacf11bSopenharmony_ci DPRINTFN(1, "\n< fmass storage %s >\n", (status == DEV_ST_CONNECTTED) ? "connected" : "disconnected"); 1460beacf11bSopenharmony_ci for (i = 0; i < MAX_NOFIFY_NUM ; i++) 1461beacf11bSopenharmony_ci { 1462beacf11bSopenharmony_ci notify = &fmass->notify[i]; 1463beacf11bSopenharmony_ci if (notify->is_used) 1464beacf11bSopenharmony_ci { 1465beacf11bSopenharmony_ci if (notify->notifycb != NULL) 1466beacf11bSopenharmony_ci { 1467beacf11bSopenharmony_ci notify->notifycb(notify->notifydata, status); 1468beacf11bSopenharmony_ci } 1469beacf11bSopenharmony_ci } 1470beacf11bSopenharmony_ci } 1471beacf11bSopenharmony_ci} 1472beacf11bSopenharmony_ci 1473beacf11bSopenharmony_cistatic void fmass_report_usb_status(struct mass_dev_s *fmass) 1474beacf11bSopenharmony_ci{ 1475beacf11bSopenharmony_ci if (fmass->dev_status == DEV_ST_DISCONNECT) 1476beacf11bSopenharmony_ci { 1477beacf11bSopenharmony_ci if (fmass->nluns == 0) /* device is not ready, skip disconnect status */ 1478beacf11bSopenharmony_ci { 1479beacf11bSopenharmony_ci fmass_task_change_state(fmass, FMASS_TASK_IDLE); 1480beacf11bSopenharmony_ci return; 1481beacf11bSopenharmony_ci } 1482beacf11bSopenharmony_ci (void)fmass_dev_close(fmass); 1483beacf11bSopenharmony_ci } 1484beacf11bSopenharmony_ci 1485beacf11bSopenharmony_ci fmass_notify_report(fmass, fmass->dev_status); 1486beacf11bSopenharmony_ci fmass_task_change_state(fmass, FMASS_TASK_IDLE); 1487beacf11bSopenharmony_ci} 1488beacf11bSopenharmony_ci 1489beacf11bSopenharmony_ci/* status 0: disconnect 1: connect */ 1490beacf11bSopenharmony_ci 1491beacf11bSopenharmony_ciint fmass_register_notify(void(*notify)(void *context, int status), void *context) 1492beacf11bSopenharmony_ci{ 1493beacf11bSopenharmony_ci int i; 1494beacf11bSopenharmony_ci struct fmass_notify *f_notify = g_notify.notify; 1495beacf11bSopenharmony_ci struct mtx *notify_mtx = &g_notify.notify_mtx; 1496beacf11bSopenharmony_ci 1497beacf11bSopenharmony_ci fmass_notify_init(); 1498beacf11bSopenharmony_ci 1499beacf11bSopenharmony_ci mtx_lock(notify_mtx); 1500beacf11bSopenharmony_ci for (i = 0; i < MAX_NOFIFY_NUM ; i++) 1501beacf11bSopenharmony_ci { 1502beacf11bSopenharmony_ci if (f_notify[i].is_used == 0) 1503beacf11bSopenharmony_ci { 1504beacf11bSopenharmony_ci f_notify[i].is_used = 1; 1505beacf11bSopenharmony_ci f_notify[i].notifycb = notify; 1506beacf11bSopenharmony_ci f_notify[i].notifydata = context; 1507beacf11bSopenharmony_ci break; 1508beacf11bSopenharmony_ci } 1509beacf11bSopenharmony_ci } 1510beacf11bSopenharmony_ci mtx_unlock(notify_mtx); 1511beacf11bSopenharmony_ci return (i < MAX_NOFIFY_NUM) ? (i) : (-1); 1512beacf11bSopenharmony_ci} 1513beacf11bSopenharmony_ci 1514beacf11bSopenharmony_ciint fmass_unregister_notify(int handle) 1515beacf11bSopenharmony_ci{ 1516beacf11bSopenharmony_ci struct fmass_notify *f_notify = g_notify.notify; 1517beacf11bSopenharmony_ci struct mtx *notify_mtx = &g_notify.notify_mtx; 1518beacf11bSopenharmony_ci 1519beacf11bSopenharmony_ci if (handle < 0 || handle >= MAX_NOFIFY_NUM) 1520beacf11bSopenharmony_ci { 1521beacf11bSopenharmony_ci return -1; 1522beacf11bSopenharmony_ci } 1523beacf11bSopenharmony_ci 1524beacf11bSopenharmony_ci mtx_lock(notify_mtx); 1525beacf11bSopenharmony_ci if (f_notify[handle].is_used == 0) 1526beacf11bSopenharmony_ci { 1527beacf11bSopenharmony_ci mtx_unlock(notify_mtx); 1528beacf11bSopenharmony_ci return -1; 1529beacf11bSopenharmony_ci } 1530beacf11bSopenharmony_ci 1531beacf11bSopenharmony_ci f_notify[handle].is_used = 0; 1532beacf11bSopenharmony_ci f_notify[handle].notifycb = NULL; 1533beacf11bSopenharmony_ci f_notify[handle].notifydata = NULL; 1534beacf11bSopenharmony_ci mtx_unlock(notify_mtx); 1535beacf11bSopenharmony_ci 1536beacf11bSopenharmony_ci return 0; 1537beacf11bSopenharmony_ci} 1538beacf11bSopenharmony_ci 1539beacf11bSopenharmony_ciint fmass_partition_startup(const char *path) 1540beacf11bSopenharmony_ci{ 1541beacf11bSopenharmony_ci struct mass_softc *mass = g_fmass; 1542beacf11bSopenharmony_ci struct mass_dev_s *fmass; 1543beacf11bSopenharmony_ci FAR struct inode *inode = NULL; 1544beacf11bSopenharmony_ci uint32_t i; 1545beacf11bSopenharmony_ci int ret; 1546beacf11bSopenharmony_ci 1547beacf11bSopenharmony_ci if (mass == NULL) 1548beacf11bSopenharmony_ci { 1549beacf11bSopenharmony_ci return -1; 1550beacf11bSopenharmony_ci } 1551beacf11bSopenharmony_ci fmass = &mass->dev; 1552beacf11bSopenharmony_ci 1553beacf11bSopenharmony_ci ret = open_blockdriver(path, O_RDWR, &inode); 1554beacf11bSopenharmony_ci if (inode == NULL || ret != ENOERR) 1555beacf11bSopenharmony_ci { 1556beacf11bSopenharmony_ci DPRINTFN(0, "open blockdriver %s fail ret = %d\n", path, ret); 1557beacf11bSopenharmony_ci return -1; 1558beacf11bSopenharmony_ci } 1559beacf11bSopenharmony_ci 1560beacf11bSopenharmony_ci for (i = 0; i < fmass->nluns; i++) 1561beacf11bSopenharmony_ci { 1562beacf11bSopenharmony_ci if (inode == fmass->fileNode[i]) 1563beacf11bSopenharmony_ci { 1564beacf11bSopenharmony_ci fmass->lun = i; 1565beacf11bSopenharmony_ci break; 1566beacf11bSopenharmony_ci } 1567beacf11bSopenharmony_ci } 1568beacf11bSopenharmony_ci 1569beacf11bSopenharmony_ci if (i == fmass->nluns) 1570beacf11bSopenharmony_ci { 1571beacf11bSopenharmony_ci usb_err("The device path is invalid\n"); 1572beacf11bSopenharmony_ci return -1; 1573beacf11bSopenharmony_ci } 1574beacf11bSopenharmony_ci 1575beacf11bSopenharmony_ci return 0; 1576beacf11bSopenharmony_ci} 1577beacf11bSopenharmony_ci 1578beacf11bSopenharmony_civoid *fmass_bind(void) 1579beacf11bSopenharmony_ci{ 1580beacf11bSopenharmony_ci return (void *)g_fmass; 1581beacf11bSopenharmony_ci} 1582beacf11bSopenharmony_ci 1583beacf11bSopenharmony_cistatic void fmass_source_free(void) 1584beacf11bSopenharmony_ci{ 1585beacf11bSopenharmony_ci g_fmass = NULL; 1586beacf11bSopenharmony_ci} 1587beacf11bSopenharmony_ci 1588beacf11bSopenharmony_cistatic int usbclass_mass_bind(struct usbdevclass_driver_s *driver, struct usbdev_s *dev) 1589beacf11bSopenharmony_ci{ 1590beacf11bSopenharmony_ci struct usbdev_ep_s *ep; 1591beacf11bSopenharmony_ci struct mass_driver_s *mass_drvr; 1592beacf11bSopenharmony_ci struct mass_dev_s *mass_dev; 1593beacf11bSopenharmony_ci 1594beacf11bSopenharmony_ci if (driver == NULL || dev == NULL) 1595beacf11bSopenharmony_ci { 1596beacf11bSopenharmony_ci return -1; 1597beacf11bSopenharmony_ci } 1598beacf11bSopenharmony_ci 1599beacf11bSopenharmony_ci mass_drvr = (struct mass_driver_s *)driver; 1600beacf11bSopenharmony_ci mass_dev = mass_drvr->dev; 1601beacf11bSopenharmony_ci if (mass_dev == NULL) 1602beacf11bSopenharmony_ci { 1603beacf11bSopenharmony_ci return -1; 1604beacf11bSopenharmony_ci } 1605beacf11bSopenharmony_ci 1606beacf11bSopenharmony_ci (void)snprintf_s(mass_dev->inquiry_str, sizeof(mass_dev->inquiry_str), sizeof(mass_dev->inquiry_str) - 1, 1607beacf11bSopenharmony_ci "%-8s%-16s%-4s","Mass","Storage Device","1.00"); 1608beacf11bSopenharmony_ci mass_dev->notify = g_notify.notify; 1609beacf11bSopenharmony_ci mass_dev->lun = 0; 1610beacf11bSopenharmony_ci mass_dev->nluns = 0; 1611beacf11bSopenharmony_ci 1612beacf11bSopenharmony_ci ep = DEV_ALLOCEP(dev, g_fmass_confd.iepd.bEndpointAddress, 1613beacf11bSopenharmony_ci (struct usb_endpoint_descriptor *)&g_fmass_confd.iepd); 1614beacf11bSopenharmony_ci if (ep == NULL) 1615beacf11bSopenharmony_ci { 1616beacf11bSopenharmony_ci PRINT_ERR("%s,%d\n", __FUNCTION__, __LINE__); 1617beacf11bSopenharmony_ci return -1; 1618beacf11bSopenharmony_ci } 1619beacf11bSopenharmony_ci ep->priv = (void *)mass_dev; 1620beacf11bSopenharmony_ci ep->handle_req = &mass_dev->bulkreq; 1621beacf11bSopenharmony_ci mass_dev->bulkin = ep; 1622beacf11bSopenharmony_ci DPRINTFN(1, "bulkin:%#x, %02x\n", ep, ep->eplog); 1623beacf11bSopenharmony_ci 1624beacf11bSopenharmony_ci ep = DEV_ALLOCEP(dev, g_fmass_confd.oepd.bEndpointAddress, 1625beacf11bSopenharmony_ci (struct usb_endpoint_descriptor *)&g_fmass_confd.oepd); 1626beacf11bSopenharmony_ci if (ep == NULL) 1627beacf11bSopenharmony_ci { 1628beacf11bSopenharmony_ci PRINT_ERR("%s,%d\n", __FUNCTION__, __LINE__); 1629beacf11bSopenharmony_ci return -1; 1630beacf11bSopenharmony_ci } 1631beacf11bSopenharmony_ci ep->priv = (void *)mass_dev; 1632beacf11bSopenharmony_ci ep->handle_req = &mass_dev->bulkreq; 1633beacf11bSopenharmony_ci mass_dev->bulkout = ep; 1634beacf11bSopenharmony_ci DPRINTFN(1, "bulkout:%#x, %02x\n", ep, ep->eplog); 1635beacf11bSopenharmony_ci 1636beacf11bSopenharmony_ci if (fmass_thread_init(mass_dev, dev) < 0) 1637beacf11bSopenharmony_ci { 1638beacf11bSopenharmony_ci PRINT_ERR("fmass_thread_init failed\n"); 1639beacf11bSopenharmony_ci goto fail; 1640beacf11bSopenharmony_ci } 1641beacf11bSopenharmony_ci 1642beacf11bSopenharmony_ci return 0; 1643beacf11bSopenharmony_cifail: 1644beacf11bSopenharmony_ci usb_err("composite_fmass_bind failed\n"); 1645beacf11bSopenharmony_ci (void)usbclass_mass_unbind(driver, dev); 1646beacf11bSopenharmony_ci return -1; 1647beacf11bSopenharmony_ci} 1648beacf11bSopenharmony_ci 1649beacf11bSopenharmony_cistatic int usbclass_mass_unbind(struct usbdevclass_driver_s *driver, struct usbdev_s *dev) 1650beacf11bSopenharmony_ci{ 1651beacf11bSopenharmony_ci struct mass_driver_s *mass_drvr; 1652beacf11bSopenharmony_ci struct mass_dev_s *mass_dev; 1653beacf11bSopenharmony_ci int ret; 1654beacf11bSopenharmony_ci 1655beacf11bSopenharmony_ci if (driver == NULL || dev == NULL) 1656beacf11bSopenharmony_ci { 1657beacf11bSopenharmony_ci return -1; 1658beacf11bSopenharmony_ci } 1659beacf11bSopenharmony_ci 1660beacf11bSopenharmony_ci mass_drvr = (struct mass_driver_s *)driver; 1661beacf11bSopenharmony_ci mass_dev = mass_drvr->dev; 1662beacf11bSopenharmony_ci if (mass_dev == NULL) 1663beacf11bSopenharmony_ci { 1664beacf11bSopenharmony_ci return -1; 1665beacf11bSopenharmony_ci } 1666beacf11bSopenharmony_ci 1667beacf11bSopenharmony_ci if (mass_dev->dev_status == DEV_ST_CONNECTTED) 1668beacf11bSopenharmony_ci { 1669beacf11bSopenharmony_ci ret = fmass_dev_close(mass_dev); 1670beacf11bSopenharmony_ci if (ret < 0) 1671beacf11bSopenharmony_ci { 1672beacf11bSopenharmony_ci PRINT_ERR("%s fmass dev close fail\n", __FUNCTION__); 1673beacf11bSopenharmony_ci return -1; 1674beacf11bSopenharmony_ci } 1675beacf11bSopenharmony_ci } 1676beacf11bSopenharmony_ci 1677beacf11bSopenharmony_ci if (driver->ops != NULL && driver->ops->disconnect != NULL) 1678beacf11bSopenharmony_ci { 1679beacf11bSopenharmony_ci driver->ops->disconnect(driver, dev); 1680beacf11bSopenharmony_ci } 1681beacf11bSopenharmony_ci 1682beacf11bSopenharmony_ci DEV_FREEEP(dev, mass_dev->bulkin); 1683beacf11bSopenharmony_ci DEV_FREEEP(dev, mass_dev->bulkout); 1684beacf11bSopenharmony_ci 1685beacf11bSopenharmony_ci ret = fmass_thread_delete(mass_dev); 1686beacf11bSopenharmony_ci if (ret < 0) 1687beacf11bSopenharmony_ci { 1688beacf11bSopenharmony_ci return -1; 1689beacf11bSopenharmony_ci } 1690beacf11bSopenharmony_ci fmass_source_free(); 1691beacf11bSopenharmony_ci 1692beacf11bSopenharmony_ci return 0; 1693beacf11bSopenharmony_ci} 1694beacf11bSopenharmony_ci 1695beacf11bSopenharmony_cistatic int usbclass_mass_set_alt(struct mass_dev_s *mass, unsigned intf, unsigned alt) 1696beacf11bSopenharmony_ci{ 1697beacf11bSopenharmony_ci (void)intf; 1698beacf11bSopenharmony_ci (void)alt; 1699beacf11bSopenharmony_ci 1700beacf11bSopenharmony_ci fmass_main_thread_signal(mass, FMASS_TASK_CONFIG_CHANGE); 1701beacf11bSopenharmony_ci fmass_wakeup(mass); 1702beacf11bSopenharmony_ci 1703beacf11bSopenharmony_ci /* the '1' indecates that the invoking of 'usbd_endpoint_request' is in fmass's protocal */ 1704beacf11bSopenharmony_ci 1705beacf11bSopenharmony_ci return 1; 1706beacf11bSopenharmony_ci} 1707beacf11bSopenharmony_ci 1708beacf11bSopenharmony_cistatic int usbclass_mass_setup(struct usbdevclass_driver_s *driver, struct usbdev_s *dev, 1709beacf11bSopenharmony_ci const struct usb_device_request *ctrl, uint8_t *dataout, size_t outlen) 1710beacf11bSopenharmony_ci{ 1711beacf11bSopenharmony_ci struct mass_dev_s *mass; 1712beacf11bSopenharmony_ci struct mass_driver_s *drvr; 1713beacf11bSopenharmony_ci uint16_t w_index; 1714beacf11bSopenharmony_ci uint16_t w_value; 1715beacf11bSopenharmony_ci uint16_t w_length; 1716beacf11bSopenharmony_ci struct usbdev_req_s *req; 1717beacf11bSopenharmony_ci errno_t ret; 1718beacf11bSopenharmony_ci uint32_t nlun_info; 1719beacf11bSopenharmony_ci 1720beacf11bSopenharmony_ci (void)dataout; 1721beacf11bSopenharmony_ci (void)outlen; 1722beacf11bSopenharmony_ci 1723beacf11bSopenharmony_ci if (driver == NULL || ctrl == NULL || dev == NULL) 1724beacf11bSopenharmony_ci { 1725beacf11bSopenharmony_ci return -1; 1726beacf11bSopenharmony_ci } 1727beacf11bSopenharmony_ci 1728beacf11bSopenharmony_ci drvr = (struct mass_driver_s *)driver; 1729beacf11bSopenharmony_ci mass = drvr->dev; 1730beacf11bSopenharmony_ci if (mass == NULL) 1731beacf11bSopenharmony_ci { 1732beacf11bSopenharmony_ci return -1; 1733beacf11bSopenharmony_ci } 1734beacf11bSopenharmony_ci w_index = UGETW(ctrl->wIndex); 1735beacf11bSopenharmony_ci w_value = UGETW(ctrl->wValue); 1736beacf11bSopenharmony_ci w_length = UGETW(ctrl->wLength); 1737beacf11bSopenharmony_ci 1738beacf11bSopenharmony_ci req = dev->ep0->handle_req; 1739beacf11bSopenharmony_ci 1740beacf11bSopenharmony_ci switch (ctrl->bRequest) 1741beacf11bSopenharmony_ci { 1742beacf11bSopenharmony_ci case USB_REQ_SET_CONFIGURATION: 1743beacf11bSopenharmony_ci case USB_REQ_SET_INTERFACE: 1744beacf11bSopenharmony_ci { 1745beacf11bSopenharmony_ci return usbclass_mass_set_alt(mass, w_index, w_value); 1746beacf11bSopenharmony_ci } 1747beacf11bSopenharmony_ci case USB_BULK_GET_MAX_LUN: 1748beacf11bSopenharmony_ci { 1749beacf11bSopenharmony_ci if (ctrl->bmRequestType != (USB_DIR_IN | 1750beacf11bSopenharmony_ci USB_TYPE_CLASS | USB_RECIP_INTERFACE)) 1751beacf11bSopenharmony_ci { 1752beacf11bSopenharmony_ci break; 1753beacf11bSopenharmony_ci } 1754beacf11bSopenharmony_ci 1755beacf11bSopenharmony_ci if (w_index != 0 || w_value != 0 || w_length != 1) 1756beacf11bSopenharmony_ci { 1757beacf11bSopenharmony_ci break; 1758beacf11bSopenharmony_ci } 1759beacf11bSopenharmony_ci 1760beacf11bSopenharmony_ci nlun_info = mass->nluns ? (mass->nluns - 1) : (0); 1761beacf11bSopenharmony_ci ret = memcpy_s(req->buf, USB_COMP_EP0_BUFSIZ, &nlun_info, sizeof(nlun_info)); 1762beacf11bSopenharmony_ci if (ret != EOK) 1763beacf11bSopenharmony_ci { 1764beacf11bSopenharmony_ci usb_err("memcpy_s fail, %d \n", ret); 1765beacf11bSopenharmony_ci return -1; 1766beacf11bSopenharmony_ci } 1767beacf11bSopenharmony_ci req->len = 1; 1768beacf11bSopenharmony_ci (void)EP_SUBMIT(dev->ep0, req); 1769beacf11bSopenharmony_ci PRINTK("****** USB BULK MAX LUN %u ******\n", mass->nluns); 1770beacf11bSopenharmony_ci } 1771beacf11bSopenharmony_ci break; 1772beacf11bSopenharmony_ci 1773beacf11bSopenharmony_ci default: 1774beacf11bSopenharmony_ci break; 1775beacf11bSopenharmony_ci } 1776beacf11bSopenharmony_ci return 0; 1777beacf11bSopenharmony_ci} 1778beacf11bSopenharmony_ci 1779beacf11bSopenharmony_cistatic void usbclass_mass_disconnect(struct usbdevclass_driver_s *driver, struct usbdev_s *dev) 1780beacf11bSopenharmony_ci{ 1781beacf11bSopenharmony_ci struct mass_dev_s *mass; 1782beacf11bSopenharmony_ci struct mass_driver_s *drvr; 1783beacf11bSopenharmony_ci uint32_t flags; 1784beacf11bSopenharmony_ci 1785beacf11bSopenharmony_ci if (driver == NULL || dev == NULL) 1786beacf11bSopenharmony_ci { 1787beacf11bSopenharmony_ci return; 1788beacf11bSopenharmony_ci } 1789beacf11bSopenharmony_ci 1790beacf11bSopenharmony_ci drvr = (struct mass_driver_s *)driver; 1791beacf11bSopenharmony_ci mass = drvr->dev; 1792beacf11bSopenharmony_ci if (mass == NULL) 1793beacf11bSopenharmony_ci { 1794beacf11bSopenharmony_ci return; 1795beacf11bSopenharmony_ci } 1796beacf11bSopenharmony_ci 1797beacf11bSopenharmony_ci spin_lock_irqsave(&mass->lock, flags); 1798beacf11bSopenharmony_ci if (taskstate_match(mass, FMASS_TASK_CONFIG_CHANGE)) 1799beacf11bSopenharmony_ci { 1800beacf11bSopenharmony_ci spin_unlock_irqrestore(&mass->lock, flags); 1801beacf11bSopenharmony_ci DPRINTFN(0, "Setting config, no need proc disconnect\n"); 1802beacf11bSopenharmony_ci return; 1803beacf11bSopenharmony_ci } 1804beacf11bSopenharmony_ci 1805beacf11bSopenharmony_ci mass->dev_status = DEV_ST_DISCONNECT; 1806beacf11bSopenharmony_ci spin_unlock_irqrestore(&mass->lock, flags); 1807beacf11bSopenharmony_ci 1808beacf11bSopenharmony_ci fmass_task_change_state(mass, FMASS_TASK_DISCONNECT); 1809beacf11bSopenharmony_ci fmass_wakeup(mass); 1810beacf11bSopenharmony_ci 1811beacf11bSopenharmony_ci if (mass->bulk_in_enabled) 1812beacf11bSopenharmony_ci { 1813beacf11bSopenharmony_ci mass->bulk_in_enabled = 0; 1814beacf11bSopenharmony_ci (void)EP_DISABLE(mass->bulkin); 1815beacf11bSopenharmony_ci } 1816beacf11bSopenharmony_ci 1817beacf11bSopenharmony_ci if (mass->bulk_out_enabled) 1818beacf11bSopenharmony_ci { 1819beacf11bSopenharmony_ci mass->bulk_out_enabled = 0; 1820beacf11bSopenharmony_ci (void)EP_DISABLE(mass->bulkout); 1821beacf11bSopenharmony_ci } 1822beacf11bSopenharmony_ci} 1823beacf11bSopenharmony_ci 1824beacf11bSopenharmony_cistruct usbd_string g_fmass_device_strings[6] = 1825beacf11bSopenharmony_ci{ 1826beacf11bSopenharmony_ci { 0, g_dt_string_id }, 1827beacf11bSopenharmony_ci { 1, g_dt_string_vid }, 1828beacf11bSopenharmony_ci { 2, g_dt_string_pid }, 1829beacf11bSopenharmony_ci { 3, g_dt_string_serial }, 1830beacf11bSopenharmony_ci { 4, g_dt_string_buf }, 1831beacf11bSopenharmony_ci USBD_DEVICE_STRINGS_END 1832beacf11bSopenharmony_ci}; 1833beacf11bSopenharmony_ci 1834beacf11bSopenharmony_civoid mass_mkdevdesc(uint8_t *buf) 1835beacf11bSopenharmony_ci{ 1836beacf11bSopenharmony_ci errno_t ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, &g_fmass_device_desc, sizeof(g_fmass_device_desc)); 1837beacf11bSopenharmony_ci if (ret != EOK) 1838beacf11bSopenharmony_ci { 1839beacf11bSopenharmony_ci usb_err("memcpy_s fail!, ret:%d\n", ret); 1840beacf11bSopenharmony_ci return; 1841beacf11bSopenharmony_ci } 1842beacf11bSopenharmony_ci} 1843beacf11bSopenharmony_ci 1844beacf11bSopenharmony_ciint16_t mass_mkcfgdesc(uint8_t *buf, struct usbdev_devinfo_s *devinfo) 1845beacf11bSopenharmony_ci{ 1846beacf11bSopenharmony_ci uint16_t total = UGETW(g_fmass_confd.confd.wTotalLength); 1847beacf11bSopenharmony_ci errno_t ret; 1848beacf11bSopenharmony_ci 1849beacf11bSopenharmony_ci ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, &g_fmass_confd, total); 1850beacf11bSopenharmony_ci if (ret != EOK) 1851beacf11bSopenharmony_ci { 1852beacf11bSopenharmony_ci usb_err("memcpy_s fail!, ret:%d\n", ret); 1853beacf11bSopenharmony_ci return -1; 1854beacf11bSopenharmony_ci } 1855beacf11bSopenharmony_ci 1856beacf11bSopenharmony_ci return (int16_t)total; 1857beacf11bSopenharmony_ci} 1858beacf11bSopenharmony_ci 1859beacf11bSopenharmony_ciint mass_mkstrdesc(uint8_t id, uint8_t *buf) 1860beacf11bSopenharmony_ci{ 1861beacf11bSopenharmony_ci errno_t ret; 1862beacf11bSopenharmony_ci const char *str; 1863beacf11bSopenharmony_ci int i; 1864beacf11bSopenharmony_ci 1865beacf11bSopenharmony_ci for (i = 0; g_fmass_device_strings[i].s != NULL; i++) 1866beacf11bSopenharmony_ci { 1867beacf11bSopenharmony_ci str = g_fmass_device_strings[i].s; 1868beacf11bSopenharmony_ci if (g_fmass_device_strings[i].id == id) 1869beacf11bSopenharmony_ci { 1870beacf11bSopenharmony_ci ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, str, str[0]); 1871beacf11bSopenharmony_ci if (ret != EOK) 1872beacf11bSopenharmony_ci { 1873beacf11bSopenharmony_ci usb_err("memcpy_s failed, ret = %d\n", ret); 1874beacf11bSopenharmony_ci return -1; 1875beacf11bSopenharmony_ci } 1876beacf11bSopenharmony_ci return str[0]; 1877beacf11bSopenharmony_ci } 1878beacf11bSopenharmony_ci } 1879beacf11bSopenharmony_ci 1880beacf11bSopenharmony_ci usb_err("Can not find the id = %u of string\n", id); 1881beacf11bSopenharmony_ci return -1; 1882beacf11bSopenharmony_ci} 1883beacf11bSopenharmony_ci 1884beacf11bSopenharmony_ci#define MASS_NCONFIGS 1 1885beacf11bSopenharmony_ci#define MASS_CONFIGID 0 1886beacf11bSopenharmony_ci#define MASS_NINTERFACES 1 1887beacf11bSopenharmony_ci#define MASS_NSTRIDS 5 1888beacf11bSopenharmony_ci#define MASS_NUM_EPS 2 1889beacf11bSopenharmony_civoid mass_get_composite_devdesc(struct composite_devdesc_s *dev) 1890beacf11bSopenharmony_ci{ 1891beacf11bSopenharmony_ci (void)memset_s(dev, sizeof(struct composite_devdesc_s), 0, sizeof(struct composite_devdesc_s)); 1892beacf11bSopenharmony_ci 1893beacf11bSopenharmony_ci dev->mkdevdesc = mass_mkdevdesc; 1894beacf11bSopenharmony_ci dev->mkconfdesc = mass_mkcfgdesc; 1895beacf11bSopenharmony_ci dev->mkstrdesc = mass_mkstrdesc; 1896beacf11bSopenharmony_ci 1897beacf11bSopenharmony_ci dev->nconfigs = MASS_NCONFIGS; /* Number of configurations supported */ 1898beacf11bSopenharmony_ci dev->configid = MASS_CONFIGID; /* The only supported configuration ID */ 1899beacf11bSopenharmony_ci 1900beacf11bSopenharmony_ci /* Interfaces. 1901beacf11bSopenharmony_ci * 1902beacf11bSopenharmony_ci * ifnobase must be provided by board-specific logic 1903beacf11bSopenharmony_ci */ 1904beacf11bSopenharmony_ci 1905beacf11bSopenharmony_ci dev->devinfo.ninterfaces = MASS_NINTERFACES; /* Number of interfaces in the configuration */ 1906beacf11bSopenharmony_ci 1907beacf11bSopenharmony_ci /* Strings. 1908beacf11bSopenharmony_ci * 1909beacf11bSopenharmony_ci * strbase must be provided by board-specific logic 1910beacf11bSopenharmony_ci */ 1911beacf11bSopenharmony_ci 1912beacf11bSopenharmony_ci dev->devinfo.nstrings = MASS_NSTRIDS; /* Number of Strings */ 1913beacf11bSopenharmony_ci 1914beacf11bSopenharmony_ci /* Endpoints. 1915beacf11bSopenharmony_ci * 1916beacf11bSopenharmony_ci * Endpoint numbers must be provided by board-specific logic. 1917beacf11bSopenharmony_ci */ 1918beacf11bSopenharmony_ci 1919beacf11bSopenharmony_ci dev->devinfo.nendpoints = MASS_NUM_EPS; 1920beacf11bSopenharmony_ci} 1921beacf11bSopenharmony_ci 1922beacf11bSopenharmony_ciint mass_classobject(int minor, struct usbdev_devinfo_s *devinfo, 1923beacf11bSopenharmony_ci struct usbdevclass_driver_s **classdev) 1924beacf11bSopenharmony_ci{ 1925beacf11bSopenharmony_ci struct mass_softc *mass_s ; 1926beacf11bSopenharmony_ci struct mass_dev_s *priv; 1927beacf11bSopenharmony_ci struct mass_driver_s *drvr; 1928beacf11bSopenharmony_ci 1929beacf11bSopenharmony_ci (void)minor; 1930beacf11bSopenharmony_ci (void)devinfo; 1931beacf11bSopenharmony_ci 1932beacf11bSopenharmony_ci /* Allocate the structures needed */ 1933beacf11bSopenharmony_ci 1934beacf11bSopenharmony_ci mass_s = (struct mass_softc *)malloc(sizeof(struct mass_softc)); 1935beacf11bSopenharmony_ci if (mass_s == NULL) 1936beacf11bSopenharmony_ci { 1937beacf11bSopenharmony_ci return -1; 1938beacf11bSopenharmony_ci } 1939beacf11bSopenharmony_ci g_fmass = mass_s; 1940beacf11bSopenharmony_ci 1941beacf11bSopenharmony_ci /* Convenience pointers into the allocated blob */ 1942beacf11bSopenharmony_ci 1943beacf11bSopenharmony_ci priv = &mass_s->dev; 1944beacf11bSopenharmony_ci drvr = &mass_s->drvr; 1945beacf11bSopenharmony_ci 1946beacf11bSopenharmony_ci /* Initialize the USB serial driver structure */ 1947beacf11bSopenharmony_ci 1948beacf11bSopenharmony_ci (void)memset_s(priv, sizeof(struct mass_dev_s), 0, sizeof(struct mass_dev_s)); 1949beacf11bSopenharmony_ci spin_lock_init(&priv->lock); 1950beacf11bSopenharmony_ci 1951beacf11bSopenharmony_ci /* Initialize the USB class driver structure */ 1952beacf11bSopenharmony_ci 1953beacf11bSopenharmony_ci drvr->drvr.speed = USB_SPEED_HIGH; 1954beacf11bSopenharmony_ci drvr->drvr.ops = &g_mass_driverops; 1955beacf11bSopenharmony_ci drvr->dev = priv; 1956beacf11bSopenharmony_ci 1957beacf11bSopenharmony_ci *classdev = &drvr->drvr; 1958beacf11bSopenharmony_ci return 0; 1959beacf11bSopenharmony_ci} 1960beacf11bSopenharmony_ci 1961beacf11bSopenharmony_civoid mass_uninitialize(struct usbdevclass_driver_s *classdev) 1962beacf11bSopenharmony_ci{ 1963beacf11bSopenharmony_ci struct mass_driver_s *mass_drvr = (struct mass_driver_s *)classdev; 1964beacf11bSopenharmony_ci struct mass_dev_s *priv ; 1965beacf11bSopenharmony_ci struct mass_softc *mass_s; 1966beacf11bSopenharmony_ci 1967beacf11bSopenharmony_ci if (mass_drvr == NULL) 1968beacf11bSopenharmony_ci { 1969beacf11bSopenharmony_ci return; 1970beacf11bSopenharmony_ci } 1971beacf11bSopenharmony_ci 1972beacf11bSopenharmony_ci priv = mass_drvr->dev; 1973beacf11bSopenharmony_ci if (priv == NULL) 1974beacf11bSopenharmony_ci { 1975beacf11bSopenharmony_ci return; 1976beacf11bSopenharmony_ci } 1977beacf11bSopenharmony_ci 1978beacf11bSopenharmony_ci mass_s = container_of(mass_drvr, struct mass_softc, drvr); 1979beacf11bSopenharmony_ci free(mass_s); 1980beacf11bSopenharmony_ci} 1981beacf11bSopenharmony_ci 1982beacf11bSopenharmony_civoid usbdev_mass_initialize_sub(struct composite_devdesc_s *dev, int ifnobase, int minor) 1983beacf11bSopenharmony_ci{ 1984beacf11bSopenharmony_ci /* Ask the UAC driver to fill in the constants we didn't 1985beacf11bSopenharmony_ci * know here. 1986beacf11bSopenharmony_ci */ 1987beacf11bSopenharmony_ci 1988beacf11bSopenharmony_ci mass_get_composite_devdesc(dev); 1989beacf11bSopenharmony_ci 1990beacf11bSopenharmony_ci /* Overwrite and correct some values... */ 1991beacf11bSopenharmony_ci /* The callback functions for the UAC class */ 1992beacf11bSopenharmony_ci 1993beacf11bSopenharmony_ci dev->classobject = mass_classobject; 1994beacf11bSopenharmony_ci dev->uninitialize = mass_uninitialize; 1995beacf11bSopenharmony_ci 1996beacf11bSopenharmony_ci /* Interfaces */ 1997beacf11bSopenharmony_ci 1998beacf11bSopenharmony_ci dev->devinfo.ifnobase = ifnobase; /* Offset to Interface-IDs */ 1999beacf11bSopenharmony_ci dev->minor = minor; /* The minor interface number */ 2000beacf11bSopenharmony_ci 2001beacf11bSopenharmony_ci /* Strings */ 2002beacf11bSopenharmony_ci 2003beacf11bSopenharmony_ci dev->devinfo.strbase = 0; /* Offset to String Numbers */ 2004beacf11bSopenharmony_ci} 2005beacf11bSopenharmony_ci 2006beacf11bSopenharmony_ciint usbdev_mass_initialize(struct module *mod, int n, void *arg) 2007beacf11bSopenharmony_ci{ 2008beacf11bSopenharmony_ci struct composite_softc *com_s = (struct composite_softc *)arg; 2009beacf11bSopenharmony_ci struct composite_devdesc_s dev; 2010beacf11bSopenharmony_ci int ret; 2011beacf11bSopenharmony_ci 2012beacf11bSopenharmony_ci (void)mod; 2013beacf11bSopenharmony_ci (void)n; 2014beacf11bSopenharmony_ci if (com_s == NULL) 2015beacf11bSopenharmony_ci { 2016beacf11bSopenharmony_ci return -1; 2017beacf11bSopenharmony_ci } 2018beacf11bSopenharmony_ci 2019beacf11bSopenharmony_ci usbdev_mass_initialize_sub(&dev, 0, DEV_MASS); 2020beacf11bSopenharmony_ci 2021beacf11bSopenharmony_ci ret = composite_initialize(com_s, 1, &dev); 2022beacf11bSopenharmony_ci if (ret < 0) 2023beacf11bSopenharmony_ci { 2024beacf11bSopenharmony_ci return -1; 2025beacf11bSopenharmony_ci } 2026beacf11bSopenharmony_ci 2027beacf11bSopenharmony_ci PRINTK(" ** Mass device initialized successfully! **\n"); 2028beacf11bSopenharmony_ci return 0; 2029beacf11bSopenharmony_ci} 2030beacf11bSopenharmony_ci 2031beacf11bSopenharmony_ci#undef USB_DEBUG_VAR 2032beacf11bSopenharmony_ci 2033beacf11bSopenharmony_ci#ifdef __cplusplus 2034beacf11bSopenharmony_ci#if __cplusplus 2035beacf11bSopenharmony_ci} 2036beacf11bSopenharmony_ci#endif /* __cplusplus */ 2037beacf11bSopenharmony_ci#endif /* __cplusplus */