kopia lustrzana https://github.com/solokeys/solo1
allocate cids better and do proper timeouts in hid
rodzic
87429fb8a6
commit
9c42823cd2
6
ctap.c
6
ctap.c
|
@ -1260,11 +1260,17 @@ void ctap_reset_pin_attempts()
|
|||
_flash_tries = 8;
|
||||
}
|
||||
|
||||
void ctap_reset_state()
|
||||
{
|
||||
memset(&getAssertionState, 0, sizeof(getAssertionState));
|
||||
}
|
||||
|
||||
void ctap_reset()
|
||||
{
|
||||
_flash_tries = 8;
|
||||
PIN_CODE_SET = 0;
|
||||
DEVICE_LOCKOUT = 0;
|
||||
ctap_reset_state();
|
||||
memset(PIN_CODE,0,sizeof(PIN_CODE));
|
||||
memset(PIN_CODE_HASH,0,sizeof(PIN_CODE_HASH));
|
||||
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
|
||||
|
|
3
ctap.h
3
ctap.h
|
@ -244,6 +244,9 @@ int ctap_encode_der_sig(uint8_t * sigbuf, uint8_t * sigder);
|
|||
// Run ctap related power-up procedures (init pinToken, generate shared secret)
|
||||
void ctap_init();
|
||||
|
||||
// Resets state between different accesses of different applications
|
||||
void ctap_reset_state();
|
||||
|
||||
void ctap_update_pin(uint8_t * pin, int len);
|
||||
uint8_t ctap_decrement_pin_attempts();
|
||||
int8_t ctap_leftover_pin_attempts();
|
||||
|
|
103
ctap_test.py
103
ctap_test.py
|
@ -12,7 +12,7 @@ from fido2.utils import Timeout
|
|||
import sys,os
|
||||
from random import randint
|
||||
from binascii import hexlify
|
||||
import array,struct
|
||||
import array,struct,socket
|
||||
|
||||
# Set up a FIDO 2 client using the origin https://example.com
|
||||
|
||||
|
@ -24,6 +24,19 @@ def ForceU2F(client,device):
|
|||
client._do_get_assertion = client._ctap1_get_assertion
|
||||
|
||||
|
||||
class Packet(object):
|
||||
def __init__(self,data):
|
||||
self.data = data
|
||||
|
||||
def ToWireFormat(self,):
|
||||
return self.data
|
||||
|
||||
@staticmethod
|
||||
def FromWireFormat(pkt_size,data):
|
||||
return Packet(data)
|
||||
|
||||
|
||||
|
||||
class Tester():
|
||||
def __init__(self,):
|
||||
self.origin = 'https://examplo.org'
|
||||
|
@ -35,15 +48,49 @@ class Tester():
|
|||
self.dev = dev
|
||||
self.ctap = CTAP2(dev)
|
||||
|
||||
# consume timeout error
|
||||
cmd,resp = self.recv_raw()
|
||||
|
||||
def send_data(self, cmd, data):
|
||||
#print('<<', hexlify(data))
|
||||
if type(data) != type(b''):
|
||||
data = data.encode()
|
||||
data = struct.pack('%dB' % len(data), *[ord(x) for x in data])
|
||||
with Timeout(1.0) as event:
|
||||
return self.dev.call(cmd, data,event)
|
||||
|
||||
def send_raw(self, data, cid = None):
|
||||
if cid is None:
|
||||
cid = self.dev._dev.cid
|
||||
if type(data) != type(b''):
|
||||
data = struct.pack('%dB' % len(data), *[ord(x) for x in data])
|
||||
self.dev._dev.InternalSendPacket(Packet(cid + data))
|
||||
|
||||
def cid(self,):
|
||||
return self.dev._dev.cid
|
||||
|
||||
def recv_raw(self,):
|
||||
cmd,payload = self.dev._dev.InternalRecv()
|
||||
return cmd, payload
|
||||
|
||||
def check_error(self,data,err=None):
|
||||
assert(len(data) == 1)
|
||||
if err is None:
|
||||
if data[0] != 0:
|
||||
raise CtapError(data[0])
|
||||
elif data[0] != err:
|
||||
raise ValueError('Unexpected error: %02x' % data[0])
|
||||
|
||||
|
||||
def test_hid(self,):
|
||||
print('Test idle')
|
||||
try:
|
||||
cmd,resp = self.recv_raw()
|
||||
except socket.timeout:
|
||||
print('Pass: Idle')
|
||||
|
||||
print('Test init')
|
||||
r = self.send_data(CTAPHID.INIT, '\x11\x11\x11\x11\x11\x11\x11\x11')
|
||||
|
||||
pingdata = os.urandom(100)
|
||||
try:
|
||||
r = self.send_data(CTAPHID.PING, pingdata)
|
||||
|
@ -62,6 +109,8 @@ class Tester():
|
|||
print('7609 byte Ping failed:', e)
|
||||
print('PASS: 7609 byte ping')
|
||||
|
||||
print('Test non-active cid')
|
||||
|
||||
try:
|
||||
r = self.send_data(CTAPHID.WINK, '')
|
||||
except CtapError as e:
|
||||
|
@ -90,15 +139,59 @@ class Tester():
|
|||
print('PASS: no data msg')
|
||||
|
||||
try:
|
||||
r = self.send_data(CTAPHID.INIT, '')
|
||||
r = self.send_data(CTAPHID.INIT, '\x11\x22\x33\x44\x55\x66\x77\x88')
|
||||
except CtapError as e:
|
||||
print('resync fail: ', e)
|
||||
return
|
||||
raise RuntimeError('resync fail: ', e)
|
||||
print('PASS: resync')
|
||||
|
||||
try:
|
||||
r = self.send_data(0x66, '')
|
||||
raise RuntimeError('Invalid command did not return error')
|
||||
except CtapError as e:
|
||||
assert(e.code == CtapError.ERR.INVALID_COMMAND)
|
||||
print('PASS: invalid HID command')
|
||||
|
||||
|
||||
print('Sending packet with too large of a length.')
|
||||
self.send_raw('\x80\x1d\xba\x00')
|
||||
cmd,resp = self.recv_raw()
|
||||
self.check_error(resp, CtapError.ERR.INVALID_LENGTH)
|
||||
print('PASS: invalid length')
|
||||
|
||||
print('Sending packets that skip a sequence number.')
|
||||
self.send_raw('\x81\x10\x00')
|
||||
self.send_raw('\x00')
|
||||
self.send_raw('\x01')
|
||||
self.send_raw('\x02')
|
||||
# skip 3
|
||||
self.send_raw('\x04')
|
||||
cmd,resp = self.recv_raw()
|
||||
self.check_error(resp, CtapError.ERR.INVALID_SEQ)
|
||||
print('PASS: invalid sequence')
|
||||
|
||||
print('Resync and send ping')
|
||||
try:
|
||||
r = self.send_data(CTAPHID.INIT, '\x11\x22\x33\x44\x55\x66\x77\x88')
|
||||
pingdata = os.urandom(100)
|
||||
r = self.send_data(CTAPHID.PING, pingdata)
|
||||
if (r != pingdata):
|
||||
raise ValueError('Ping data not echo\'d')
|
||||
except CtapError as e:
|
||||
raise RuntimeError('resync fail: ', e)
|
||||
print('PASS: resync and ping')
|
||||
|
||||
print('Send ping and abort it')
|
||||
self.send_raw('\x81\x10\x00')
|
||||
self.send_raw('\x00')
|
||||
self.send_raw('\x01')
|
||||
try:
|
||||
r = self.send_data(CTAPHID.INIT, '\x11\x22\x33\x44\x55\x66\x77\x88')
|
||||
except CtapError as e:
|
||||
raise RuntimeError('resync fail: ', e)
|
||||
print('PASS: interrupt ping with resync')
|
||||
|
||||
|
||||
print('Send ping and abort it')
|
||||
|
||||
if __name__ == '__main__':
|
||||
t = Tester()
|
||||
|
|
316
ctaphid.c
316
ctaphid.c
|
@ -34,13 +34,22 @@ typedef struct
|
|||
uint8_t buf[HID_MESSAGE_SIZE];
|
||||
} CTAPHID_WRITE_BUFFER;
|
||||
|
||||
struct CID
|
||||
{
|
||||
uint32_t cid;
|
||||
uint64_t last_used;
|
||||
uint8_t busy;
|
||||
uint8_t last_cmd;
|
||||
};
|
||||
|
||||
|
||||
#define SUCESS 0
|
||||
#define SEQUENCE_ERROR 1
|
||||
|
||||
static int state;
|
||||
static struct CID CIDS[10];
|
||||
#define CID_MAX (sizeof(CIDS)/sizeof(struct CID))
|
||||
|
||||
static int active_cid;
|
||||
static uint64_t active_cid_timestamp;
|
||||
|
||||
static uint8_t ctap_buffer[CTAPHID_BUFFER_SIZE];
|
||||
|
@ -49,8 +58,6 @@ static uint16_t ctap_buffer_bcnt;
|
|||
static int ctap_buffer_offset;
|
||||
static int ctap_packet_seq;
|
||||
|
||||
static uint32_t _next_cid = 0;
|
||||
|
||||
static void buffer_reset();
|
||||
|
||||
#define CTAPHID_WRITE_INIT 0x01
|
||||
|
@ -63,28 +70,61 @@ static void ctaphid_write(CTAPHID_WRITE_BUFFER * wb, void * _data, int len);
|
|||
void ctaphid_init()
|
||||
{
|
||||
state = IDLE;
|
||||
active_cid = 0;
|
||||
buffer_reset();
|
||||
active_cid_timestamp = millis();
|
||||
}
|
||||
|
||||
static uint32_t set_next_cid(uint32_t cid)
|
||||
{
|
||||
_next_cid = cid;
|
||||
ctap_reset_state();
|
||||
}
|
||||
|
||||
static uint32_t get_new_cid()
|
||||
{
|
||||
static uint32_t cid = 1;
|
||||
|
||||
if (_next_cid != 0)
|
||||
do
|
||||
{
|
||||
int tmp = _next_cid;
|
||||
_next_cid = 0;
|
||||
return tmp;
|
||||
}
|
||||
cid++;
|
||||
}while(cid == 0 || cid == 0xffffffff);
|
||||
return cid;
|
||||
}
|
||||
|
||||
return cid++;
|
||||
static int8_t add_cid(uint32_t cid)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < CID_MAX-1; i++)
|
||||
{
|
||||
if (!CIDS[i].busy)
|
||||
{
|
||||
CIDS[i].cid = cid;
|
||||
CIDS[i].busy = 1;
|
||||
CIDS[i].last_used = millis();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int8_t cid_exists(uint32_t cid)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < CID_MAX-1; i++)
|
||||
{
|
||||
if (CIDS[i].cid == cid)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int8_t cid_refresh(uint32_t cid)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < CID_MAX-1; i++)
|
||||
{
|
||||
if (CIDS[i].cid == cid)
|
||||
{
|
||||
CIDS[i].last_used = millis();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int is_broadcast(CTAPHID_PACKET * pkt)
|
||||
|
@ -102,10 +142,6 @@ static int is_cont_pkt(CTAPHID_PACKET * pkt)
|
|||
return !(pkt->pkt.init.cmd & TYPE_INIT);
|
||||
}
|
||||
|
||||
static int is_active_cid(CTAPHID_PACKET * pkt)
|
||||
{
|
||||
return (pkt->cid == active_cid);
|
||||
}
|
||||
|
||||
static int is_timed_out()
|
||||
{
|
||||
|
@ -252,106 +288,148 @@ static void ctaphid_send_error(uint32_t cid, uint8_t error)
|
|||
ctaphid_write(&wb, NULL, 0);
|
||||
}
|
||||
|
||||
static void send_init_response(uint32_t oldcid, uint32_t newcid, uint8_t * nonce)
|
||||
{
|
||||
CTAPHID_INIT_RESPONSE init_resp;
|
||||
CTAPHID_WRITE_BUFFER wb;
|
||||
ctaphid_write_buffer_init(&wb);
|
||||
wb.cid = oldcid;
|
||||
wb.cmd = CTAPHID_INIT;
|
||||
wb.bcnt = 17;
|
||||
|
||||
memmove(init_resp.nonce, nonce, 8);
|
||||
init_resp.cid = newcid;
|
||||
init_resp.protocol_version = 0;//?
|
||||
init_resp.version_major = 0;//?
|
||||
init_resp.version_minor = 0;//?
|
||||
init_resp.build_version = 0;//?
|
||||
init_resp.capabilities = CTAP_CAPABILITIES;
|
||||
|
||||
ctaphid_write(&wb,&init_resp,sizeof(CTAPHID_INIT_RESPONSE));
|
||||
ctaphid_write(&wb,NULL,0);
|
||||
}
|
||||
|
||||
|
||||
void u2f_hid_check_timeouts()
|
||||
{
|
||||
uint8_t i;
|
||||
for(i = 0; i < CID_MAX; i++)
|
||||
{
|
||||
if (CIDS[i].busy && ((millis() - CIDS[i].last_used) >= 750))
|
||||
{
|
||||
printf("TIMEOUT CID: %08x\n", CIDS[i].cid);
|
||||
ctaphid_send_error(CIDS[i].cid, CTAP1_ERR_TIMEOUT);
|
||||
memset(CIDS + i, 0, sizeof(struct CID));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ctaphid_handle_packet(uint8_t * pkt_raw)
|
||||
{
|
||||
CTAPHID_PACKET * pkt = (CTAPHID_PACKET *)(pkt_raw);
|
||||
|
||||
printf("Recv packet\n");
|
||||
printf(" CID: %08x active(%08x)\n", pkt->cid, active_cid);
|
||||
printf(" CID: %08x \n", pkt->cid);
|
||||
printf(" cmd: %02x\n", pkt->pkt.init.cmd);
|
||||
if (!is_cont_pkt(pkt)) printf(" length: %d\n", ctaphid_packet_len(pkt));
|
||||
|
||||
int ret;
|
||||
uint8_t status;
|
||||
uint32_t oldcid;
|
||||
static CTAPHID_INIT_RESPONSE init_resp;
|
||||
uint32_t newcid;
|
||||
static CTAPHID_WRITE_BUFFER wb;
|
||||
uint32_t active_cid;
|
||||
|
||||
CTAP_RESPONSE ctap_resp;
|
||||
|
||||
|
||||
start_over:
|
||||
|
||||
switch (state)
|
||||
if (is_init_pkt(pkt))
|
||||
{
|
||||
case IDLE:
|
||||
if (is_broadcast(pkt))
|
||||
{
|
||||
printf("starting a new request\n");
|
||||
state = HANDLING_REQUEST;
|
||||
buffer_packet(pkt);
|
||||
}
|
||||
if (ctaphid_packet_len(pkt) != 8)
|
||||
{
|
||||
printf("Error,invalid length field for init packet\n");
|
||||
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_LENGTH);
|
||||
return;
|
||||
}
|
||||
if (pkt->cid == 0)
|
||||
{
|
||||
printf("Error, invalid cid 0\n");
|
||||
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_PARAMETER);
|
||||
return;
|
||||
}
|
||||
|
||||
ctaphid_init();
|
||||
if (is_broadcast(pkt))
|
||||
{
|
||||
// Check if any existing cids are busy first ?
|
||||
printf("adding a new cid\n");
|
||||
oldcid = CTAPHID_BROADCAST_CID;
|
||||
newcid = get_new_cid();
|
||||
ret = add_cid(newcid);
|
||||
// handle init here
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("synchronizing to cid\n");
|
||||
oldcid = pkt->cid;
|
||||
newcid = pkt->cid;
|
||||
if (cid_exists(newcid))
|
||||
ret = cid_refresh(newcid);
|
||||
else
|
||||
{
|
||||
printf("Error, unknown request\n");
|
||||
ctaphid_send_error(pkt->cid, ERR_INVALID_PAR);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case HANDLING_REQUEST:
|
||||
if (is_active_cid(pkt))
|
||||
{
|
||||
if (is_init_pkt(pkt))
|
||||
{
|
||||
printf("received abort request from %08x\n", pkt->cid);
|
||||
ctaphid_write_buffer_init(&wb);
|
||||
|
||||
wb.cid = active_cid;
|
||||
active_cid_timestamp = millis();
|
||||
|
||||
ctaphid_init();
|
||||
|
||||
active_cid = wb.cid;
|
||||
wb.cmd = CTAPHID_INIT;
|
||||
wb.bcnt = 0;
|
||||
ctaphid_write(&wb, ctap_buffer, buffer_len());
|
||||
ctaphid_write(&wb, NULL, 0);
|
||||
return;
|
||||
}
|
||||
else if (!is_cont_pkt(pkt) && buffer_status() == BUFFERING)
|
||||
{
|
||||
printf("Error, expecting cont packet\n");
|
||||
ctaphid_send_error(pkt->cid, ERR_INVALID_PAR);
|
||||
return;
|
||||
}
|
||||
else if(!is_cont_pkt(pkt))
|
||||
{
|
||||
if (ctaphid_packet_len(pkt) > CTAPHID_BUFFER_SIZE)
|
||||
{
|
||||
printf("Error, internal buffer not big enough\n");
|
||||
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_LENGTH);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
active_cid_timestamp = millis();
|
||||
ret = buffer_packet(pkt);
|
||||
if (ret == SEQUENCE_ERROR)
|
||||
{
|
||||
printf("Sequence error\n");
|
||||
ctaphid_send_error(pkt->cid, ERR_INVALID_SEQ);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (is_timed_out())
|
||||
{
|
||||
printf("dropping last channel -- timeout");
|
||||
oldcid = active_cid;
|
||||
ctaphid_init();
|
||||
ctaphid_send_error(active_cid, ERR_MSG_TIMEOUT);
|
||||
goto start_over;
|
||||
}
|
||||
else
|
||||
{
|
||||
ctaphid_send_error(pkt->cid, ERR_CHANNEL_BUSY);
|
||||
printf("Too busy with current transaction\n");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("invalid state; abort\n");
|
||||
exit(1);
|
||||
ret = add_cid(newcid);
|
||||
}
|
||||
if (ret == -1)
|
||||
{
|
||||
printf("Error, not enough memory for new CID. return BUSY.\n");
|
||||
ctaphid_send_error(pkt->cid, CTAP1_ERR_CHANNEL_BUSY);
|
||||
return;
|
||||
}
|
||||
send_init_response(oldcid, newcid, pkt->pkt.init.payload);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if matches existing CID
|
||||
if (cid_exists(pkt->cid))
|
||||
{
|
||||
if (! is_cont_pkt(pkt))
|
||||
{
|
||||
if (ctaphid_packet_len(pkt) > CTAPHID_BUFFER_SIZE)
|
||||
{
|
||||
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_LENGTH);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (buffer_packet(pkt) == SEQUENCE_ERROR)
|
||||
{
|
||||
printf("Buffering sequence error\n");
|
||||
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_SEQ);
|
||||
return;
|
||||
}
|
||||
ret = cid_refresh(pkt->cid);
|
||||
if (ret != 0)
|
||||
{
|
||||
printf("Error, refresh cid failed\n");
|
||||
exit(1);
|
||||
}
|
||||
active_cid = pkt->cid;
|
||||
}
|
||||
else if (is_cont_pkt(pkt))
|
||||
{
|
||||
printf("ignoring unwarranted cont packet\n");
|
||||
// Ignore
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("ignoring unwarranted init packet\n");
|
||||
// Ignore
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
switch(buffer_status())
|
||||
|
@ -367,37 +445,8 @@ start_over:
|
|||
switch(buffer_cmd())
|
||||
{
|
||||
case CTAPHID_INIT:
|
||||
printf("CTAPHID_INIT\n");
|
||||
|
||||
if (buffer_len() != 8)
|
||||
{
|
||||
printf("Error,invalid length field for init packet\n");
|
||||
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_LENGTH);
|
||||
return;
|
||||
}
|
||||
|
||||
active_cid = get_new_cid();
|
||||
|
||||
printf("cid: %08x\n",active_cid);
|
||||
active_cid_timestamp = millis();
|
||||
|
||||
ctaphid_write_buffer_init(&wb);
|
||||
wb.cid = CTAPHID_BROADCAST_CID;
|
||||
wb.cmd = CTAPHID_INIT;
|
||||
wb.bcnt = 17;
|
||||
|
||||
memmove(init_resp.nonce, pkt->pkt.init.payload, 8);
|
||||
init_resp.cid = active_cid;
|
||||
init_resp.protocol_version = 0;//?
|
||||
init_resp.version_major = 0;//?
|
||||
init_resp.version_minor = 0;//?
|
||||
init_resp.build_version = 0;//?
|
||||
init_resp.capabilities = CTAP_CAPABILITIES;
|
||||
|
||||
ctaphid_write(&wb,&init_resp,sizeof(CTAPHID_INIT_RESPONSE));
|
||||
ctaphid_write(&wb,NULL,0);
|
||||
|
||||
|
||||
printf("CTAPHID_INIT, error this should already be handled\n");
|
||||
exit(1);
|
||||
break;
|
||||
case CTAPHID_PING:
|
||||
printf("CTAPHID_PING\n");
|
||||
|
@ -476,6 +525,7 @@ start_over:
|
|||
|
||||
default:
|
||||
printf("error, unimplemented HID cmd: %02x\r\n", buffer_cmd());
|
||||
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_COMMAND);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ void ctaphid_init();
|
|||
|
||||
void ctaphid_handle_packet(uint8_t * pkt_raw);
|
||||
|
||||
void u2f_hid_check_timeouts();
|
||||
|
||||
|
||||
#define ctaphid_packet_len(pkt) ((uint16_t)((pkt)->pkt.init.bcnth << 8) | ((pkt)->pkt.init.bcntl))
|
||||
|
|
11
main.c
11
main.c
|
@ -50,11 +50,14 @@ int main(int argc, char * argv[])
|
|||
|
||||
while(1)
|
||||
{
|
||||
usbhid_recv(hidmsg);
|
||||
printf("%d>> ",count++); dump_hex(hidmsg,sizeof(hidmsg));
|
||||
if (usbhid_recv(hidmsg) > 0)
|
||||
{
|
||||
printf("%d>> ",count++); dump_hex(hidmsg,sizeof(hidmsg));
|
||||
|
||||
ctaphid_handle_packet(hidmsg);
|
||||
memset(hidmsg, 0, sizeof(hidmsg));
|
||||
ctaphid_handle_packet(hidmsg);
|
||||
memset(hidmsg, 0, sizeof(hidmsg));
|
||||
}
|
||||
u2f_hid_check_timeouts();
|
||||
}
|
||||
|
||||
|
||||
|
|
32
udp_bridge.c
32
udp_bridge.c
|
@ -7,11 +7,13 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
int udp_server()
|
||||
|
@ -22,6 +24,16 @@ int udp_server()
|
|||
return 1;
|
||||
}
|
||||
|
||||
struct timeval read_timeout;
|
||||
read_timeout.tv_sec = 0;
|
||||
read_timeout.tv_usec = 10;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &read_timeout, sizeof(struct timeval)) != 0)
|
||||
{
|
||||
perror( "setsockopt" );
|
||||
exit(1);
|
||||
}
|
||||
/*fcntl(fd, F_SETFL, fcntl(fd,F_GETFL, 0)|O_NONBLOCK);*/
|
||||
|
||||
struct sockaddr_in serveraddr;
|
||||
memset( &serveraddr, 0, sizeof(serveraddr) );
|
||||
serveraddr.sin_family = AF_INET;
|
||||
|
@ -35,13 +47,31 @@ int udp_server()
|
|||
return fd;
|
||||
}
|
||||
|
||||
void udp_recv(int fd, uint8_t * buf, int size)
|
||||
int udp_recv(int fd, uint8_t * buf, int size)
|
||||
{
|
||||
|
||||
fd_set input;
|
||||
FD_ZERO(&input);
|
||||
FD_SET(fd, &input);
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 100000;
|
||||
int n = select(fd + 1, &input, NULL, NULL, &timeout);
|
||||
if (n == -1) {
|
||||
perror("select\n");
|
||||
exit(1);
|
||||
} else if (n == 0)
|
||||
return 0;
|
||||
if (!FD_ISSET(fd, &input))
|
||||
{
|
||||
|
||||
}
|
||||
int length = recvfrom( fd, buf, size, 0, NULL, 0 );
|
||||
if ( length < 0 ) {
|
||||
perror( "recvfrom failed" );
|
||||
exit(1);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
int udp_server();
|
||||
|
||||
// Recv from anyone
|
||||
void udp_recv(int fd, uint8_t * buf, int size);
|
||||
int udp_recv(int fd, uint8_t * buf, int size);
|
||||
|
||||
// Send to 127.0.0.1:7112
|
||||
void udp_send(int fd, uint8_t * buf, int size);
|
||||
|
|
14
usbhid.c
14
usbhid.c
|
@ -1,5 +1,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "usbhid.h"
|
||||
#include "udp_bridge.h"
|
||||
|
@ -13,10 +15,16 @@ void usbhid_init()
|
|||
serverfd = udp_server();
|
||||
}
|
||||
|
||||
// Receive 64 byte USB HID message
|
||||
void usbhid_recv(uint8_t * msg)
|
||||
// Receive 64 byte USB HID message, don't block, return size of packet, return 0 if nothing
|
||||
int usbhid_recv(uint8_t * msg)
|
||||
{
|
||||
udp_recv(serverfd, msg, HID_MESSAGE_SIZE);
|
||||
int l = udp_recv(serverfd, msg, HID_MESSAGE_SIZE);
|
||||
/*if (l && l != HID_MESSAGE_SIZE)*/
|
||||
/*{*/
|
||||
/*printf("Error, recv'd message of wrong size %d", l);*/
|
||||
/*exit(1);*/
|
||||
/*}*/
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
|
|
2
usbhid.h
2
usbhid.h
|
@ -7,7 +7,7 @@
|
|||
|
||||
void usbhid_init();
|
||||
|
||||
void usbhid_recv(uint8_t * msg);
|
||||
int usbhid_recv(uint8_t * msg);
|
||||
|
||||
void usbhid_send(uint8_t * msg);
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue