summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2021-09-20 01:41:26 +0100
committerAidan MacDonald <amachronic@protonmail.com>2021-10-16 21:14:42 +0100
commit82efb1150e2c47b13857cc705b46fba4a57a9cf5 (patch)
treed1f695addfc2cc4a736c60c68db3084b75e3c48e
parentdff8320a5d04d74d8a08a81d9e6f6ed296d672ce (diff)
downloadrockbox-82efb1150e2c47b13857cc705b46fba4a57a9cf5.tar.gz
rockbox-82efb1150e2c47b13857cc705b46fba4a57a9cf5.zip
usb: implement new API with legacy emulation layer
All existing USB drivers now define USB_LEGACY_CONTROL_API to enable the emulation layer. Control request handlers will be ported in follow-up commits. Change-Id: I4be1ce7c372f2f6fee5978a4858c841b72e77405
-rw-r--r--firmware/export/config.h4
-rw-r--r--firmware/usbstack/usb_core.c148
2 files changed, 131 insertions, 21 deletions
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 5700fad37f..870ae43785 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -1172,6 +1172,7 @@ Lyre prototype 1 */
1172/* Define the implemented USB transport classes */ 1172/* Define the implemented USB transport classes */
1173#if CONFIG_USBOTG == USBOTG_ISP1583 1173#if CONFIG_USBOTG == USBOTG_ISP1583
1174#define USB_HAS_BULK 1174#define USB_HAS_BULK
1175#define USB_LEGACY_CONTROL_API
1175#elif (CONFIG_USBOTG == USBOTG_ARC) || \ 1176#elif (CONFIG_USBOTG == USBOTG_ARC) || \
1176 (CONFIG_USBOTG == USBOTG_JZ4740) || \ 1177 (CONFIG_USBOTG == USBOTG_JZ4740) || \
1177 (CONFIG_USBOTG == USBOTG_JZ4760) || \ 1178 (CONFIG_USBOTG == USBOTG_JZ4760) || \
@@ -1182,10 +1183,13 @@ Lyre prototype 1 */
1182 (CONFIG_USBOTG == USBOTG_TNETV105) 1183 (CONFIG_USBOTG == USBOTG_TNETV105)
1183#define USB_HAS_BULK 1184#define USB_HAS_BULK
1184#define USB_HAS_INTERRUPT 1185#define USB_HAS_INTERRUPT
1186#define USB_LEGACY_CONTROL_API
1185#elif defined(CPU_TCC780X) 1187#elif defined(CPU_TCC780X)
1186#define USB_HAS_BULK 1188#define USB_HAS_BULK
1189#define USB_LEGACY_CONTROL_API
1187#elif CONFIG_USBOTG == USBOTG_S3C6400X 1190#elif CONFIG_USBOTG == USBOTG_S3C6400X
1188#define USB_HAS_BULK 1191#define USB_HAS_BULK
1192#define USB_LEGACY_CONTROL_API
1189//#define USB_HAS_INTERRUPT -- seems to be broken 1193//#define USB_HAS_INTERRUPT -- seems to be broken
1190#endif /* CONFIG_USBOTG */ 1194#endif /* CONFIG_USBOTG */
1191 1195
diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c
index 9ece4fc796..9afaf5c336 100644
--- a/firmware/usbstack/usb_core.c
+++ b/firmware/usbstack/usb_core.c
@@ -22,6 +22,7 @@
22#include "thread.h" 22#include "thread.h"
23#include "kernel.h" 23#include "kernel.h"
24#include "string.h" 24#include "string.h"
25#include "panic.h"
25/*#define LOGF_ENABLE*/ 26/*#define LOGF_ENABLE*/
26#include "logf.h" 27#include "logf.h"
27 28
@@ -262,6 +263,13 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] =
262#endif 263#endif
263}; 264};
264 265
266#ifdef USB_LEGACY_CONTROL_API
267static struct usb_ctrlrequest active_request_buf;
268static struct usb_ctrlrequest* active_request = NULL;
269static void* control_write_data = NULL;
270static bool control_write_data_done = false;
271#endif
272
265static void usb_core_control_request_handler(struct usb_ctrlrequest* req, void* reqdata); 273static void usb_core_control_request_handler(struct usb_ctrlrequest* req, void* reqdata);
266 274
267static unsigned char response_data[256] USB_DEVBSS_ATTR; 275static unsigned char response_data[256] USB_DEVBSS_ATTR;
@@ -940,26 +948,29 @@ void usb_core_bus_reset(void)
940/* called by usb_drv_transfer_completed() */ 948/* called by usb_drv_transfer_completed() */
941void usb_core_transfer_complete(int endpoint, int dir, int status, int length) 949void usb_core_transfer_complete(int endpoint, int dir, int status, int length)
942{ 950{
943 struct usb_transfer_completion_event_data *completion_event; 951 struct usb_transfer_completion_event_data* completion_event =
944 952 &ep_data[endpoint].completion_event[EP_DIR(dir)];
945 switch (endpoint) {
946 case EP_CONTROL:
947 /* already handled */
948 break;
949 953
950 default: 954 completion_event->endpoint = endpoint;
951 completion_event = &ep_data[endpoint].completion_event[EP_DIR(dir)]; 955 completion_event->dir = dir;
952 956 completion_event->data[0] = NULL;
953 completion_event->endpoint = endpoint; 957 completion_event->data[1] = NULL;
954 completion_event->dir = dir; 958 completion_event->status = status;
955 completion_event->data[0] = NULL; 959 completion_event->length = length;
956 completion_event->data[1] = NULL; 960
957 completion_event->status = status; 961#ifdef USB_LEGACY_CONTROL_API
958 completion_event->length = length; 962 if(endpoint == EP_CONTROL) {
959 /* All other endpoints. Let the thread deal with it */ 963 if(dir == USB_DIR_OUT && active_request && control_write_data_done) {
960 usb_signal_transfer_completion(completion_event); 964 completion_event->data[0] = active_request;
961 break; 965 if(control_write_data_done && dir == USB_DIR_OUT)
966 completion_event->data[1] = control_write_data;
967 } else {
968 return;
969 }
962 } 970 }
971#endif
972
973 usb_signal_transfer_completion(completion_event);
963} 974}
964 975
965void usb_core_handle_notify(long id, intptr_t data) 976void usb_core_handle_notify(long id, intptr_t data)
@@ -977,8 +988,7 @@ void usb_core_handle_notify(long id, intptr_t data)
977 } 988 }
978} 989}
979 990
980/* called by usb_drv_int() */ 991void usb_core_control_request(struct usb_ctrlrequest* req, void* reqdata)
981void usb_core_legacy_control_request(struct usb_ctrlrequest* req)
982{ 992{
983 struct usb_transfer_completion_event_data* completion_event = 993 struct usb_transfer_completion_event_data* completion_event =
984 &ep_data[EP_CONTROL].completion_event[EP_DIR(USB_DIR_IN)]; 994 &ep_data[EP_CONTROL].completion_event[EP_DIR(USB_DIR_IN)];
@@ -986,13 +996,109 @@ void usb_core_legacy_control_request(struct usb_ctrlrequest* req)
986 completion_event->endpoint = EP_CONTROL; 996 completion_event->endpoint = EP_CONTROL;
987 completion_event->dir = 0; 997 completion_event->dir = 0;
988 completion_event->data[0] = (void*)req; 998 completion_event->data[0] = (void*)req;
989 completion_event->data[1] = NULL; 999 completion_event->data[1] = reqdata;
990 completion_event->status = 0; 1000 completion_event->status = 0;
991 completion_event->length = 0; 1001 completion_event->length = 0;
992 logf("ctrl received %ld, req=0x%x", current_tick, req->bRequest); 1002 logf("ctrl received %ld, req=0x%x", current_tick, req->bRequest);
993 usb_signal_transfer_completion(completion_event); 1003 usb_signal_transfer_completion(completion_event);
994} 1004}
995 1005
1006void usb_core_control_complete(int status)
1007{
1008 /* We currently don't use this, it's here to make the API look good ;)
1009 * It makes sense to #define it away on normal builds.
1010 */
1011 (void)status;
1012 logf("ctrl complete %ld, %d", current_tick, status);
1013}
1014
1015#ifdef USB_LEGACY_CONTROL_API
1016/* Only needed if the driver does not support the new API yet */
1017void usb_core_legacy_control_request(struct usb_ctrlrequest* req)
1018{
1019 memcpy(&active_request_buf, req, sizeof(*req));
1020 active_request = &active_request_buf;
1021 control_write_data = NULL;
1022 control_write_data_done = false;
1023
1024 usb_core_control_request(req, NULL);
1025}
1026
1027void usb_drv_control_response(enum usb_control_response resp,
1028 void* data, int length)
1029{
1030 if(!active_request)
1031 panicf("null ctrl req");
1032
1033 if(active_request->wLength == 0)
1034 {
1035 active_request = NULL;
1036
1037 /* No-data request */
1038 if(resp == USB_CONTROL_ACK)
1039 usb_drv_send(EP_CONTROL, data, length);
1040 else if(resp == USB_CONTROL_STALL)
1041 usb_drv_stall(EP_CONTROL, true, true);
1042 else
1043 panicf("RECEIVE on non-data req");
1044 }
1045 else if(active_request->bRequestType & USB_DIR_IN)
1046 {
1047 /* Control read request */
1048 if(resp == USB_CONTROL_ACK)
1049 {
1050 active_request = NULL;
1051 usb_drv_recv_nonblocking(EP_CONTROL, NULL, 0);
1052 usb_drv_send(EP_CONTROL, data, length);
1053 }
1054 else if(resp == USB_CONTROL_STALL)
1055 {
1056 active_request = NULL;
1057 usb_drv_stall(EP_CONTROL, true, true);
1058 }
1059 else
1060 {
1061 panicf("RECEIVE on ctrl read req");
1062 }
1063 }
1064 else if(!control_write_data_done)
1065 {
1066 /* Control write request, data phase */
1067 if(resp == USB_CONTROL_RECEIVE)
1068 {
1069 control_write_data = data;
1070 control_write_data_done = true;
1071 usb_drv_recv_nonblocking(EP_CONTROL, data, length);
1072 }
1073 else if(resp == USB_CONTROL_STALL)
1074 {
1075 /* We should stall the OUT endpoint here, but the old code did
1076 * not do so and some drivers may not handle it correctly. */
1077 active_request = NULL;
1078 usb_drv_stall(EP_CONTROL, true, true);
1079 }
1080 else
1081 {
1082 panicf("ACK on ctrl write data");
1083 }
1084 }
1085 else
1086 {
1087 active_request = NULL;
1088 control_write_data = NULL;
1089 control_write_data_done = false;
1090
1091 /* Control write request, status phase */
1092 if(resp == USB_CONTROL_ACK)
1093 usb_drv_send(EP_CONTROL, NULL, 0);
1094 else if(resp == USB_CONTROL_STALL)
1095 usb_drv_stall(EP_CONTROL, true, true);
1096 else
1097 panicf("RECEIVE on ctrl write status");
1098 }
1099}
1100#endif
1101
996void usb_core_notify_set_address(uint8_t addr) 1102void usb_core_notify_set_address(uint8_t addr)
997{ 1103{
998 logf("notify set addr received %ld", current_tick); 1104 logf("notify set addr received %ld", current_tick);