1 /*
2  * Copyright (c) 2024, sakumisu
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include "usbd_core.h"
7 #include "usbd_adb.h"
8 
9 #define ADB_OUT_EP_IDX        0
10 #define ADB_IN_EP_IDX         1
11 
12 #define ADB_STATE_READ_MSG    0
13 #define ADB_STATE_READ_DATA   1
14 #define ADB_STATE_WRITE_MSG   2
15 #define ADB_STATE_WRITE_DATA  3
16 #define ADB_STATE_AWRITE_MSG  4
17 #define ADB_STATE_AWRITE_DATA 5
18 
19 #define MAX_PAYLOAD_V1        (4 * 1024)
20 #define MAX_PAYLOAD_V2        (256 * 1024)
21 #define MAX_PAYLOAD           MAX_PAYLOAD_V1
22 #define A_VERSION             0x01000000
23 
24 #define A_SYNC                0x434e5953
25 #define A_CNXN                0x4e584e43
26 #define A_OPEN                0x4e45504f
27 #define A_OKAY                0x59414b4f
28 #define A_CLSE                0x45534c43
29 #define A_WRTE                0x45545257
30 #define A_AUTH                0x48545541
31 
32 struct adb_msg {
33     uint32_t command;     /* command identifier constant (A_CNXN, ...) */
34     uint32_t arg0;        /* first argument                            */
35     uint32_t arg1;        /* second argument                           */
36     uint32_t data_length; /* length of payload (0 is allowed)          */
37     uint32_t data_crc32;  /* crc32 of data payload                     */
38     uint32_t magic;       /* command ^ 0xffffffff */
39 };
40 
41 struct adb_packet {
42     USB_MEM_ALIGNX struct adb_msg msg;
43     USB_MEM_ALIGNX uint8_t payload[USB_ALIGN_UP(MAX_PAYLOAD, CONFIG_USB_ALIGN_SIZE)];
44 };
45 
46 struct usbd_adb {
47     uint8_t state;
48     uint8_t common_state;
49     uint8_t write_state;
50     bool writable;
51     uint32_t localid;
52     uint32_t shell_remoteid;
53     uint32_t file_remoteid;
54 } adb_client;
55 
56 static struct usbd_endpoint adb_ep_data[2];
57 
58 USB_NOCACHE_RAM_SECTION struct adb_packet tx_packet;
59 USB_NOCACHE_RAM_SECTION struct adb_packet rx_packet;
60 
adb_packet_checksum(struct adb_packet * packet)61 static inline uint32_t adb_packet_checksum(struct adb_packet *packet)
62 {
63     uint32_t sum = 0;
64     uint32_t i;
65 
66     for (i = 0; i < packet->msg.data_length; ++i) {
67         sum += (uint32_t)(packet->payload[i]);
68     }
69 
70     return sum;
71 }
72 
usbd_adb_get_remoteid(uint32_t localid)73 static uint32_t usbd_adb_get_remoteid(uint32_t localid)
74 {
75     if (localid == ADB_SHELL_LOALID) {
76         return adb_client.shell_remoteid;
77     } else {
78         return adb_client.file_remoteid;
79     }
80 }
81 
adb_send_msg(struct adb_packet * packet)82 static void adb_send_msg(struct adb_packet *packet)
83 {
84     adb_client.common_state = ADB_STATE_WRITE_MSG;
85 
86     packet->msg.data_crc32 = adb_packet_checksum(packet);
87     packet->msg.magic = packet->msg.command ^ 0xffffffff;
88 
89     usbd_ep_start_write(0, adb_ep_data[ADB_IN_EP_IDX].ep_addr, (uint8_t *)&packet->msg, sizeof(struct adb_msg));
90 }
91 
adb_send_okay(struct adb_packet * packet,uint32_t localid)92 static void adb_send_okay(struct adb_packet *packet, uint32_t localid)
93 {
94     packet->msg.command = A_OKAY;
95     packet->msg.arg0 = localid;
96     packet->msg.arg1 = usbd_adb_get_remoteid(localid);
97     packet->msg.data_length = 0;
98 
99     adb_send_msg(&tx_packet);
100 }
101 
adb_send_close(struct adb_packet * packet,uint32_t localid,uint32_t remoteid)102 static void adb_send_close(struct adb_packet *packet, uint32_t localid, uint32_t remoteid)
103 {
104     packet->msg.command = A_CLSE;
105     packet->msg.arg0 = localid;
106     packet->msg.arg1 = remoteid;
107     packet->msg.data_length = 0;
108 
109     adb_send_msg(&tx_packet);
110 }
111 
usbd_adb_bulk_out(uint8_t busid,uint8_t ep,uint32_t nbytes)112 void usbd_adb_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
113 {
114     (void)ep;
115 
116     if (adb_client.common_state == ADB_STATE_READ_MSG) {
117         if (nbytes != sizeof(struct adb_msg)) {
118             USB_LOG_ERR("invalid adb msg size:%d\r\n", (unsigned int)nbytes);
119             return;
120         }
121 
122         USB_LOG_DBG("command:%x arg0:%x arg1:%x len:%d\r\n",
123                      rx_packet.msg.command,
124                      rx_packet.msg.arg0,
125                      rx_packet.msg.arg1,
126                      rx_packet.msg.data_length);
127 
128         if (rx_packet.msg.data_length) {
129             /* setup next out ep read transfer */
130             adb_client.common_state = ADB_STATE_READ_DATA;
131             usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, rx_packet.payload, rx_packet.msg.data_length);
132         } else {
133             if (rx_packet.msg.command == A_CLSE) {
134                 adb_client.writable = false;
135                 usbd_adb_notify_write_done();
136                 USB_LOG_INFO("Close remoteid:%x\r\n", rx_packet.msg.arg0);
137             }
138             adb_client.common_state = ADB_STATE_READ_MSG;
139             /* setup first out ep read transfer */
140             usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
141         }
142     } else if (adb_client.common_state == ADB_STATE_READ_DATA) {
143         switch (rx_packet.msg.command) {
144             case A_SYNC:
145 
146                 break;
147             case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
148                 char *support_feature = "device::"
149                                         "ro.product.name=cherryadb;"
150                                         "ro.product.model=cherrysh;"
151                                         "ro.product.device=cherryadb;"
152                                         "features=cmd,shell_v1";
153 
154                 tx_packet.msg.command = A_CNXN;
155                 tx_packet.msg.arg0 = A_VERSION;
156                 tx_packet.msg.arg1 = MAX_PAYLOAD;
157                 tx_packet.msg.data_length = strlen(support_feature);
158                 memcpy(tx_packet.payload, support_feature, strlen(support_feature));
159 
160                 adb_send_msg(&tx_packet);
161 
162                 adb_client.writable = false;
163                 break;
164             case A_OPEN: /* OPEN(local-id, 0, "destination") */
165                 rx_packet.payload[rx_packet.msg.data_length] = '\0';
166 
167                 if (strncmp((const char *)rx_packet.payload, "shell:", 6) == 0) {
168                     adb_client.localid = ADB_SHELL_LOALID;
169                     adb_client.shell_remoteid = rx_packet.msg.arg0;
170                     adb_send_okay(&tx_packet, ADB_SHELL_LOALID);
171 
172                     USB_LOG_INFO("Open shell service, remoteid:%x\r\n", rx_packet.msg.arg0);
173                 } else if (strncmp((const char *)rx_packet.payload, "sync:", 5) == 0) {
174                     adb_client.localid = ADB_FILE_LOALID;
175                     adb_client.file_remoteid = rx_packet.msg.arg0;
176                     adb_send_okay(&tx_packet, ADB_FILE_LOALID);
177                     USB_LOG_INFO("Open file service, remoteid:%x\r\n", rx_packet.msg.arg0);
178                 }
179                 break;
180             case A_OKAY:
181 
182                 break;
183             case A_CLSE:
184 
185                 break;
186             case A_WRTE: /* WRITE(local-id, remote-id, "data") */
187                 if ((rx_packet.msg.arg0 == adb_client.shell_remoteid) && (rx_packet.msg.arg1 == ADB_SHELL_LOALID)) {
188                     adb_send_okay(&tx_packet, rx_packet.msg.arg1);
189                 } else if ((rx_packet.msg.arg0 == adb_client.file_remoteid) && (rx_packet.msg.arg1 == ADB_FILE_LOALID)) {
190                     adb_send_okay(&tx_packet, rx_packet.msg.arg1);
191                 } else {
192                     adb_send_close(&tx_packet, 0, rx_packet.msg.arg0);
193                 }
194                 break;
195             case A_AUTH:
196 
197                 break;
198 
199             default:
200                 break;
201         }
202     }
203 }
204 
usbd_adb_bulk_in(uint8_t busid,uint8_t ep,uint32_t nbytes)205 void usbd_adb_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
206 {
207     (void)ep;
208     (void)nbytes;
209 
210     if (adb_client.common_state == ADB_STATE_WRITE_MSG) {
211         if (tx_packet.msg.data_length) {
212             adb_client.common_state = ADB_STATE_WRITE_DATA;
213             usbd_ep_start_write(busid, adb_ep_data[ADB_IN_EP_IDX].ep_addr, tx_packet.payload, tx_packet.msg.data_length);
214         } else {
215             if (rx_packet.msg.command == A_WRTE) {
216                 adb_client.writable = true;
217                 if (adb_client.localid == ADB_SHELL_LOALID) {
218                     usbd_adb_notify_shell_read(rx_packet.payload, rx_packet.msg.data_length);
219                 } else {
220                 }
221             }
222             adb_client.common_state = ADB_STATE_READ_MSG;
223             /* setup first out ep read transfer */
224             usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
225         }
226     } else if (adb_client.common_state == ADB_STATE_WRITE_DATA) {
227         adb_client.common_state = ADB_STATE_READ_MSG;
228         /* setup first out ep read transfer */
229         usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
230     } else if (adb_client.write_state == ADB_STATE_AWRITE_MSG) {
231         if (tx_packet.msg.data_length) {
232             adb_client.write_state = ADB_STATE_AWRITE_DATA;
233             usbd_ep_start_write(busid, adb_ep_data[ADB_IN_EP_IDX].ep_addr, tx_packet.payload, tx_packet.msg.data_length);
234         } else {
235         }
236     } else if (adb_client.write_state == ADB_STATE_AWRITE_DATA) {
237         usbd_adb_notify_write_done();
238     }
239 }
240 
adb_notify_handler(uint8_t busid,uint8_t event,void * arg)241 void adb_notify_handler(uint8_t busid, uint8_t event, void *arg)
242 {
243     (void)arg;
244 
245     switch (event) {
246         case USBD_EVENT_INIT:
247             break;
248         case USBD_EVENT_DEINIT:
249             break;
250         case USBD_EVENT_RESET:
251             break;
252         case USBD_EVENT_CONFIGURED:
253             adb_client.common_state = ADB_STATE_READ_MSG;
254             /* setup first out ep read transfer */
255             usbd_ep_start_read(busid, adb_ep_data[ADB_OUT_EP_IDX].ep_addr, (uint8_t *)&rx_packet.msg, sizeof(struct adb_msg));
256             break;
257 
258         default:
259             break;
260     }
261 }
262 
usbd_adb_init_intf(uint8_t busid,struct usbd_interface * intf,uint8_t in_ep,uint8_t out_ep)263 struct usbd_interface *usbd_adb_init_intf(uint8_t busid, struct usbd_interface *intf, uint8_t in_ep, uint8_t out_ep)
264 {
265     (void)busid;
266 
267     intf->class_interface_handler = NULL;
268     intf->class_endpoint_handler = NULL;
269     intf->vendor_handler = NULL;
270     intf->notify_handler = adb_notify_handler;
271 
272     adb_ep_data[ADB_OUT_EP_IDX].ep_addr = out_ep;
273     adb_ep_data[ADB_OUT_EP_IDX].ep_cb = usbd_adb_bulk_out;
274     adb_ep_data[ADB_IN_EP_IDX].ep_addr = in_ep;
275     adb_ep_data[ADB_IN_EP_IDX].ep_cb = usbd_adb_bulk_in;
276 
277     usbd_add_endpoint(busid, &adb_ep_data[ADB_OUT_EP_IDX]);
278     usbd_add_endpoint(busid, &adb_ep_data[ADB_IN_EP_IDX]);
279 
280     return intf;
281 }
282 
usbd_adb_can_write(void)283 bool usbd_adb_can_write(void)
284 {
285     return adb_client.writable;
286 }
287 
usbd_abd_write(uint32_t localid,const uint8_t * data,uint32_t len)288 int usbd_abd_write(uint32_t localid, const uint8_t *data, uint32_t len)
289 {
290     struct adb_packet *packet;
291 
292     packet = &tx_packet;
293     packet->msg.command = A_WRTE;
294     packet->msg.arg0 = localid;
295     packet->msg.arg1 = usbd_adb_get_remoteid(localid);
296     packet->msg.data_length = len;
297     memcpy(packet->payload, data, len);
298 
299     packet->msg.data_crc32 = adb_packet_checksum(packet);
300     packet->msg.magic = packet->msg.command ^ 0xffffffff;
301 
302     adb_client.write_state = ADB_STATE_AWRITE_MSG;
303     usbd_ep_start_write(0, adb_ep_data[ADB_IN_EP_IDX].ep_addr, (uint8_t *)&packet->msg, sizeof(struct adb_msg));
304     return 0;
305 }
306 
usbd_adb_close(uint32_t localid)307 void usbd_adb_close(uint32_t localid)
308 {
309     adb_send_close(&tx_packet, 0, usbd_adb_get_remoteid(localid));
310 }