foboot/src/grainuum-phy.c

188 lines
5.3 KiB
C
Raw Normal View History

/****************************************************************************
* 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);
}