2019-01-01 15:03:45 +00:00
|
|
|
/****************************************************************************
|
|
|
|
* Grainuum Software USB Stack *
|
|
|
|
* *
|
|
|
|
* MIT License: *
|
|
|
|
* Copyright (c) 2016 Sean Cross *
|
|
|
|
* *
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a *
|
|
|
|
* copy of this software and associated documentation files (the *
|
|
|
|
* "Software"), to deal in the Software without restriction, including *
|
|
|
|
* without limitation the rights to use, copy, modify, merge, publish, *
|
|
|
|
* distribute, distribute with modifications, sublicense, and/or sell *
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is *
|
|
|
|
* furnished to do so, subject to the following conditions: *
|
|
|
|
* *
|
|
|
|
* The above copyright notice and this permission notice shall be included *
|
|
|
|
* in all copies or substantial portions of the Software. *
|
|
|
|
* *
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
|
|
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
|
|
|
|
* IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
|
|
|
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
|
|
|
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
|
|
|
|
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
|
|
|
* *
|
|
|
|
* Except as contained in this notice, the name(s) of the above copyright *
|
|
|
|
* holders shall not be used in advertising or otherwise to promote the *
|
|
|
|
* sale, use or other dealings in this Software without prior written *
|
|
|
|
* authorization. *
|
|
|
|
****************************************************************************/
|
|
|
|
|
2019-01-23 03:52:47 +00:00
|
|
|
#include <generated/csr.h>
|
2019-01-01 15:03:45 +00:00
|
|
|
#include <grainuum.h>
|
2019-01-23 03:52:47 +00:00
|
|
|
#include <printf.h>
|
2019-01-01 15:03:45 +00:00
|
|
|
|
2019-01-23 03:52:47 +00:00
|
|
|
__attribute__((weak)) void grainuumConnectPre(struct GrainuumUSB *usb)
|
2019-01-01 15:03:45 +00:00
|
|
|
{
|
|
|
|
(void)usb;
|
|
|
|
}
|
2019-01-23 03:52:47 +00:00
|
|
|
__attribute__((weak)) void grainuumConnectPost(struct GrainuumUSB *usb)
|
2019-01-01 15:03:45 +00:00
|
|
|
{
|
|
|
|
(void)usb;
|
|
|
|
}
|
|
|
|
|
2019-01-23 03:52:47 +00:00
|
|
|
__attribute__((weak)) void grainuumDisconnectPre(struct GrainuumUSB *usb)
|
2019-01-01 15:03:45 +00:00
|
|
|
{
|
|
|
|
(void)usb;
|
|
|
|
}
|
2019-01-23 03:52:47 +00:00
|
|
|
__attribute__((weak)) void grainuumDisconnectPost(struct GrainuumUSB *usb)
|
2019-01-01 15:03:45 +00:00
|
|
|
{
|
|
|
|
(void)usb;
|
|
|
|
}
|
|
|
|
|
2019-01-23 03:52:47 +00:00
|
|
|
__attribute__((weak)) void grainuumReceivePacket(struct GrainuumUSB *usb)
|
2019-01-01 15:03:45 +00:00
|
|
|
{
|
|
|
|
(void)usb;
|
|
|
|
}
|
|
|
|
|
2019-01-23 03:52:47 +00:00
|
|
|
__attribute__((weak)) void grainuumInitPre(struct GrainuumUSB *usb)
|
2019-01-01 15:03:45 +00:00
|
|
|
{
|
|
|
|
(void)usb;
|
|
|
|
}
|
|
|
|
|
2019-01-23 03:52:47 +00:00
|
|
|
__attribute__((weak)) void grainuumInitPost(struct GrainuumUSB *usb)
|
2019-01-01 15:03:45 +00:00
|
|
|
{
|
|
|
|
(void)usb;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --- */
|
|
|
|
|
2019-01-23 03:52:47 +00:00
|
|
|
void grainuum_receive_packet(struct GrainuumUSB *usb)
|
|
|
|
{
|
2019-01-01 15:03:45 +00:00
|
|
|
grainuumReceivePacket(usb);
|
|
|
|
}
|
|
|
|
|
|
|
|
int grainuumCaptureI(struct GrainuumUSB *usb, uint8_t samples[67])
|
|
|
|
{
|
2019-01-23 03:52:47 +00:00
|
|
|
#if 0
|
2019-01-01 15:03:45 +00:00
|
|
|
int ret;
|
|
|
|
const uint8_t nak_pkt[] = {USB_PID_NAK};
|
|
|
|
const uint8_t ack_pkt[] = {USB_PID_ACK};
|
|
|
|
|
|
|
|
ret = usbPhyReadI(usb, samples);
|
|
|
|
if (ret <= 0) {
|
|
|
|
if (ret != -1)
|
|
|
|
usbPhyWriteI(usb, nak_pkt, sizeof(nak_pkt));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Save the byte counter for later inspection */
|
|
|
|
samples[11] = ret;
|
|
|
|
|
|
|
|
switch (samples[0]) {
|
|
|
|
case USB_PID_IN:
|
|
|
|
/* Make sure we have queued data, and that it's for this particular EP */
|
|
|
|
if ((!usb->queued_size)
|
|
|
|
|| (((((const uint16_t *)(samples+1))[0] >> 7) & 0xf) != usb->queued_epnum))
|
|
|
|
{
|
|
|
|
usbPhyWriteI(usb, nak_pkt, sizeof(nak_pkt));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
usbPhyWriteI(usb, usb->queued_data, usb->queued_size);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case USB_PID_SETUP:
|
|
|
|
grainuum_receive_packet(usb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case USB_PID_OUT:
|
|
|
|
grainuum_receive_packet(usb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case USB_PID_ACK:
|
|
|
|
/* Allow the next byte to be sent */
|
|
|
|
usb->queued_size = 0;
|
|
|
|
grainuum_receive_packet(usb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case USB_PID_DATA0:
|
|
|
|
case USB_PID_DATA1:
|
|
|
|
usbPhyWriteI(usb, ack_pkt, sizeof(ack_pkt));
|
|
|
|
grainuum_receive_packet(usb);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
usbPhyWriteI(usb, nak_pkt, sizeof(nak_pkt));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2019-01-23 03:52:47 +00:00
|
|
|
#endif
|
|
|
|
uint8_t obufbuf[128];
|
|
|
|
uint32_t obufbuf_cnt = 0;
|
|
|
|
while (!usb_ep_0_out_obuf_empty_read())
|
|
|
|
{
|
|
|
|
uint32_t obh = usb_ep_0_out_obuf_head_read();
|
|
|
|
obufbuf[obufbuf_cnt++] = obh;
|
|
|
|
usb_ep_0_out_obuf_head_write(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int i;
|
|
|
|
static int loops;
|
|
|
|
uint8_t last_tok = usb_ep_0_out_last_tok_read();
|
|
|
|
printf("i: %d b: %d olt: %02x --", loops, obufbuf_cnt, last_tok); //obe: %d obh: %02x\n", i, obe, obh);
|
|
|
|
for (i = 0; i < obufbuf_cnt; i++)
|
|
|
|
{
|
|
|
|
printf(" %02x", obufbuf[i]);
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
usb_ep_0_out_ev_pending_write((1 << 1));
|
|
|
|
|
|
|
|
// Response
|
|
|
|
if (!usb_ep_0_in_ibuf_empty_read())
|
|
|
|
{
|
|
|
|
printf("USB ibuf still has data\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t usb_in_pending = usb_ep_0_out_ev_pending_read();
|
|
|
|
if (usb_in_pending)
|
|
|
|
{
|
|
|
|
printf("USB EP0 in pending is: %02x\n", usb_in_pending);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
grainuumProcess(usb, obufbuf, obufbuf_cnt);
|
|
|
|
|
|
|
|
return 0;
|
2019-01-01 15:03:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int grainuumInitialized(struct GrainuumUSB *usb)
|
|
|
|
{
|
|
|
|
if (!usb)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return usb->initialized;
|
|
|
|
}
|
|
|
|
|
2019-01-23 03:52:47 +00:00
|
|
|
enum usb_responses {
|
|
|
|
USB_STALL = 0b11,
|
|
|
|
USB_ACK = 0b00,
|
|
|
|
USB_NAK = 0b01,
|
|
|
|
USB_NONE = 0b10,
|
|
|
|
};
|
|
|
|
|
2019-01-01 15:03:45 +00:00
|
|
|
void grainuumWriteQueue(struct GrainuumUSB *usb, int epnum,
|
|
|
|
const void *buffer, int size)
|
|
|
|
{
|
|
|
|
usb->queued_data = buffer;
|
|
|
|
usb->queued_epnum = epnum;
|
|
|
|
usb->queued_size = size;
|
2019-01-23 03:52:47 +00:00
|
|
|
|
|
|
|
int i;
|
|
|
|
const uint8_t *buffer_u8 = buffer;
|
|
|
|
for (i = 0; i < size; i++)
|
|
|
|
{
|
|
|
|
usb_ep_0_in_ibuf_head_write(buffer_u8[i]);
|
|
|
|
}
|
|
|
|
// Indicate that we respond with an ACK
|
|
|
|
usb_ep_0_in_respond_write(USB_ACK);
|
|
|
|
usb_ep_0_in_ev_pending_write(0xff);
|
2019-01-01 15:03:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void grainuumInit(struct GrainuumUSB *usb,
|
2019-01-23 03:52:47 +00:00
|
|
|
struct GrainuumConfig *cfg)
|
|
|
|
{
|
2019-01-01 15:03:45 +00:00
|
|
|
|
|
|
|
if (usb->initialized)
|
|
|
|
return;
|
|
|
|
|
|
|
|
grainuumInitPre(usb);
|
|
|
|
|
|
|
|
usb->cfg = cfg;
|
|
|
|
usb->state.usb = usb;
|
|
|
|
cfg->usb = usb;
|
|
|
|
|
|
|
|
usb->initialized = 1;
|
|
|
|
|
|
|
|
grainuumInitPost(usb);
|
|
|
|
}
|
|
|
|
|
2019-01-23 03:52:47 +00:00
|
|
|
void grainuumDisconnect(struct GrainuumUSB *usb)
|
|
|
|
{
|
2019-01-01 15:03:45 +00:00
|
|
|
|
|
|
|
grainuumDisconnectPre(usb);
|
|
|
|
|
|
|
|
usb_pullup_out_write(0);
|
|
|
|
|
|
|
|
grainuumDisconnectPost(usb);
|
|
|
|
}
|
|
|
|
|
2019-01-23 03:52:47 +00:00
|
|
|
void grainuumConnect(struct GrainuumUSB *usb)
|
|
|
|
{
|
2019-01-01 15:03:45 +00:00
|
|
|
|
|
|
|
grainuumConnectPre(usb);
|
|
|
|
|
|
|
|
usb_pullup_out_write(1);
|
|
|
|
|
|
|
|
grainuumConnectPost(usb);
|
|
|
|
}
|