188 lines
5.3 KiB
C
188 lines
5.3 KiB
C
|
/****************************************************************************
|
||
|
* 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. *
|
||
|
****************************************************************************/
|
||
|
|
||
|
#include <generated/csr.h>
|
||
|
#include <grainuum.h>
|
||
|
|
||
|
__attribute__((weak))
|
||
|
void grainuumConnectPre(struct GrainuumUSB *usb)
|
||
|
{
|
||
|
(void)usb;
|
||
|
}
|
||
|
__attribute__((weak))
|
||
|
void grainuumConnectPost(struct GrainuumUSB *usb)
|
||
|
{
|
||
|
(void)usb;
|
||
|
}
|
||
|
|
||
|
__attribute__((weak))
|
||
|
void grainuumDisconnectPre(struct GrainuumUSB *usb)
|
||
|
{
|
||
|
(void)usb;
|
||
|
}
|
||
|
__attribute__((weak))
|
||
|
void grainuumDisconnectPost(struct GrainuumUSB *usb)
|
||
|
{
|
||
|
(void)usb;
|
||
|
}
|
||
|
|
||
|
__attribute__((weak))
|
||
|
void grainuumReceivePacket(struct GrainuumUSB *usb)
|
||
|
{
|
||
|
(void)usb;
|
||
|
}
|
||
|
|
||
|
__attribute__((weak))
|
||
|
void grainuumInitPre(struct GrainuumUSB *usb)
|
||
|
{
|
||
|
(void)usb;
|
||
|
}
|
||
|
|
||
|
__attribute__((weak))
|
||
|
void grainuumInitPost(struct GrainuumUSB *usb)
|
||
|
{
|
||
|
(void)usb;
|
||
|
}
|
||
|
|
||
|
/* --- */
|
||
|
|
||
|
void grainuum_receive_packet(struct GrainuumUSB *usb) {
|
||
|
grainuumReceivePacket(usb);
|
||
|
}
|
||
|
|
||
|
int grainuumCaptureI(struct GrainuumUSB *usb, uint8_t samples[67])
|
||
|
{
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
int grainuumInitialized(struct GrainuumUSB *usb)
|
||
|
{
|
||
|
if (!usb)
|
||
|
return 0;
|
||
|
|
||
|
return usb->initialized;
|
||
|
}
|
||
|
|
||
|
void grainuumWriteQueue(struct GrainuumUSB *usb, int epnum,
|
||
|
const void *buffer, int size)
|
||
|
{
|
||
|
usb->queued_data = buffer;
|
||
|
usb->queued_epnum = epnum;
|
||
|
usb->queued_size = size;
|
||
|
}
|
||
|
|
||
|
void grainuumInit(struct GrainuumUSB *usb,
|
||
|
struct GrainuumConfig *cfg) {
|
||
|
|
||
|
if (usb->initialized)
|
||
|
return;
|
||
|
|
||
|
grainuumInitPre(usb);
|
||
|
|
||
|
usb->cfg = cfg;
|
||
|
usb->state.usb = usb;
|
||
|
cfg->usb = usb;
|
||
|
|
||
|
usb->initialized = 1;
|
||
|
|
||
|
grainuumInitPost(usb);
|
||
|
}
|
||
|
|
||
|
void grainuumDisconnect(struct GrainuumUSB *usb) {
|
||
|
|
||
|
grainuumDisconnectPre(usb);
|
||
|
|
||
|
usb_pullup_out_write(0);
|
||
|
|
||
|
grainuumDisconnectPost(usb);
|
||
|
}
|
||
|
|
||
|
void grainuumConnect(struct GrainuumUSB *usb) {
|
||
|
|
||
|
grainuumConnectPre(usb);
|
||
|
|
||
|
usb_pullup_out_write(1);
|
||
|
|
||
|
grainuumConnectPost(usb);
|
||
|
}
|