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 */