* [PATCH v4 1/3] platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role()
2020-08-20 23:38 [PATCH v4 0/3] TypeC Connector Class driver improvements Azhar Shaikh
@ 2020-08-20 23:38 ` Azhar Shaikh
2020-08-20 23:38 ` [PATCH v4 2/3] platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect Azhar Shaikh
` (2 subsequent siblings)
3 siblings, 0 replies; 8+ messages in thread
From: Azhar Shaikh @ 2020-08-20 23:38 UTC (permalink / raw)
To: bleung, enric.balletbo, groeck, heikki.krogerus, pmalani
Cc: linux-kernel, azhar.shaikh, rajmohan.mani, utkarsh.h.patel,
casey.g.bowman
usb_role_switch_set_role() has the second argument as enum for usb_role.
Currently depending upon the data role i.e. UFP(0) or DFP(1) is sent.
This eventually translates to USB_ROLE_NONE in case of UFP and
USB_ROLE_DEVICE in case of DFP. Correct this by sending correct enum
values as USB_ROLE_DEVICE in case of UFP and USB_ROLE_HOST in case of
DFP.
Fixes: 7e7def15fa4b ("platform/chrome: cros_ec_typec: Add USB mux control")
Signed-off-by: Azhar Shaikh <azhar.shaikh@intel.com>
Cc: Prashant Malani <pmalani@chromium.org>
Reviewed-by: Prashant Malani <pmalani@chromium.org>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
---
Changes in v4:
- Remove extra line between Fixes and Signed-off tag.
- Added Reviewed-by and Cc tags from v1 and v2.
Changes in v3:
- No changes
Changes in v2:
- Update the commit message to change 'USB_ROLE_HOST in case of
UFP.' to 'USB_ROLE_HOST in case of DFP.'
drivers/platform/chrome/cros_ec_typec.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
index 3fcd27ec9ad8..06108212ee94 100644
--- a/drivers/platform/chrome/cros_ec_typec.c
+++ b/drivers/platform/chrome/cros_ec_typec.c
@@ -591,7 +591,8 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret);
return usb_role_switch_set_role(typec->ports[port_num]->role_sw,
- !!(resp.role & PD_CTRL_RESP_ROLE_DATA));
+ resp.role & PD_CTRL_RESP_ROLE_DATA
+ ? USB_ROLE_HOST : USB_ROLE_DEVICE);
}
static int cros_typec_get_cmd_version(struct cros_typec_data *typec)
--
2.17.1
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v4 2/3] platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect
2020-08-20 23:38 [PATCH v4 0/3] TypeC Connector Class driver improvements Azhar Shaikh
2020-08-20 23:38 ` [PATCH v4 1/3] platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role() Azhar Shaikh
@ 2020-08-20 23:38 ` Azhar Shaikh
2020-08-20 23:38 ` [PATCH v4 3/3] platform/chrome: cros_ec_typec: Re-order connector configuration steps Azhar Shaikh
2020-08-21 7:13 ` [PATCH v4 0/3] TypeC Connector Class driver improvements Enric Balletbo i Serra
3 siblings, 0 replies; 8+ messages in thread
From: Azhar Shaikh @ 2020-08-20 23:38 UTC (permalink / raw)
To: bleung, enric.balletbo, groeck, heikki.krogerus, pmalani
Cc: linux-kernel, azhar.shaikh, rajmohan.mani, utkarsh.h.patel,
casey.g.bowman
On disconnect port partner is removed and usb role is set to NONE.
But then in cros_typec_port_update() the role is set again.
Avoid this by moving usb_role_switch_set_role() to
cros_typec_configure_mux().
Suggested-by: Prashant Malani <pmalani@chromium.org>
Signed-off-by: Azhar Shaikh <azhar.shaikh@intel.com>
---
Changes in v4:
- Added Suggested-by from v2.
Changes in v3:
- Move the location of calling usb_role_switch_set_role() to
end of function in cros_typec_configure_mux() to avoid any change
in code flow.
Changes in v2:
- New patch added
drivers/platform/chrome/cros_ec_typec.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
index 06108212ee94..2b43e1176e73 100644
--- a/drivers/platform/chrome/cros_ec_typec.c
+++ b/drivers/platform/chrome/cros_ec_typec.c
@@ -533,7 +533,12 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
ret = -ENOTSUPP;
}
- return ret;
+ if (ret)
+ return ret;
+
+ return usb_role_switch_set_role(typec->ports[port_num]->role_sw,
+ pd_ctrl->role & PD_CTRL_RESP_ROLE_DATA
+ ? USB_ROLE_HOST : USB_ROLE_DEVICE);
}
static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
@@ -590,9 +595,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
if (ret)
dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret);
- return usb_role_switch_set_role(typec->ports[port_num]->role_sw,
- resp.role & PD_CTRL_RESP_ROLE_DATA
- ? USB_ROLE_HOST : USB_ROLE_DEVICE);
+ return ret;
}
static int cros_typec_get_cmd_version(struct cros_typec_data *typec)
--
2.17.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v4 3/3] platform/chrome: cros_ec_typec: Re-order connector configuration steps
2020-08-20 23:38 [PATCH v4 0/3] TypeC Connector Class driver improvements Azhar Shaikh
2020-08-20 23:38 ` [PATCH v4 1/3] platform/chrome: cros_ec_typec: Send enum values to usb_role_switch_set_role() Azhar Shaikh
2020-08-20 23:38 ` [PATCH v4 2/3] platform/chrome: cros_ec_typec: Avoid setting usb role twice during disconnect Azhar Shaikh
@ 2020-08-20 23:38 ` Azhar Shaikh
2020-08-21 0:01 ` Prashant Malani
2020-08-21 7:13 ` [PATCH v4 0/3] TypeC Connector Class driver improvements Enric Balletbo i Serra
3 siblings, 1 reply; 8+ messages in thread
From: Azhar Shaikh @ 2020-08-20 23:38 UTC (permalink / raw)
To: bleung, enric.balletbo, groeck, heikki.krogerus, pmalani
Cc: linux-kernel, azhar.shaikh, rajmohan.mani, utkarsh.h.patel,
casey.g.bowman
As per USB Type-C Spec R2.0 section 4.5.1.2 (Connecting Sources and Sinks)
and section 4.5.2.2 (Connection State Machine Requirements), the typical
flow for configuring a device connected to a typeC port is as below:
1. Source/sink detection
2. Orientation
3. Data role
4. VCONN
5. VBUS (USB Type-C currents)
6. The connector is now configured. We can start the PD communication
that should lead into configuration of the mux if we enter a mode.
But in existing code data role was set after the connector and mux are
already configured. So fix this by following the spec to set the data
role before the connector and mux are configured.
Signed-off-by: Azhar Shaikh <azhar.shaikh@intel.com>
---
Changes in v4:
- No change
Changes in v3:
- New patch added
drivers/platform/chrome/cros_ec_typec.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
index 2b43e1176e73..9e4fad9ca59e 100644
--- a/drivers/platform/chrome/cros_ec_typec.c
+++ b/drivers/platform/chrome/cros_ec_typec.c
@@ -516,6 +516,12 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
if (ret)
return ret;
+ ret = usb_role_switch_set_role(typec->ports[port_num]->role_sw,
+ pd_ctrl->role & PD_CTRL_RESP_ROLE_DATA
+ ? USB_ROLE_HOST : USB_ROLE_DEVICE);
+ if (ret)
+ return ret;
+
if (mux_flags & USB_PD_MUX_TBT_COMPAT_ENABLED) {
ret = cros_typec_enable_tbt(typec, port_num, pd_ctrl);
} else if (mux_flags & USB_PD_MUX_DP_ENABLED) {
@@ -533,12 +539,7 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
ret = -ENOTSUPP;
}
- if (ret)
- return ret;
-
- return usb_role_switch_set_role(typec->ports[port_num]->role_sw,
- pd_ctrl->role & PD_CTRL_RESP_ROLE_DATA
- ? USB_ROLE_HOST : USB_ROLE_DEVICE);
+ return ret;
}
static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
--
2.17.1
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v4 3/3] platform/chrome: cros_ec_typec: Re-order connector configuration steps
2020-08-20 23:38 ` [PATCH v4 3/3] platform/chrome: cros_ec_typec: Re-order connector configuration steps Azhar Shaikh
@ 2020-08-21 0:01 ` Prashant Malani
0 siblings, 0 replies; 8+ messages in thread
From: Prashant Malani @ 2020-08-21 0:01 UTC (permalink / raw)
To: Azhar Shaikh
Cc: bleung, enric.balletbo, groeck, heikki.krogerus, linux-kernel,
rajmohan.mani, utkarsh.h.patel, casey.g.bowman
On Thu, Aug 20, 2020 at 04:38:32PM -0700, Azhar Shaikh wrote:
> As per USB Type-C Spec R2.0 section 4.5.1.2 (Connecting Sources and Sinks)
> and section 4.5.2.2 (Connection State Machine Requirements), the typical
> flow for configuring a device connected to a typeC port is as below:
>
> 1. Source/sink detection
> 2. Orientation
> 3. Data role
> 4. VCONN
> 5. VBUS (USB Type-C currents)
> 6. The connector is now configured. We can start the PD communication
> that should lead into configuration of the mux if we enter a mode.
>
> But in existing code data role was set after the connector and mux are
> already configured. So fix this by following the spec to set the data
> role before the connector and mux are configured.
>
> Signed-off-by: Azhar Shaikh <azhar.shaikh@intel.com>
To be clear, I still maintain that the quoted section pertains to
*detection* of those various properties (which is handled by the TCPM in
the Chrome OS EC), and not any ordering for setting switches etc.
That said, I'm not opposed to the re-ordering, so:
Reviewed-by: Prashant Malani <pmalani@chromium.org>
> ---
> Changes in v4:
> - No change
>
> Changes in v3:
> - New patch added
>
> drivers/platform/chrome/cros_ec_typec.c | 13 +++++++------
> 1 file changed, 7 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
> index 2b43e1176e73..9e4fad9ca59e 100644
> --- a/drivers/platform/chrome/cros_ec_typec.c
> +++ b/drivers/platform/chrome/cros_ec_typec.c
> @@ -516,6 +516,12 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
> if (ret)
> return ret;
>
> + ret = usb_role_switch_set_role(typec->ports[port_num]->role_sw,
> + pd_ctrl->role & PD_CTRL_RESP_ROLE_DATA
> + ? USB_ROLE_HOST : USB_ROLE_DEVICE);
> + if (ret)
> + return ret;
> +
> if (mux_flags & USB_PD_MUX_TBT_COMPAT_ENABLED) {
> ret = cros_typec_enable_tbt(typec, port_num, pd_ctrl);
> } else if (mux_flags & USB_PD_MUX_DP_ENABLED) {
> @@ -533,12 +539,7 @@ static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
> ret = -ENOTSUPP;
> }
>
> - if (ret)
> - return ret;
> -
> - return usb_role_switch_set_role(typec->ports[port_num]->role_sw,
> - pd_ctrl->role & PD_CTRL_RESP_ROLE_DATA
> - ? USB_ROLE_HOST : USB_ROLE_DEVICE);
> + return ret;
> }
>
> static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
> --
> 2.17.1
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v4 0/3] TypeC Connector Class driver improvements
2020-08-20 23:38 [PATCH v4 0/3] TypeC Connector Class driver improvements Azhar Shaikh
` (2 preceding siblings ...)
2020-08-20 23:38 ` [PATCH v4 3/3] platform/chrome: cros_ec_typec: Re-order connector configuration steps Azhar Shaikh
@ 2020-08-21 7:13 ` Enric Balletbo i Serra
2020-08-21 13:34 ` Shaikh, Azhar
3 siblings, 1 reply; 8+ messages in thread
From: Enric Balletbo i Serra @ 2020-08-21 7:13 UTC (permalink / raw)
To: Azhar Shaikh, bleung, groeck, heikki.krogerus, pmalani
Cc: linux-kernel, rajmohan.mani, utkarsh.h.patel, casey.g.bowman
Hi Azhar,
I got a merge conflict because I applied [1] before these patches, fix the
conflict is trivial but, as I can't test, can you rebase your patches on top of
[1] and test and resend to make sure everything is working?
Thanks,
Enric
[1] https://lkml.org/lkml/2020/7/10/1063
On 21/8/20 1:38, Azhar Shaikh wrote:
> Changes in v4:
> * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to
> usb_role_switch_set_role()"
> - Remove extra line between Fixes and Signed-off tag.
> - Added Reviewed-by and Cc tags from v1 and v2.
>
> * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice
> during disconnect"
> - Added Suggested-by from v2.
>
> * Patch 3: "platform/chrome: cros_ec_typec: Re-order connector
> configuration steps"
> - No change
>
> Changes in v3:
> * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to
> usb_role_switch_set_role()"
> - No change
>
> * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice
> during disconnect"
> - Move the location of calling usb_role_switch_set_role() to
> end of function in cros_typec_configure_mux() to avoid any change
> in code flow.
>
> * Patch 3: "platform/chrome: cros_ec_typec: Re-order connector
> configuration steps"
> - New patch added
>
> Changes in v2:
> * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to
> usb_role_switch_set_role()"
> - Update the commit message to change 'USB_ROLE_HOST in case of
> UFP.' to 'USB_ROLE_HOST in case of DFP.'
>
> * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice
> during disconnect"
> - New patch added.
>
> Azhar Shaikh (3):
> platform/chrome: cros_ec_typec: Send enum values to
> usb_role_switch_set_role()
> platform/chrome: cros_ec_typec: Avoid setting usb role twice during
> disconnect
> platform/chrome: cros_ec_typec: Re-order connector configuration steps
>
> drivers/platform/chrome/cros_ec_typec.c | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
>
^ permalink raw reply [flat|nested] 8+ messages in thread* RE: [PATCH v4 0/3] TypeC Connector Class driver improvements
2020-08-21 7:13 ` [PATCH v4 0/3] TypeC Connector Class driver improvements Enric Balletbo i Serra
@ 2020-08-21 13:34 ` Shaikh, Azhar
2020-08-21 13:36 ` Heikki Krogerus
0 siblings, 1 reply; 8+ messages in thread
From: Shaikh, Azhar @ 2020-08-21 13:34 UTC (permalink / raw)
To: Enric Balletbo i Serra, bleung@chromium.org, groeck@chromium.org,
heikki.krogerus@linux.intel.com, pmalani@chromium.org
Cc: linux-kernel@vger.kernel.org, Mani, Rajmohan, Patel, Utkarsh H,
Bowman, Casey G
Hi Enric,
Sure, I will rebase, test and upload a new revision.
Regards,
Azhar Shaikh
> -----Original Message-----
> From: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> Sent: Friday, August 21, 2020 12:13 AM
> To: Shaikh, Azhar <azhar.shaikh@intel.com>; bleung@chromium.org;
> groeck@chromium.org; heikki.krogerus@linux.intel.com;
> pmalani@chromium.org
> Cc: linux-kernel@vger.kernel.org; Mani, Rajmohan
> <rajmohan.mani@intel.com>; Patel, Utkarsh H <utkarsh.h.patel@intel.com>;
> Bowman, Casey G <casey.g.bowman@intel.com>
> Subject: Re: [PATCH v4 0/3] TypeC Connector Class driver improvements
>
> Hi Azhar,
>
> I got a merge conflict because I applied [1] before these patches, fix the
> conflict is trivial but, as I can't test, can you rebase your patches on top of [1]
> and test and resend to make sure everything is working?
>
> Thanks,
> Enric
>
> [1] https://lkml.org/lkml/2020/7/10/1063
>
>
> On 21/8/20 1:38, Azhar Shaikh wrote:
> > Changes in v4:
> > * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to
> > usb_role_switch_set_role()"
> > - Remove extra line between Fixes and Signed-off tag.
> > - Added Reviewed-by and Cc tags from v1 and v2.
> >
> > * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice
> > during disconnect"
> > - Added Suggested-by from v2.
> >
> > * Patch 3: "platform/chrome: cros_ec_typec: Re-order connector
> > configuration steps"
> > - No change
> >
> > Changes in v3:
> > * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to
> > usb_role_switch_set_role()"
> > - No change
> >
> > * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice
> > during disconnect"
> > - Move the location of calling usb_role_switch_set_role() to
> > end of function in cros_typec_configure_mux() to avoid any change
> > in code flow.
> >
> > * Patch 3: "platform/chrome: cros_ec_typec: Re-order connector
> > configuration steps"
> > - New patch added
> >
> > Changes in v2:
> > * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to
> > usb_role_switch_set_role()"
> > - Update the commit message to change 'USB_ROLE_HOST in case of
> > UFP.' to 'USB_ROLE_HOST in case of DFP.'
> >
> > * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice
> > during disconnect"
> > - New patch added.
> >
> > Azhar Shaikh (3):
> > platform/chrome: cros_ec_typec: Send enum values to
> > usb_role_switch_set_role()
> > platform/chrome: cros_ec_typec: Avoid setting usb role twice during
> > disconnect
> > platform/chrome: cros_ec_typec: Re-order connector configuration
> > steps
> >
> > drivers/platform/chrome/cros_ec_typec.c | 9 +++++++--
> > 1 file changed, 7 insertions(+), 2 deletions(-)
> >
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v4 0/3] TypeC Connector Class driver improvements
2020-08-21 13:34 ` Shaikh, Azhar
@ 2020-08-21 13:36 ` Heikki Krogerus
0 siblings, 0 replies; 8+ messages in thread
From: Heikki Krogerus @ 2020-08-21 13:36 UTC (permalink / raw)
To: Shaikh, Azhar
Cc: Enric Balletbo i Serra, bleung@chromium.org, groeck@chromium.org,
pmalani@chromium.org, linux-kernel@vger.kernel.org,
Mani, Rajmohan, Patel, Utkarsh H, Bowman, Casey G
On Fri, Aug 21, 2020 at 01:34:46PM +0000, Shaikh, Azhar wrote:
> Hi Enric,
>
> Sure, I will rebase, test and upload a new revision.
I don't think I have anything to add, so FWIW:
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Regards,
> Azhar Shaikh
>
> > -----Original Message-----
> > From: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> > Sent: Friday, August 21, 2020 12:13 AM
> > To: Shaikh, Azhar <azhar.shaikh@intel.com>; bleung@chromium.org;
> > groeck@chromium.org; heikki.krogerus@linux.intel.com;
> > pmalani@chromium.org
> > Cc: linux-kernel@vger.kernel.org; Mani, Rajmohan
> > <rajmohan.mani@intel.com>; Patel, Utkarsh H <utkarsh.h.patel@intel.com>;
> > Bowman, Casey G <casey.g.bowman@intel.com>
> > Subject: Re: [PATCH v4 0/3] TypeC Connector Class driver improvements
> >
> > Hi Azhar,
> >
> > I got a merge conflict because I applied [1] before these patches, fix the
> > conflict is trivial but, as I can't test, can you rebase your patches on top of [1]
> > and test and resend to make sure everything is working?
> >
> > Thanks,
> > Enric
> >
> > [1] https://lkml.org/lkml/2020/7/10/1063
> >
> >
> > On 21/8/20 1:38, Azhar Shaikh wrote:
> > > Changes in v4:
> > > * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to
> > > usb_role_switch_set_role()"
> > > - Remove extra line between Fixes and Signed-off tag.
> > > - Added Reviewed-by and Cc tags from v1 and v2.
> > >
> > > * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice
> > > during disconnect"
> > > - Added Suggested-by from v2.
> > >
> > > * Patch 3: "platform/chrome: cros_ec_typec: Re-order connector
> > > configuration steps"
> > > - No change
> > >
> > > Changes in v3:
> > > * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to
> > > usb_role_switch_set_role()"
> > > - No change
> > >
> > > * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice
> > > during disconnect"
> > > - Move the location of calling usb_role_switch_set_role() to
> > > end of function in cros_typec_configure_mux() to avoid any change
> > > in code flow.
> > >
> > > * Patch 3: "platform/chrome: cros_ec_typec: Re-order connector
> > > configuration steps"
> > > - New patch added
> > >
> > > Changes in v2:
> > > * Patch 1: "platform/chrome: cros_ec_typec: Send enum values to
> > > usb_role_switch_set_role()"
> > > - Update the commit message to change 'USB_ROLE_HOST in case of
> > > UFP.' to 'USB_ROLE_HOST in case of DFP.'
> > >
> > > * Patch 2: "platform/chrome: cros_ec_typec: Avoid setting usb role twice
> > > during disconnect"
> > > - New patch added.
> > >
> > > Azhar Shaikh (3):
> > > platform/chrome: cros_ec_typec: Send enum values to
> > > usb_role_switch_set_role()
> > > platform/chrome: cros_ec_typec: Avoid setting usb role twice during
> > > disconnect
> > > platform/chrome: cros_ec_typec: Re-order connector configuration
> > > steps
> > >
> > > drivers/platform/chrome/cros_ec_typec.c | 9 +++++++--
> > > 1 file changed, 7 insertions(+), 2 deletions(-)
> > >
thanks,
--
heikki
^ permalink raw reply [flat|nested] 8+ messages in thread