You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
CMSIS_DAP_FTDI/src/socket_ipc.c

217 lines
5.3 KiB

/*
* socket_ipc.c
*
* Created on: 03.11.2014
* Author: powertomato
*/
#include <stdio.h>
#include <fcntl.h>
#include "DAP_config.h"
#include "DAP.h"
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
static volatile uint8_t request_full; // Request Buffer Usage Flag
static volatile uint32_t request_head; // ReqBuff Buffer In Index
static volatile uint32_t request_tail; // ReqBuff Buffer Out Index
static volatile uint8_t response_full; // Response Buffer Usage Flag
static volatile uint32_t response_head; // Response Buffer In Index
static volatile uint32_t response_tail; // Response Buffer Out Index
static uint8_t request_buff[DAP_PACKET_COUNT][DAP_PACKET_SIZE]; // ReqBuff Buffer
static uint8_t response_buff[DAP_PACKET_COUNT][DAP_PACKET_SIZE]; // Response Buffer
#ifdef __CYGWIN__ /*include oddness...*/
typedef struct {
sa_family_t sin_family; /* Address family */
in_port_t sin_port; /* Port number */
struct in_addr sin_addr; /* Internet address */
/* Pad to size of `struct sockaddr'. */
unsigned char __pad[__SOCK_SIZE__ - sizeof(short int)
- sizeof(unsigned short int) - sizeof(struct in_addr)];
} sockaddr_in_t;
#else
typedef struct sockaddr_in sockaddr_in_t;
#endif
int sockfd, csockfd, portno, clilen;
sockaddr_in_t serv_addr;
sockaddr_in_t cli_addr;
void init_socket(void) {
request_full = 0;
request_head = 0;
request_tail = 0;
response_full = 0;
response_head = 0;
response_tail = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
DEBUG("ERROR opening socket: %s\n", strerror(errno));
exit(1);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 4777;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
int yes = 1;
if ( setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0){
DEBUG("ERROR on setting socket option: %s\n", strerror(errno));
exit(1);
}
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
DEBUG("ERROR on binding: %s\n", strerror(errno));
exit(1);
}
listen(sockfd,5);
csockfd = -1;
}
void close_socket() {
if( csockfd == -1){
return;
}
printf("Closed session!\n");
close(csockfd);
csockfd = -1;
}
static int should_close=0;
void late_close_socket() {
should_close = 1;
}
// USB HID Callback: when system initializes
void wait_for_client(void) {
printf("Wait client... ");
clilen = sizeof(cli_addr);
csockfd = accept(sockfd, (struct sockaddr*)&cli_addr, (socklen_t*)&clilen);
if (csockfd < 0){
DEBUG("ERROR on accept: %s\n", strerror(errno));
exit(1);
}
int flags;
flags = fcntl(csockfd, F_GETFL, 0);
if(flags < 0 ){
flags = 0;
}
if( fcntl(csockfd, F_SETFL, flags | O_NONBLOCK) < 0 ){
DEBUG("ERROR seting non-blocking: %s\n", strerror(errno));
}
printf("connected\n");
}
// USB HID Callback: when data needs to be prepared for the host
int write_response() {
if ((response_tail != response_head) || response_full) {
int n = write(csockfd,response_buff[response_tail],DAP_PACKET_SIZE);
if (n != DAP_PACKET_SIZE){
DEBUG("ERROR writing to socket: %s\n", strerror(errno));
close_socket();
}
// remove a response
response_tail = (response_tail+1) % DAP_PACKET_COUNT;
response_full = 0;
return (DAP_PACKET_SIZE);
}
return (0);
}
// USB HID Callback: when data is received from the host
void buffer_request(uint8_t *buff, int len) {
if (len == 0){
return;
}
if (buff[0] == ID_DAP_TransferAbort) {
DAP_TransferAbort = 1;
return;
}
if (request_full) {
return; // Discard packet when buffer is full
}
// add a request
memcpy(request_buff[request_head], buff, len);
request_head++;
if (request_head == DAP_PACKET_COUNT) {
request_head = 0;
}
if (request_head == request_tail) {
request_full = 1;
}
}
// Process USB HID Data
void process_data(void) {
static uint8_t buff[DAP_PACKET_SIZE];
static int buff_pos = 0;
int n;
if( csockfd == -1 ){
wait_for_client();
}
n = read(csockfd,buff+buff_pos,DAP_PACKET_SIZE);
if ( n==0 ) {
}else if( n>0 ) {
buff_pos += n;
if( buff_pos==DAP_PACKET_SIZE ) {
buffer_request(buff,DAP_PACKET_SIZE);
buff_pos=0;
}
}else if( n<0 ){
switch( errno ) {
case EAGAIN: break;
default:
DEBUG("A problem occured: %d %d %s\n", n, errno,strerror(errno) );
DEBUG("Closing connection!\n");
close_socket(csockfd);
break;
}
}
// Process pending requests
if ((request_tail != request_head) || request_full) {
// Process DAP Command and prepare response
DAP_ProcessCommand(request_buff[request_tail], response_buff[response_head]);
if( out_state_buff_pos != 0 ){
FTDI_WRITE_OUT();
}
// remove a request
request_tail = (request_tail + 1) % DAP_PACKET_COUNT;
request_full = 0;
if( csockfd != -1 ) {
// add a response
response_head = (response_head + 1) % DAP_PACKET_COUNT;
if (response_head == response_tail) {
response_full = 1;
}
write_response();
}
}
if(should_close) {
close_socket();
}
should_close = 0;
}