add some more files.

This commit is contained in:
NIIBE Yutaka
2010-08-18 12:57:45 +09:00
parent 6cfc5155f6
commit e6116828c5
14 changed files with 2299 additions and 6 deletions

4
src/.gdbinit Normal file
View File

@@ -0,0 +1,4 @@
set arm force-mode thumb
set arm fallback-mode thumb
target remote localhost:3333
monitor reset halt

View File

@@ -50,10 +50,10 @@ endif
#
# Define project name here
PROJECT = gpgtoken
PROJECT = gnuk
# Define linker script file here
LDSCRIPT= gpgtoken.ld
LDSCRIPT= gnuk.ld
# Imported source files
CHIBIOS = ../ChibiOS_2.0.2
@@ -78,7 +78,7 @@ CSRC = $(PORTSRC) \
$(CHIBIOS)/os/various/syscalls.c \
$(STMUSBSRC) \
$(USBCDCSRC) \
main.c hw_config.c usb_lld.c
main.c hw_config.c usb_lld.c usb_desc.c usb_prop.c
# List ASM source files here
ASMSRC = $(PORTASM) \

570
src/gpg.c Normal file
View File

@@ -0,0 +1,570 @@
/*
* gpg.c --
*
* Copyright (C) 2010 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
*
* Gnuk is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#define RSA_SIGNATURE_LENGTH 128 /* 128 byte == 1024-bit */
extern unsigned char *rsa_sign (unsigned char *);
#define INS_PUT_DATA 0xDA
#define INS_VERIFY 0x20
#define INS_GET_DATA 0xCA
#define INS_GET_RESPONSE 0xC0
#define INS_SELECT_FILE 0xA4
#define INS_READ_BINARY 0xB0
#define INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR 0x47
#define INS_PSO 0x2A
static const char const select_file_TOP_result[] =
{ 0x00, 0x00, 0x0b, 0x10, 0x3f, 0x00, 0x38, 0xff, 0xff, 0x44,
0x44, 0x01, 0x05, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 };
static const char const get_data_64_result[] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const char const get_data_5e_result[] =
{ /* Login Data */
'g', 'n', 'i', 'i', 'b', 'e'
};
/***** do_65 is compound object of { do_47, do_4f, do_c0,..,c6,cd }*/
const unsigned char const do_6e_head[] =
{
0x6e, 0x81, 2*10+3+16+1+1+1+1+7+60+60+12 /* (> 128) */
};
const char const do_47[] = /* Card Capabilities */
{
0x47, 3,
0x00 /*???*/, 0x00 /*???*/, 0x00 /*???*/
/* XXX: See ISO 7816-4 for first byte and second byte */
};
const char const do_4f[] = /* AID */
{
0x4f, 16,
0xD2, 0x76, 0x00, 0x01, 0x24, 0x01,
0x01, 0x01, /* Version 1.1 */
0xF5, 0x17, /* Manufacturer (FSIJ) */
0x00, 0x00, 0x00, 0x02, /* Serial */
0x00, 0x00
};
const char const do_c0[] =
{ /* Extended capability */
0xc0, 1,
0x00
};
const char const do_c1[] =
{ /* Algorithm Attributes Signature ??? */
0xc1, 1,
0x01, /* RSA */ /*??? should have length modulus, length exponent ??? */
};
const char const do_c2[] =
{ /* Algorithm Attributes Decryption ??? */
0xc2, 1,
0x00
};
const char const do_c3[] =
{ /* Algorithm Attributes Authentication ??? */
0xc3, 1,
0x00
};
const char const do_c4[] =
{ /* CHV status bytes */
0xc4, 7,
0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01
};
const char const do_c5[] =
{
0xc5, 60,
/* sign */
0x5b, 0x85, 0x67, 0x3c, 0x08, 0x4f, 0x80, 0x0d,
0x54, 0xac, 0x95, 0x1c, 0x35, 0x15, 0x97, 0xcc,
0xe5, 0x02, 0xbf, 0xcd,
/* enc */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
/* auth */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
const char const do_c6[] = /* CA Fingerprints */
{
0xc6, 60,
/* c6 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
/* c7 */
0x5b, 0x85, 0x67, 0x3c, 0x08, 0x4f, 0x80, 0x0d,
0x54, 0xac, 0x95, 0x1c, 0x35, 0x15, 0x97, 0xcc,
0xe5, 0x02, 0xbf, 0xcd,
/* c8 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
const char const do_cd[] =
{ /* Generation time */
0xcd, 12,
0x00, 0x00, 0x00, 0x00,
0x49, 0x8a, 0x50, 0x7a, /* 0xce */
0x00, 0x00, 0x00, 0x00,
};
/*************************/
/***** do_65 is compound object of { do_5b, do_5f2d, do_5f35 }*/
const char const do_65_head[] =
{
0x65, 2*1+3*2+12+2+1
};
const char const do_5b[] =
{
0x5b, 12,
'N', 'I', 'I', 'B', 'E', ' ', 'Y', 'u', 't', 'a', 'k', 'a'
};
const char const do_5f2d[] =
{
0x5f, 0x2d, 2,
'j', 'a'
};
const char const do_5f35[] =
{
0x5f, 0x35, 1,
'1'
};
/****************************/
/* do_7a is compound object of { do_93 } */
const char const do_7a_head[] =
{
0x7a, 2+3
};
/* Digital Signature Counter (3-bytes) */
const char const do_93[] =
{
0x93, 3,
0, 0, 0
};
/****************************/
const char const do_5f50[] =
{
0x5f, 0x50, 20,
'h', 't', 't', 'p', ':', '/', '/', 'w', 'w', 'w',
'.', 'f', 's', 'i', 'j', '.', 'o', 'r', 'g', '/'
};
/*
* 73
* 101
* 102
* 103
* 104
*
* 65 - 5b, 5f2d, 5f35
* 6e - 47, 4f, c0, c1, c2, c3, c4, c5, c6, cd
* 7a - 93
*
*
* 65 L-65 [5b L-5b .... ] [5f2d 2 'j' 'a'] [5f35 1 '1']
* 6e L-6e [47 3 x x x ] [4f L-4f ...] [c0 L-c0 ...] ...
* 7a L-7a [93 L-93 ... ]
*/
static byte
process_command_adpu (void)
{
if (icc_read_buf[1] == INS_GET_RESPONSE)
{
stx_put_string (" - GET Response\r\n");
if ((icc_result_flag & ICC_RESULT_BUF))
return 0;
else
{
stx_put_string ("Wrong GET Response\r\n");
return 1;
}
}
icc_result_flag = 0;
/*
INS_VERIFY
00 20 00 81 06 - ???
CHV1
00 20 00 82 06 - ???
CHV2
00 20 00 83 08 - ???
CHV3
*/
if (icc_read_buf[1] == INS_PUT_DATA)
{
stx_put_string (" - PUT DATA\r\n");
icc_result_value = 0x9000; /* 6a88: No record */
icc_result_len = 0;
icc_result_flag = 0;
return 0;
}
if (icc_read_buf[1] == INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR)
{
stx_put_string (" - Generate Asymmetric Key Pair\r\n");
if (icc_read_buf[2] == 0x81)
{
/*
* tag: 0x7f49 public key data
* tag: 0x0081 RSA modulus
* tag: 0x0082 RSA exponent
*
* TAG
* [0x7f 0x49][LEN][DATA]
* _______/ \_________________
* / \
* [0x81][128][DATA][0x82][3][DATA]
* __/ \__ 0x01, 0x00, 0x01
* / \
* 0x81 0x80
*/
if (icc_read_buf[6] == 0x00 && icc_read_buf[5] == 0xb6)
{ /* Key for Sign */
static const char const get_data_sigkey_result[] =
{
0x7f, 0x49, 0x81, 0x88,
0x81, 0x81, 0x80,
/* 128-byte data */
/* modulus */
0xdb, 0xca, 0x58, 0x74, 0x44, 0x8e, 0x1a, 0x2c,
0xa0, 0x91, 0xac, 0xc4, 0xe2, 0x77, 0x2b, 0x90,
0xcf, 0x3c, 0x7e, 0x81, 0xdc, 0x8d, 0xb0, 0xe2,
0xf1, 0xfe, 0x56, 0x7e, 0x54, 0x57, 0xf0, 0xd8,
0xb1, 0xb1, 0xaa, 0x9d, 0x8f, 0xb0, 0x56, 0x01,
0xaa, 0x6b, 0xa7, 0x2e, 0xce, 0x01, 0x20, 0xd2,
0xf8, 0xf5, 0x85, 0x3a, 0xc2, 0x73, 0xf9, 0x66,
0x30, 0x28, 0x65, 0x5e, 0x3f, 0x91, 0xaf, 0x3f,
0xf6, 0x1c, 0x31, 0x2f, 0xa2, 0x91, 0xbb, 0x41,
0x91, 0x41, 0x08, 0x0a, 0xc5, 0x3e, 0x39, 0xda,
0x2f, 0x6f, 0x58, 0x51, 0xe2, 0xd2, 0xe9, 0x42,
0x8a, 0x7b, 0x72, 0x7b, 0x15, 0xf6, 0xf6, 0x6a,
0x12, 0x6e, 0x0c, 0x15, 0x24, 0x13, 0x16, 0x55,
0x3a, 0xf1, 0xa7, 0x16, 0x3e, 0xe9, 0xc8, 0x3d,
0x2c, 0x3d, 0xae, 0x51, 0x2d, 0x7f, 0xef, 0x92,
0x25, 0x6a, 0xbb, 0x02, 0x03, 0x70, 0x45, 0x3d,
/* public exponent */
0x82, 3, 0x01, 0x00, 0x01
};
icc_result_value = get_data_sigkey_result;
icc_result_len = sizeof (get_data_sigkey_result);
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
}
else if (icc_read_buf[6] == 0x00 && icc_read_buf[5] == 0xb8)
{ /* Key for Encryption */
static const char const get_data_enckey_result[] =
{
0x7f, 0x49, 0x81, 0x88,
0x81, 0x81, 0x80,
/* 128-byte data */
0xB2, 0x19, 0x91, 0x42, 0x27, 0xC7, 0x97, 0xFE,
0x92, 0x64, 0x42, 0xCA, 0xE3, 0x66, 0x4D, 0xD0,
0x31, 0xE4, 0x10, 0x31, 0x0F, 0xC7, 0x07, 0x4A,
0xAA, 0x6D, 0x31, 0xA2, 0x88, 0x68, 0xAF, 0x45,
0x8E, 0x42, 0x12, 0xFF, 0xB6, 0xEF, 0x6E, 0x54,
0x7E, 0x51, 0x8E, 0xBC, 0xE8, 0x18, 0x79, 0xA7,
0xBC, 0xA8, 0x14, 0x8B, 0xE7, 0x91, 0x57, 0x38,
0xCE, 0x4F, 0x6E, 0x16, 0x48, 0xCB, 0xD6, 0x0B,
0x3A, 0x53, 0x70, 0xF3, 0xFC, 0xFA, 0xC3, 0x58,
0x3D, 0xE7, 0x2A, 0x5E, 0xDD, 0xE1, 0x38, 0x82,
0x57, 0x87, 0x3A, 0xDC, 0x34, 0xDE, 0xCD, 0x5D,
0x33, 0x1C, 0xAB, 0xB0, 0x1B, 0xEE, 0x82, 0x43,
0x7B, 0xAC, 0xF8, 0xF0, 0xB2, 0x62, 0xB2, 0x6D,
0x09, 0xED, 0x2E, 0xD1, 0xBA, 0xB8, 0xC6, 0x96,
0xFA, 0x3E, 0xB4, 0xE3, 0xFE, 0x68, 0xF9, 0x51,
0x9A, 0x8C, 0x8B, 0x20, 0x93, 0xD0, 0x2E, 0x0F,
0x82, 3, 0x01, 0x00, 0x01
};
icc_result_value = get_data_enckey_result;
icc_result_len = sizeof (get_data_enckey_result);
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
}
/* icc_read_buf[5] == 0xa4 */
else
{
icc_result_value = 0x6a88; /* No record */
icc_result_len = 0;
icc_result_flag = 0;
}
}
else
{
icc_result_value = 0x6a88; /* No record */
icc_result_len = 0;
icc_result_flag = 0;
}
}
else if (icc_read_buf[1] == INS_READ_BINARY)
{ /* it must be for DF 0x2f02 */
stx_put_string (" - Read binary\r\n");
if (icc_read_buf[3] >= 6)
{
icc_result_value = 0x6b00; /* BAD_P0_P1 */
icc_result_len = 0;
icc_result_flag = 0;
}
else
{ /* Tag 5a, serial number */
static const char const get_data_rb_result[] = { 0x5a, 0x4, 0x01, 0x02, 0x03, 0x04 };
icc_result_value = (word)get_data_rb_result;
icc_result_len = sizeof (get_data_rb_result);
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
/* XXX: Next get response returns 6282??? eof_reached ??? */
}
}
else if (icc_read_buf[1] == INS_SELECT_FILE)
{
if (icc_read_buf[2] == 4) /* Selection by DF name */
{
stx_put_string (" - select DF by name\r\n");
/*
* XXX: Should return contents.
*/
if (1)
{
icc_result_value = 0x9000;
icc_result_len = 0;
icc_result_flag = 0;
}
}
else if (icc_read_buf[4] == 2
&& icc_read_buf[5] == 0x2f
&& icc_read_buf[6] == 02)
{
stx_put_string (" - select 0x2f02 EF\r\n");
/*
* MF.EF-GDO -- Serial number of the card and name of the owner
*/
icc_result_value = 0x9000;
icc_result_len = 0;
icc_result_flag = 0;
}
else
if (icc_read_buf[4] == 2
&& icc_read_buf[5] == 0x3f
&& icc_read_buf[6] == 0)
{
stx_put_string (" - select ROOT MF\r\n");
if (icc_read_buf[3] == 0x0c)
{
icc_result_value = 0x9000;
icc_result_len = 0;
icc_result_flag = 0;
}
else
{
icc_result_value = select_file_TOP_result;
icc_result_len = sizeof (select_file_TOP_result);
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
}
}
else
{
stx_put_string (" - select ?? \r\n");
icc_result_value = 0x6a82; /* File missing */
icc_result_len = 0;
icc_result_flag = 0;
}
}
else if (icc_read_buf[1] == INS_GET_DATA)
{
stx_put_string (" - Get Data\r\n");
switch (((icc_read_buf[2]<<8) | icc_read_buf[3]))
{
case 0x4f: /* AID */
{
icc_result_value = (word)&do_4f[2];
icc_result_len = sizeof (do_4f) - 2;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x5e: /* Login data */
{
icc_result_value = (word)get_data_5e_result;
icc_result_len = sizeof (get_data_5e_result);
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x64:
{
icc_result_value = (word)get_data_64_result;
icc_result_len = sizeof (get_data_64_result);
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0xc0:
{
icc_result_value = (word)&do_c0[2];
icc_result_len = sizeof (do_c0) - 2;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0xc4:
{
icc_result_value = (word)&do_c4[2];
icc_result_len = sizeof (do_c4) - 2;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x5b: /* Name */
{
icc_result_value = (word)&do_5b[2];
icc_result_len = sizeof (do_5b) - 2;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x93: /* Digital Signature Counter (3-bytes) */
{
icc_result_value = (word)&do_93[2];
icc_result_len = sizeof (do_93) - 2;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0xc5: /* Fingerprints */
{
icc_result_value = &do_c5[2];
icc_result_len = sizeof (do_c5) - 2;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x5f2d: /* Language preference */
{
icc_result_value = (word)&do_5f2d[3];
icc_result_len = sizeof (do_5f2d) - 3;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x5f35: /* Sex */
{
icc_result_value = (word)&do_5f35[3];
icc_result_len = sizeof (do_5f35) - 3;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x5f50: /* URL */
{
icc_result_value = (word)&do_5f50[3];
icc_result_len = sizeof (do_5f50) - 3;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x65: /* Card Holder Related Data (Tag) */
{
icc_result_value = (word)do_65_head;
icc_result_len = do_65_head[1] + 2;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x6e: /* Application Related Data (Tag) */
{
icc_result_value = (word)do_6e_head;
icc_result_len = do_6e_head[2] + 3;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x7a: /* Security Support Template (Tag) */
{
icc_result_value = (word)do_7a_head;
icc_result_len = do_7a_head[1] + 2;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0xc6: /* List of CA fingerprints */
case 0xcd: /* List of generation dates/times public-key pairs */
default:
icc_result_value = 0x9000;
icc_result_len = 0;
icc_result_flag = 0;
}
}
else if (icc_read_buf[1] == INS_PSO)
{
stx_put_string (" - PSO\r\n");
if (icc_read_buf[2] == 0x9E && icc_read_buf[3] == 0x9A)
{
if (icc_read_len != 5 + 35 && icc_read_len != 5 + 35 + 1)
stx_put_string (" wrong length\r\n");
else
{
icc_result_value = rsa_sign (&icc_read_buf[5]);
icc_result_len = RSA_SIGNATURE_LENGTH;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_RAM;
}
stx_put_string ("done.\r\n");
}
else
{
stx_put_string (" - ???\r\n");
icc_result_value = 0x9000;
icc_result_len = 0;
icc_result_flag = 0;
}
}
else
{
stx_put_string (" - ???\r\n");
icc_result_value = 0x9000;
icc_result_len = 0;
icc_result_flag = 0;
}
return 0;
}

40
src/hw_config.c Normal file
View File

@@ -0,0 +1,40 @@
#include "ch.h"
#include "hal.h"
#include "usb_lib.h"
#include "usb_prop.h"
#include "usb_desc.h"
#include "hw_config.h"
#include "platform_config.h"
#include "usb_pwr.h"
void
Enter_LowPowerMode (void)
{
bDeviceState = SUSPENDED;
}
void
Leave_LowPowerMode (void)
{
DEVICE_INFO *pInfo = &Device_Info;
if (pInfo->Current_Configuration != 0)
bDeviceState = CONFIGURED;
else
bDeviceState = ATTACHED;
}
void
USB_Cable_Config (FunctionalState NewState)
{
if (NewState != DISABLE)
palClearPad (IOPORT3, GPIOC_DISC);
else
palSetPad (IOPORT3, GPIOC_DISC);
}
void
Get_SerialNum (void)
{
}

886
src/icc.c Normal file
View File

@@ -0,0 +1,886 @@
/*
* icc.c --
*
* Copyright (C) 2010 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
*
* Gnuk is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
enum icc_state {
ICC_STATE_INITIAL,
ICC_STATE_WAITING_ADPU,
ICC_STATE_BUSY1,
ICC_STATE_BUSY2,
ICC_STATE_BUSY3,
ICC_STATE_BUSY4,
ICC_STATE_BUSY5,
ICC_STATE_ADPU_RECEIVED_PARTIALLY,
ICC_STATE_ADPU_SENT_PARTIALLY,
};
#define RSA_SIGNATURE_LENGTH 128 /* 128 byte == 1024-bit */
extern unsigned char *rsa_sign (unsigned char *);
/* Three callbacks */
static byte icc_cycle;
byte icc_status;
/* GET_ICC_STATUS */
byte
icc_get_status (void)
{
#if 0
if (icc_status == ICC_STATUS_BUSY)
return ((icc_cycle++) & 0x0f) | ICC_STATUS_BUSY;
#endif
return icc_status;
}
/* XXX: need to be fixed... *//* T=0 */
const char *ATR = "\x3B\x02\xbe\xef";
task_t icc_wait_task;
byte icc_wait_result;
/* ICC_POWER_ON */
const byte *
icc_power_on (void)
{
task_t t = icc_wait_task;
if (t != 0)
{
icc_wait_task = 0;
need_resched = 1;
icc_wait_result = 1;
stx_wakeup (t);
}
return ATR;
}
word icc_initial_sp;
void icc_main (void);
extern word task[];
extern byte icc_write_buf[2];
byte icc_read_buf[143];
extern int icc_write_len;
extern int icc_read_len;
extern task_t icc_write_task;
extern task_t icc_read_task;
/* ICC_POWER_OFF */
void
icc_power_off (void)
{
#if 0
if (icc_read_task)
{
icc_read_task = 0;
icc_read_len = 0xff;
}
if (icc_write_task)
{
icc_write_task = 0;
icc_write_len = 0xff;
}
if (icc_wait_task)
{
icc_wait_task = 0;
icc_wait_result = 0;
}
icc_status = ICC_STATUS_BUSY;
stx_wakeup (ICC_TASK);
#endif
#if 1
extern stx_cancel_write (byte);
word sp = icc_initial_sp;
if (sp)
{
icc_status = ICC_STATUS_BUSY;
stx_cancel_write (ICC_TASK);
/* Push PC */
*(byte *)(sp - 1) = ((word)icc_main >> 8);
*(byte *)sp = ((word)icc_main & 0xff);
sp -= 32 + 1 + 2; /* Registers 0-31, SREG and PC */
need_resched = 1;
task[ICC_TASK] = sp;
stx_wakeup (ICC_TASK);
}
#endif
}
#define INS_PUT_DATA 0xDA
#define INS_VERIFY 0x20
#define INS_GET_DATA 0xCA
#define INS_GET_RESPONSE 0xC0
#define INS_SELECT_FILE 0xA4
#define INS_READ_BINARY 0xB0
#define INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR 0x47
#define INS_PSO 0x2A
extern byte *icc_read_p;
word icc_result_value; /* Buffer pointer or status word */
byte icc_result_flag;
byte icc_result_len;
#define ICC_RESULT_BUF 0x80
#define ICC_RESULT_BUF_MASK 0x7f
#define ICC_RESULT_BUF_ROM 0
#define ICC_RESULT_BUF_EEPROM 1
#define ICC_RESULT_BUF_RAM 2
/************************ 3 */
static void
icc_success (void)
{
icc_result_flag = 0;
}
byte
stx_icc_read (void)
{
asm volatile ("cli");
icc_read_p = icc_read_buf;
icc_read_len = 0;
icc_read_task = current;
task_wait_bits |= taskset_current ();
icc_status = ICC_STATUS_READY;
stx_yield ();
if (icc_read_len == 5
&& (icc_read_buf[1] == INS_SELECT_FILE
|| icc_read_buf[1] == INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR
|| icc_read_buf[1] == INS_PUT_DATA
|| icc_read_buf[1] == INS_VERIFY
|| icc_read_buf[1] == INS_PSO))
{ /* Recieve a packet again */
asm volatile ("cli");
icc_read_task = current;
task_wait_bits |= taskset_current ();
icc_status = ICC_STATUS_DATA;
stx_yield ();
}
return icc_read_len;
}
static byte
receive_command_adpu (void)
{
byte r;
char s[11];
if ((r = stx_icc_read ()) != 0xff)
{
int i;
for (i = 0; i < icc_read_len; i++)
{
sprintf (s, " %02x", icc_read_buf[i]);
stx_put_string (s);
}
}
return r;
}
static const char const select_file_TOP_result[] =
{ 0x00, 0x00, 0x0b, 0x10, 0x3f, 0x00, 0x38, 0xff, 0xff, 0x44,
0x44, 0x01, 0x05, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 };
static const char const get_data_64_result[] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const char const get_data_5e_result[] =
{ /* Login Data */
'g', 'n', 'i', 'i', 'b', 'e'
};
/***** do_65 is compound object of { do_47, do_4f, do_c0,..,c6,cd }*/
const unsigned char const do_6e_head[] =
{
0x6e, 0x81, 2*10+3+16+1+1+1+1+7+60+60+12 /* (> 128) */
};
const char const do_47[] = /* Card Capabilities */
{
0x47, 3,
0x00 /*???*/, 0x00 /*???*/, 0x00 /*???*/
/* XXX: See ISO 7816-4 for first byte and second byte */
};
const char const do_4f[] = /* AID */
{
0x4f, 16,
0xD2, 0x76, 0x00, 0x01, 0x24, 0x01,
0x01, 0x01, /* Version 1.1 */
0xF5, 0x17, /* Manufacturer (FSIJ) */
0x00, 0x00, 0x00, 0x02, /* Serial */
0x00, 0x00
};
const char const do_c0[] =
{ /* Extended capability */
0xc0, 1,
0x00
};
const char const do_c1[] =
{ /* Algorithm Attributes Signature ??? */
0xc1, 1,
0x01, /* RSA */ /*??? should have length modulus, length exponent ??? */
};
const char const do_c2[] =
{ /* Algorithm Attributes Decryption ??? */
0xc2, 1,
0x00
};
const char const do_c3[] =
{ /* Algorithm Attributes Authentication ??? */
0xc3, 1,
0x00
};
const char const do_c4[] =
{ /* CHV status bytes */
0xc4, 7,
0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01
};
const char const do_c5[] =
{
0xc5, 60,
/* sign */
0x5b, 0x85, 0x67, 0x3c, 0x08, 0x4f, 0x80, 0x0d,
0x54, 0xac, 0x95, 0x1c, 0x35, 0x15, 0x97, 0xcc,
0xe5, 0x02, 0xbf, 0xcd,
/* enc */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
/* auth */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
const char const do_c6[] = /* CA Fingerprints */
{
0xc6, 60,
/* c6 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
/* c7 */
0x5b, 0x85, 0x67, 0x3c, 0x08, 0x4f, 0x80, 0x0d,
0x54, 0xac, 0x95, 0x1c, 0x35, 0x15, 0x97, 0xcc,
0xe5, 0x02, 0xbf, 0xcd,
/* c8 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
const char const do_cd[] =
{ /* Generation time */
0xcd, 12,
0x00, 0x00, 0x00, 0x00,
0x49, 0x8a, 0x50, 0x7a, /* 0xce */
0x00, 0x00, 0x00, 0x00,
};
/*************************/
/***** do_65 is compound object of { do_5b, do_5f2d, do_5f35 }*/
const char const do_65_head[] =
{
0x65, 2*1+3*2+12+2+1
};
const char const do_5b[] =
{
0x5b, 12,
'N', 'I', 'I', 'B', 'E', ' ', 'Y', 'u', 't', 'a', 'k', 'a'
};
const char const do_5f2d[] =
{
0x5f, 0x2d, 2,
'j', 'a'
};
const char const do_5f35[] =
{
0x5f, 0x35, 1,
'1'
};
/****************************/
/* do_7a is compound object of { do_93 } */
const char const do_7a_head[] =
{
0x7a, 2+3
};
/* Digital Signature Counter (3-bytes) */
const char const do_93[] =
{
0x93, 3,
0, 0, 0
};
/****************************/
const char const do_5f50[] =
{
0x5f, 0x50, 20,
'h', 't', 't', 'p', ':', '/', '/', 'w', 'w', 'w',
'.', 'f', 's', 'i', 'j', '.', 'o', 'r', 'g', '/'
};
/*
* 73
* 101
* 102
* 103
* 104
*
* 65 - 5b, 5f2d, 5f35
* 6e - 47, 4f, c0, c1, c2, c3, c4, c5, c6, cd
* 7a - 93
*
*
* 65 L-65 [5b L-5b .... ] [5f2d 2 'j' 'a'] [5f35 1 '1']
* 6e L-6e [47 3 x x x ] [4f L-4f ...] [c0 L-c0 ...] ...
* 7a L-7a [93 L-93 ... ]
*/
static byte
process_command_adpu (void)
{
if (icc_read_buf[1] == INS_GET_RESPONSE)
{
stx_put_string (" - GET Response\r\n");
if ((icc_result_flag & ICC_RESULT_BUF))
return 0;
else
{
stx_put_string ("Wrong GET Response\r\n");
return 1;
}
}
icc_result_flag = 0;
/*
INS_VERIFY
00 20 00 81 06 - ???
CHV1
00 20 00 82 06 - ???
CHV2
00 20 00 83 08 - ???
CHV3
*/
if (icc_read_buf[1] == INS_PUT_DATA)
{
stx_put_string (" - PUT DATA\r\n");
icc_result_value = 0x9000; /* 6a88: No record */
icc_result_len = 0;
icc_result_flag = 0;
return 0;
}
if (icc_read_buf[1] == INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR)
{
stx_put_string (" - Generate Asymmetric Key Pair\r\n");
if (icc_read_buf[2] == 0x81)
{
/*
* tag: 0x7f49 public key data
* tag: 0x0081 RSA modulus
* tag: 0x0082 RSA exponent
*
* TAG
* [0x7f 0x49][LEN][DATA]
* _______/ \_________________
* / \
* [0x81][128][DATA][0x82][3][DATA]
* __/ \__ 0x01, 0x00, 0x01
* / \
* 0x81 0x80
*/
if (icc_read_buf[6] == 0x00 && icc_read_buf[5] == 0xb6)
{ /* Key for Sign */
static const char const get_data_sigkey_result[] =
{
0x7f, 0x49, 0x81, 0x88,
0x81, 0x81, 0x80,
/* 128-byte data */
/* modulus */
0xdb, 0xca, 0x58, 0x74, 0x44, 0x8e, 0x1a, 0x2c,
0xa0, 0x91, 0xac, 0xc4, 0xe2, 0x77, 0x2b, 0x90,
0xcf, 0x3c, 0x7e, 0x81, 0xdc, 0x8d, 0xb0, 0xe2,
0xf1, 0xfe, 0x56, 0x7e, 0x54, 0x57, 0xf0, 0xd8,
0xb1, 0xb1, 0xaa, 0x9d, 0x8f, 0xb0, 0x56, 0x01,
0xaa, 0x6b, 0xa7, 0x2e, 0xce, 0x01, 0x20, 0xd2,
0xf8, 0xf5, 0x85, 0x3a, 0xc2, 0x73, 0xf9, 0x66,
0x30, 0x28, 0x65, 0x5e, 0x3f, 0x91, 0xaf, 0x3f,
0xf6, 0x1c, 0x31, 0x2f, 0xa2, 0x91, 0xbb, 0x41,
0x91, 0x41, 0x08, 0x0a, 0xc5, 0x3e, 0x39, 0xda,
0x2f, 0x6f, 0x58, 0x51, 0xe2, 0xd2, 0xe9, 0x42,
0x8a, 0x7b, 0x72, 0x7b, 0x15, 0xf6, 0xf6, 0x6a,
0x12, 0x6e, 0x0c, 0x15, 0x24, 0x13, 0x16, 0x55,
0x3a, 0xf1, 0xa7, 0x16, 0x3e, 0xe9, 0xc8, 0x3d,
0x2c, 0x3d, 0xae, 0x51, 0x2d, 0x7f, 0xef, 0x92,
0x25, 0x6a, 0xbb, 0x02, 0x03, 0x70, 0x45, 0x3d,
/* public exponent */
0x82, 3, 0x01, 0x00, 0x01
};
icc_result_value = get_data_sigkey_result;
icc_result_len = sizeof (get_data_sigkey_result);
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
}
#if 0
else if (icc_read_buf[6] == 0x00 && icc_read_buf[5] == 0xb8)
{ /* Key for Encryption */
static const char const get_data_enckey_result[] =
{
0x7f, 0x49, 0x81, 0x88,
0x81, 0x81, 0x80,
/* 128-byte data */
0xB2, 0x19, 0x91, 0x42, 0x27, 0xC7, 0x97, 0xFE,
0x92, 0x64, 0x42, 0xCA, 0xE3, 0x66, 0x4D, 0xD0,
0x31, 0xE4, 0x10, 0x31, 0x0F, 0xC7, 0x07, 0x4A,
0xAA, 0x6D, 0x31, 0xA2, 0x88, 0x68, 0xAF, 0x45,
0x8E, 0x42, 0x12, 0xFF, 0xB6, 0xEF, 0x6E, 0x54,
0x7E, 0x51, 0x8E, 0xBC, 0xE8, 0x18, 0x79, 0xA7,
0xBC, 0xA8, 0x14, 0x8B, 0xE7, 0x91, 0x57, 0x38,
0xCE, 0x4F, 0x6E, 0x16, 0x48, 0xCB, 0xD6, 0x0B,
0x3A, 0x53, 0x70, 0xF3, 0xFC, 0xFA, 0xC3, 0x58,
0x3D, 0xE7, 0x2A, 0x5E, 0xDD, 0xE1, 0x38, 0x82,
0x57, 0x87, 0x3A, 0xDC, 0x34, 0xDE, 0xCD, 0x5D,
0x33, 0x1C, 0xAB, 0xB0, 0x1B, 0xEE, 0x82, 0x43,
0x7B, 0xAC, 0xF8, 0xF0, 0xB2, 0x62, 0xB2, 0x6D,
0x09, 0xED, 0x2E, 0xD1, 0xBA, 0xB8, 0xC6, 0x96,
0xFA, 0x3E, 0xB4, 0xE3, 0xFE, 0x68, 0xF9, 0x51,
0x9A, 0x8C, 0x8B, 0x20, 0x93, 0xD0, 0x2E, 0x0F,
0x82, 3, 0x01, 0x00, 0x01
};
icc_result_value = get_data_enckey_result;
icc_result_len = sizeof (get_data_enckey_result);
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
}
#endif
/* icc_read_buf[5] == 0xa4 */
else
{
icc_result_value = 0x6a88; /* No record */
icc_result_len = 0;
icc_result_flag = 0;
}
}
else
{
icc_result_value = 0x6a88; /* No record */
icc_result_len = 0;
icc_result_flag = 0;
}
}
else if (icc_read_buf[1] == INS_READ_BINARY)
{ /* it must be for DF 0x2f02 */
stx_put_string (" - Read binary\r\n");
if (icc_read_buf[3] >= 6)
{
icc_result_value = 0x6b00; /* BAD_P0_P1 */
icc_result_len = 0;
icc_result_flag = 0;
}
else
{ /* Tag 5a, serial number */
static const char const get_data_rb_result[] = { 0x5a, 0x4, 0x01, 0x02, 0x03, 0x04 };
icc_result_value = (word)get_data_rb_result;
icc_result_len = sizeof (get_data_rb_result);
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
/* XXX: Next get response returns 6282??? eof_reached ??? */
}
}
else if (icc_read_buf[1] == INS_SELECT_FILE)
{
if (icc_read_buf[2] == 4) /* Selection by DF name */
{
stx_put_string (" - select DF by name\r\n");
/*
* XXX: Should return contents.
*/
if (1)
{
icc_result_value = 0x9000;
icc_result_len = 0;
icc_result_flag = 0;
}
}
else if (icc_read_buf[4] == 2
&& icc_read_buf[5] == 0x2f
&& icc_read_buf[6] == 02)
{
stx_put_string (" - select 0x2f02 EF\r\n");
/*
* MF.EF-GDO -- Serial number of the card and name of the owner
*/
icc_result_value = 0x9000;
icc_result_len = 0;
icc_result_flag = 0;
}
else
if (icc_read_buf[4] == 2
&& icc_read_buf[5] == 0x3f
&& icc_read_buf[6] == 0)
{
stx_put_string (" - select ROOT MF\r\n");
if (icc_read_buf[3] == 0x0c)
{
icc_result_value = 0x9000;
icc_result_len = 0;
icc_result_flag = 0;
}
else
{
icc_result_value = select_file_TOP_result;
icc_result_len = sizeof (select_file_TOP_result);
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
}
}
else
{
stx_put_string (" - select ?? \r\n");
icc_result_value = 0x6a82; /* File missing */
icc_result_len = 0;
icc_result_flag = 0;
}
}
else if (icc_read_buf[1] == INS_GET_DATA)
{
stx_put_string (" - Get Data\r\n");
switch (((icc_read_buf[2]<<8) | icc_read_buf[3]))
{
case 0x4f: /* AID */
{
icc_result_value = (word)&do_4f[2];
icc_result_len = sizeof (do_4f) - 2;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x5e: /* Login data */
{
icc_result_value = (word)get_data_5e_result;
icc_result_len = sizeof (get_data_5e_result);
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x64:
{
icc_result_value = (word)get_data_64_result;
icc_result_len = sizeof (get_data_64_result);
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0xc0:
{
icc_result_value = (word)&do_c0[2];
icc_result_len = sizeof (do_c0) - 2;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0xc4:
{
icc_result_value = (word)&do_c4[2];
icc_result_len = sizeof (do_c4) - 2;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x5b: /* Name */
{
icc_result_value = (word)&do_5b[2];
icc_result_len = sizeof (do_5b) - 2;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x93: /* Digital Signature Counter (3-bytes) */
{
icc_result_value = (word)&do_93[2];
icc_result_len = sizeof (do_93) - 2;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0xc5: /* Fingerprints */
{
icc_result_value = &do_c5[2];
icc_result_len = sizeof (do_c5) - 2;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x5f2d: /* Language preference */
{
icc_result_value = (word)&do_5f2d[3];
icc_result_len = sizeof (do_5f2d) - 3;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x5f35: /* Sex */
{
icc_result_value = (word)&do_5f35[3];
icc_result_len = sizeof (do_5f35) - 3;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x5f50: /* URL */
{
icc_result_value = (word)&do_5f50[3];
icc_result_len = sizeof (do_5f50) - 3;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x65: /* Card Holder Related Data (Tag) */
{
icc_result_value = (word)do_65_head;
icc_result_len = do_65_head[1] + 2;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x6e: /* Application Related Data (Tag) */
{
icc_result_value = (word)do_6e_head;
icc_result_len = do_6e_head[2] + 3;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0x7a: /* Security Support Template (Tag) */
{
icc_result_value = (word)do_7a_head;
icc_result_len = do_7a_head[1] + 2;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_ROM;
break;
}
case 0xc6: /* List of CA fingerprints */
case 0xcd: /* List of generation dates/times public-key pairs */
default:
icc_result_value = 0x9000;
icc_result_len = 0;
icc_result_flag = 0;
}
}
else if (icc_read_buf[1] == INS_PSO)
{
stx_put_string (" - PSO\r\n");
if (icc_read_buf[2] == 0x9E && icc_read_buf[3] == 0x9A)
{
if (icc_read_len != 5 + 35 && icc_read_len != 5 + 35 + 1)
stx_put_string (" wrong length\r\n");
else
{
icc_result_value = rsa_sign (&icc_read_buf[5]);
icc_result_len = RSA_SIGNATURE_LENGTH;
icc_result_flag = ICC_RESULT_BUF | ICC_RESULT_BUF_RAM;
}
stx_put_string ("done.\r\n");
}
else
{
stx_put_string (" - ???\r\n");
icc_result_value = 0x9000;
icc_result_len = 0;
icc_result_flag = 0;
}
}
else
{
stx_put_string (" - ???\r\n");
icc_result_value = 0x9000;
icc_result_len = 0;
icc_result_flag = 0;
}
return 0;
}
#define ICC_RESULT_MAX_LEN 32
static byte
send_result_adpu (void)
{
byte r = 0;
if ((icc_result_flag & ICC_RESULT_BUF))
{
if ((icc_result_flag & ICC_RESULT_BUF_MASK) == ICC_RESULT_BUF_ROM
|| (icc_result_flag & ICC_RESULT_BUF_MASK) == ICC_RESULT_BUF_RAM)
{
byte r;
asm volatile ("cli");
icc_status = ICC_STATUS_DATA;
icc_write_task = current;
task_wait_bits |= taskset_current ();
r = stx_yield ();
if (r == 0)
{
if (icc_result_len <= ICC_RESULT_MAX_LEN)
{
icc_write_buf[0] = 0x90;
icc_write_buf[1] = 0x00;
}
else
{
icc_result_len -= ICC_RESULT_MAX_LEN;
icc_result_value += ICC_RESULT_MAX_LEN;
icc_write_buf[0] = 0x61;
icc_write_buf[1] = icc_result_len;
}
icc_write_len = 2;
asm volatile ("cli");
icc_status = ICC_STATUS_SW;
icc_write_task = current;
task_wait_bits |= taskset_current ();
stx_yield ();
}
}
else
;
}
else /* Status word */
{
icc_write_buf[0] = (icc_result_value >> 8);
icc_write_buf[1] = (icc_result_value & 0xff);
icc_write_len = 2;
asm volatile ("cli");
icc_status = ICC_STATUS_SW;
icc_write_task = current;
task_wait_bits |= taskset_current ();
stx_yield ();
}
return r;
}
byte
stx_icc_wait_power_on (void)
{
stx_put_string ("W\r\n");
asm volatile ("cli");
icc_status = ICC_STATUS_DATA; /* Ready to send ATR */
icc_wait_task = current;
task_wait_bits |= taskset_current ();
stx_yield ();
stx_put_string ("w\r\n");
if (icc_wait_result)
{
char s[10];
sprintf(s,"On %d\r\n", icc_wait_task);
stx_put_string (s);
}
else
stx_put_string ("Off?\r\n");
return icc_wait_result;
}
void
icc_main (void)
{
#if 1
word old_sp = icc_initial_sp;
icc_status = ICC_STATUS_BUSY;
icc_wait_task = 0;
icc_write_task = 0;
icc_read_task = 0;
icc_initial_sp = task[ICC_TASK] + 32 + 1 + 2;
if (old_sp != icc_initial_sp)
stx_put_string ("Start\r\n");
else
stx_put_string ("RESET\r\n");
#else
char s[12];
sprintf(s, "Start %d\r\n", current);
stx_put_string (s);
#endif
again:
if (stx_icc_wait_power_on ())
while (1)
{
byte r;
r = receive_command_adpu ();
if (r == 0xff) /* wait for XFR_BLOCK */
break;
if (r == 0)
{
stx_put_string ("zero size command packet\r\n");
continue;
}
if (process_command_adpu ())
continue;
if (send_result_adpu () == 0xff)
break;
}
stx_put_string ("Reset\r\n");
goto again;
}

148
src/usb.c Normal file
View File

@@ -0,0 +1,148 @@
/*
* usb.c --
*
* Copyright (C) 2010 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
*
* Gnuk is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#define ICC_POWER_ON 0x62
0 bMessageType 0x62
1 dwLength 0x00000000
5 bSlot 0x00 FIXED
6 bSeq 0x00-FF
7 bReserved 0x01 FIXED
8 abRFU 0x0000
0 bMessageType 0x80 Indicates RDR_to_PC_DataBlock
1 dwLength Size of bytes for the ATR
5 bSlot 0x00 FIXED
6 bSeq Sequence number for the corresponding command.
7 bStatus USB-ICC Status register as defined in Table 6.1-8
8 bError USB-ICC Error register as defined in Table 6.1-9
9 bChainParameter 0x00 Indicates that this message contains the complete ATR.
10 abData ATR
#define ICC_POWER_OFF 0x63
0 bMessageType 0x63 Indicates PC_to_RDR_IccPowerOn
1 dwLength 0x00000000 Message-specific data length
5 bSlot 0x00 FIXED
6 bSeq 0x00-FF Sequence number for command.
7 abRFU 0x000000
0 bMessageType 81h Indicates RDR_to_PC_SlotStatus
1 dwLength 0x00000000 Message-specific data length
5 bSlot 0x00 FIXED
6 bSeq Sequence number for the corresponding command.
7 bStatus USB-ICC Status register as defined in Table 6.1-8
8 bError USB-ICC Error register as defined in Table 6.1-9
9 bReserved 0x00 FIXED
#define XFR_BLOCK 0x6F
0 bMessageType 0x6F Indicates PC_to_RDR_XfrBlock
1 dwLength Size of abData field of this message
5 bSlot 0x00 FIXED
6 bSeq 0x00-FF Sequence number for command.
7 bReserved 0x00 FIXED
8 wLevelParameter
0x0000
the command APDU begins and ends with this command
0x0001
the command APDU begins with this command, and
continue in the next PC_to_RDR_XfrBlock
0x0002
this abData field continues a command APDU and
ends the command APDU
0x0003
the abData field continues a command APDU and
another block is to follow
0x0010
empty abData field, continuation of response APDU
is expected in the next RDR_to_PC_DataBlock.
10 abData Data block sent to the USB-ICC
0 bMessageType 0x80 Indicates RDR_to_PC_DataBlock
1 dwLength Size of abData field of this message
5 bSlot 0x00 FIXED
6 bSeq Sequence number for the corresponding command.
7 bStatus USB-ICC Status register as defined in Table 6.1-8
8 bError USB-ICC Error register as defined in Table 6.1-9
9 bChainParameter
Indicates if the response is complete, to be
continued or if the command APDU can continue
0x00: The response APDU begins and ends in this command
0x01: The response APDU begins with this command and is to continue
0x02: This abData field continues the response
APDU and ends the response APDU
0x03: This abData field continues the response
APDU and another block is to follow
0x10: Empty abData field, continuation of the
command APDU is expected in next PC_to_RDR_XfrBlock command
10 abData
/* status code and error code */
0 bmIccStatus 1 0, 1, 2 0= The USB-ICC is present and activated.
(2 bits) 1= The USB-ICC is present but not activated
(2 bits) 2= The USB-ICC is virtually not present
3= RFU
(4 bits) RFU
(6 bits) bmCommandStatus (2 bits) 0, 1, 2 0= Processed without error.
1= Failed, error condition given by bError.
2= Time extension is requested
3= RFU
1 bError 1 Error codes
/* error code */
ICC_MUTE 0xFE The applications of the USB-ICC did not respond
or the ATR could not be sent by the USB-ICC.
XFR_OVERRUN 0xFC The USB-ICC detected a buffer overflow when
receiving a data block.
HW_ERROR 0xFB The USB-ICC detected a hardware error.
(0xC0 to 0x81) User defined
0xE0, 0xEF, 0xF0, These values shall not be used by the USB-ICC
0xF2..0xF8, 0xFD
all others Reserved for future use
(0x80 and those filling the gaps)
extern const uchar *icc_power_on (void);
extern byte icc_get_status (void);
PC_to_RDR_IccPowerOff
RDR_to_PC_SlotStatus
PC_to_RDR_IccPowerOn
RDR_to_PC_DataBlock
PC_to_RDR_XfrBlock
RDR_to_PC_DataBlock

81
src/usb_conf.h Normal file
View File

@@ -0,0 +1,81 @@
/*
(C) COPYRIGHT 2010 STMicroelectronics
usb_conf.h
MCD Application Team
V3.1.1
04/07/2010
Virtual COM Port Demo configuration header
*/
#ifndef __USB_CONF_H
#define __USB_CONF_H
/*-------------------------------------------------------------*/
/* EP_NUM */
/* defines how many endpoints are used by the device */
/*-------------------------------------------------------------*/
#define EP_NUM (6)
/*-------------------------------------------------------------*/
/* -------------- Buffer Description Table -----------------*/
/*-------------------------------------------------------------*/
/* buffer table base address */
/* buffer table base address */
#define BTABLE_ADDRESS (0x00)
/* EP0 */
/* rx/tx buffer base address */
#define ENDP0_RXADDR (0x40)
#define ENDP0_TXADDR (0x80)
/* EP1 */
/* tx buffer base address */
#define ENDP1_TXADDR (0xC0)
/* EP2 */
#define ENDP2_TXADDR (0x100)
/* EP3 */
#define ENDP3_RXADDR (0x110)
/* EP4 */
#define ENDP4_TXADDR (0x180)
/* EP5 */
#define ENDP5_RXADDR (0x1C0)
/*-------------------------------------------------------------*/
/* ------------------- ISTR events -------------------------*/
/*-------------------------------------------------------------*/
/* IMR_MSK */
/* mask defining which events has to be handled */
/* by the device application software */
#define IMR_MSK (CNTR_CTRM | CNTR_SOFM | CNTR_RESETM )
/*#define CTR_CALLBACK*/
/*#define DOVR_CALLBACK*/
/*#define ERR_CALLBACK*/
/*#define WKUP_CALLBACK*/
/*#define SUSP_CALLBACK*/
/*#define RESET_CALLBACK*/
/*#define SOF_CALLBACK*/
/*#define ESOF_CALLBACK*/
#if 0
#define EP1_IN_Callback NOP_Process
#define EP2_IN_Callback NOP_Process
#define EP3_IN_Callback NOP_Process
#define EP4_IN_Callback NOP_Process
#define EP5_IN_Callback NOP_Process
#define EP6_IN_Callback NOP_Process
#define EP7_IN_Callback NOP_Process
#define EP1_OUT_Callback NOP_Process
#define EP2_OUT_Callback NOP_Process
#define EP3_OUT_Callback NOP_Process
#define EP4_OUT_Callback NOP_Process
#define EP5_OUT_Callback NOP_Process
#define EP6_OUT_Callback NOP_Process
#define EP7_OUT_Callback NOP_Process
#endif
#endif /* __USB_CONF_H */

206
src/usb_desc.c Normal file
View File

@@ -0,0 +1,206 @@
/*
*
*/
#include "usb_lib.h"
#include "usb_desc.h"
#define USB_ICC_INTERFACE_CLASS 0x0B
#define USB_ICC_INTERFACE_SUBCLASS 0x00
#define USB_ICC_INTERFACE_BULK_PROTOCOL 0x00
#define USB_ICC_DATA_SIZE 64
/* USB Standard Device Descriptor */
static const uint8_t gnukDeviceDescriptor[] = {
18, /* bLength */
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
0x00, 0x02, /* bcdUSB = 2.00 */
0x00, /* bDeviceClass: 0 means deferred to interface */
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
0x40, /* bMaxPacketSize0 */
0xff, 0xff, /* idVendor = 0xffff */
0x01, 0x00, /* idProduct = 0x0001 */
0x00, 0x02, /* bcdDevice = 2.00 */
1, /* Index of string descriptor describing manufacturer */
2, /* Index of string descriptor describing product */
3, /* Index of string descriptor describing the device's serial number */
0x01 /* bNumConfigurations */
};
/* Configuation Descriptor */
static const uint8_t gnukConfigDescriptor[] = {
9, /* bLength: Configuation Descriptor size */
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
9+9+54+7+7+9+5+5+4+5+7+9+7+7, 0x00, /* wTotalLength:no of returned bytes */
0x03, /* bNumInterfaces: 3 interfaces (two for CDC, one for GPG) */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
0xC0, /* bmAttributes: self powered */
0x32, /* MaxPower 0 mA */
/* Interface Descriptor */
9, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
0, /* Index of this interface */
0, /* Alternate setting for this interface */
2, /* bNumEndpoints: Bulk-IN, Bulk-OUT */
USB_ICC_INTERFACE_CLASS,
USB_ICC_INTERFACE_SUBCLASS,
USB_ICC_INTERFACE_BULK_PROTOCOL,
0, /* string index for interface */
/* ICC Descriptor */
54, /* bLength: */
0x21, /* bDescriptorType: USBDESCR_ICC */
0x10, 0x01, /* bcdCCID: 1.1 */
0, /* bMaxSlotIndex: */
1, /* bVoltageSupport: FIXED VALUE */
0x02, 0, 0, 0, /* dwProtocols: T=1 */
0xfc, 0x0d, 0, 0, /* dwDefaultClock: FIXED VALUE */
0xfc, 0x0d, 0, 0, /* dwMaximumClock: FIXED VALUE*/
1, /* bNumClockSupported: FIXED VALUE*/
0x80, 0x25, 0, 0, /* dwDataRate: FIXED VALUE */
0x80, 0x25, 0, 0, /* dwMaxDataRate: FIXED VALUE */
1, /* bNumDataRateSupported: FIXED VALUE */
0xfe, 0, 0, 0, /* dwMaxIFSD: */
0, 0, 0, 0, /* dwSynchProtocols: FIXED VALUE */
0, 0, 0, 0, /* dwMechanical: FIXED VALUE */
0x40, 0x08, 0x04, 0x00, /* dwFeatures: Short and extended ADPU level */
0x0f, 0x01, 0, 0, /* dwMaxCCIDMessageLength: 261+10 */
0xff, /* bClassGetResponse: */
0xff, /* bClassEnvelope: */
0, 0, /* wLCDLayout: FIXED VALUE */
0, /* bPinSupport: No PIN pad */
1, /* bMaxCCIDBusySlots: 1 */
/*Endpoint 4 Descriptor*/
7, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
0x84, /* bEndpointAddress: (IN4) */
0x02, /* bmAttributes: Bulk */
USB_ICC_DATA_SIZE, 0x00, /* wMaxPacketSize: */
0x00, /* bInterval */
/*Endpoint 5 Descriptor*/
7, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
0x05, /* bEndpointAddress: (OUT5) */
0x02, /* bmAttributes: Bulk */
USB_ICC_DATA_SIZE, 0x00, /* wMaxPacketSize: */
0x00, /* bInterval */
/* Interface Descriptor */
9, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
0x01, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints: One endpoints used */
0x02, /* bInterfaceClass: Communication Interface Class */
0x02, /* bInterfaceSubClass: Abstract Control Model */
0x01, /* bInterfaceProtocol: Common AT commands */
0x00, /* iInterface: */
/*Header Functional Descriptor*/
5, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
/*Call Managment Functional Descriptor*/
5, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x00, /* bmCapabilities: D0+D1 */
0x01, /* bDataInterface: 1 */
/*ACM Functional Descriptor*/
4, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
0x02, /* bmCapabilities */
/*Union Functional Descriptor*/
5, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x06, /* bDescriptorSubtype: Union func desc */
0x00, /* bMasterInterface: Communication class interface */
0x01, /* bSlaveInterface0: Data Class Interface */
/*Endpoint 2 Descriptor*/
7, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
0x82, /* bEndpointAddress: (IN2) */
0x03, /* bmAttributes: Interrupt */
VIRTUAL_COM_PORT_INT_SIZE, 0x00, /* wMaxPacketSize: */
0xFF, /* bInterval: */
/*Data class interface descriptor*/
9, /* bLength: Endpoint Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
0x02, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: Two endpoints used */
0x0A, /* bInterfaceClass: CDC */
0x00, /* bInterfaceSubClass: */
0x00, /* bInterfaceProtocol: */
0x00, /* iInterface: */
/*Endpoint 3 Descriptor*/
7, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
0x03, /* bEndpointAddress: (OUT3) */
0x02, /* bmAttributes: Bulk */
VIRTUAL_COM_PORT_DATA_SIZE, 0x00, /* wMaxPacketSize: */
0x00, /* bInterval: ignore for Bulk transfer */
/*Endpoint 1 Descriptor*/
7, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
0x81, /* bEndpointAddress: (IN1) */
0x02, /* bmAttributes: Bulk */
VIRTUAL_COM_PORT_DATA_SIZE, 0x00, /* wMaxPacketSize: */
0x00 /* bInterval */
};
/* USB String Descriptors */
static const uint8_t gnukStringLangID[] = {
4, /* bLength */
USB_STRING_DESCRIPTOR_TYPE,
0x09, 0x04 /* LangID = 0x0409: US-English */
};
static const uint8_t gnukStringVendor[] = {
33*2+2, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType*/
/* Manufacturer: "Free Software Initiative of Japan" */
'F', 0, 'r', 0, 'e', 0, 'e', 0, ' ', 0, 'S', 0, 'o', 0, 'f', 0,
't', 0, 'w', 0, 'a', 0, 'r', 0, 'e', 0, ' ', 0, 'I', 0, 'n', 0,
'i', 0, 't', 0, 'i', 0, 'a', 0, 't', 0, 'i', 0, 'v', 0, 'e', 0,
' ', 0, 'o', 0, 'f', 0, ' ', 0, 'J', 0, 'a', 0, 'p', 0, 'a', 0,
'n', 0
};
static const uint8_t gnukStringProduct[VIRTUAL_COM_PORT_SIZ_STRING_PRODUCT] = {
14*2+2, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
/* Product name: "FSIJ USB Token" */
'F', 0, 'S', 0, 'I', 0, 'J', 0, ' ', 0, 'U', 0, 'S', 0, 'B', 0,
' ', 0, 'T', 0, 'o', 0, 'k', 0, 'e', 0, 'n', 0
};
static uint8_t gnukStringSerial[] = {
8, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
'2', 0, '.', 0, '0', 0
};
ONE_DESCRIPTOR Device_Descriptor = {
(uint8_t*)gnukDeviceDescriptor,
sizeof (gnukDeviceDescriptor)
};
ONE_DESCRIPTOR Config_Descriptor = {
(uint8_t*)gnukConfigDescriptor,
sizeof (gnukConfigDescriptor)
};
ONE_DESCRIPTOR String_Descriptor[4] = {
{(uint8_t*)gnukStringLangID, sizeof (gnukStringLangID)},
{(uint8_t*)gnukStringVendor, sizeof (gnukStringVendor)},
{(uint8_t*)gnukStringProduct, sizeof (gnukStringProduct)},
{(uint8_t*)gnukStringSerial, sizeof (gnukStringSerial)},
};

26
src/usb_lld.c Normal file
View File

@@ -0,0 +1,26 @@
#include "ch.h"
#include "hal.h"
#include "usb_lld.h"
extern void USB_Istr (void);
CH_IRQ_HANDLER (Vector90) {
CH_IRQ_PROLOGUE();
USB_Istr();
CH_IRQ_EPILOGUE();
}
void usb_lld_init (void) {
RCC->APB1ENR |= RCC_APB1ENR_USBEN;
NVICEnableVector (USB_LP_CAN1_RX0_IRQn,
CORTEX_PRIORITY_MASK (STM32_USB_IRQ_PRIORITY));
/*
* Note that we also have other IRQs:
* USB_HP_CAN1_TX_IRQn
* USBWakeUp_IRQn
*/
RCC->APB1RSTR = RCC_APB1RSTR_USBRST;
RCC->APB1RSTR = 0;
}

8
src/usb_lld.h Normal file
View File

@@ -0,0 +1,8 @@
/**
* @brief USB interrupt priority level setting.
*/
#if !defined(STM32_USB_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_USB_IRQ_PRIORITY 11
#endif
void usb_lld_init (void);

299
src/usb_prop.c Normal file
View File

@@ -0,0 +1,299 @@
/*
usb_prop.c
MCD Application Team
V3.1.1
04/07/2010
All processing related to Virtual Com Port Demo
*/
#include "usb_lib.h"
#include "usb_conf.h"
#include "usb_prop.h"
#include "usb_desc.h"
#include "usb_pwr.h"
#include "hw_config.h"
#if 0
static uint8_t Request = 0;
#endif
typedef struct
{
uint32_t bitrate;
uint8_t format;
uint8_t paritytype;
uint8_t datatype;
} LINE_CODING;
static LINE_CODING linecoding = {
115200, /* baud rate*/
0x00, /* stop bits-1*/
0x00, /* parity - none*/
0x08 /* no. of bits 8*/
};
static uint8_t *Virtual_Com_Port_GetLineCoding(uint16_t Length)
{
if (Length == 0)
{
pInformation->Ctrl_Info.Usb_wLength = sizeof(linecoding);
return NULL;
}
return (uint8_t *)&linecoding;
}
static uint8_t *Virtual_Com_Port_SetLineCoding(uint16_t Length)
{
if (Length == 0)
{
pInformation->Ctrl_Info.Usb_wLength = sizeof(linecoding);
return NULL;
}
return (uint8_t *)&linecoding;
}
#define GNUK_MAX_PACKET_SIZE 64
static void
gnuk_device_init (void)
{
/* Update the serial number string descriptor with the data from the unique
ID*/
Get_SerialNum ();
pInformation->Current_Configuration = 0;
/* Connect the device */
PowerOn ();
/* Perform basic device initialization operations */
USB_SIL_Init ();
bDeviceState = UNCONNECTED;
}
static void
gnuk_device_reset (void)
{
/* Set Virtual_Com_Port DEVICE as not configured */
pInformation->Current_Configuration = 0;
/* Current Feature initialization */
pInformation->Current_Feature = Config_Descriptor.Descriptor[7];
/* Set Virtual_Com_Port DEVICE with the default Interface*/
pInformation->Current_Interface = 0;
SetBTABLE (BTABLE_ADDRESS);
/* Initialize Endpoint 0 */
SetEPType (ENDP0, EP_CONTROL);
SetEPTxStatus (ENDP0, EP_TX_STALL);
SetEPRxAddr (ENDP0, ENDP0_RXADDR);
SetEPTxAddr (ENDP0, ENDP0_TXADDR);
Clear_Status_Out (ENDP0);
SetEPRxCount (ENDP0, GNUK_MAX_PACKET_SIZE);
SetEPRxValid (ENDP0);
/* Initialize Endpoint 1 */
SetEPType (ENDP1, EP_BULK);
SetEPTxAddr (ENDP1, ENDP1_TXADDR);
SetEPTxStatus (ENDP1, EP_TX_NAK);
SetEPRxStatus (ENDP1, EP_RX_DIS);
/* Initialize Endpoint 2 */
SetEPType (ENDP2, EP_INTERRUPT);
SetEPTxAddr (ENDP2, ENDP2_TXADDR);
SetEPRxStatus (ENDP2, EP_RX_DIS);
SetEPTxStatus (ENDP2, EP_TX_NAK);
/* Initialize Endpoint 3 */
SetEPType (ENDP3, EP_BULK);
SetEPRxAddr (ENDP3, ENDP3_RXADDR);
SetEPRxCount (ENDP3, VIRTUAL_COM_PORT_DATA_SIZE);
SetEPRxStatus (ENDP3, EP_RX_VALID);
SetEPTxStatus (ENDP3, EP_TX_DIS);
/* Initialize Endpoint 4 */
SetEPType (ENDP4, EP_BULK);
SetEPTxAddr (ENDP4, ENDP4_TXADDR);
SetEPTxStatus (ENDP4, EP_TX_NAK);
SetEPRxStatus (ENDP4, EP_RX_DIS);
/* Initialize Endpoint 5 */
SetEPType (ENDP5, EP_BULK);
SetEPRxAddr (ENDP5, ENDP5_RXADDR);
SetEPRxCount (ENDP5, VIRTUAL_COM_PORT_DATA_SIZE); /* XXX */
SetEPRxStatus (ENDP5, EP_RX_VALID);
SetEPTxStatus (ENDP5, EP_TX_DIS);
/* Set this device to response on default address */
SetDeviceAddress (0);
bDeviceState = ATTACHED;
}
static void
gnuk_device_SetConfiguration (void)
{
DEVICE_INFO *pInfo = &Device_Info;
if (pInfo->Current_Configuration != 0)
/* Device configured */
bDeviceState = CONFIGURED;
}
static void
gnuk_device_SetDeviceAddress (void)
{
bDeviceState = ADDRESSED;
}
/* IN from port 0 */
static void
gnuk_device_Status_In (void)
{
#if 0
if (Request == SET_LINE_CODING)
Request = 0;
#endif
}
/* OUT to port 0 */
static void
gnuk_device_Status_Out (void)
{
}
/*******************************************************************************
* Function Name : Virtual_Com_Port_Data_Setup
* Description : handle the data class specific requests
* Input : Request Nb.
* Output : None.
* Return : USB_UNSUPPORT or USB_SUCCESS.
*******************************************************************************/
static RESULT
Virtual_Com_Port_Data_Setup (uint8_t RequestNo)
{
uint8_t *(*CopyRoutine)(uint16_t);
CopyRoutine = NULL;
if (RequestNo == GET_LINE_CODING)
{
if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
CopyRoutine = Virtual_Com_Port_GetLineCoding;
}
else if (RequestNo == SET_LINE_CODING)
{
if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
CopyRoutine = Virtual_Com_Port_SetLineCoding;
#if 0
Request = SET_LINE_CODING;
#endif
}
if (CopyRoutine == NULL)
return USB_UNSUPPORT;
pInformation->Ctrl_Info.CopyData = CopyRoutine;
pInformation->Ctrl_Info.Usb_wOffset = 0;
(*CopyRoutine) (0);
return USB_SUCCESS;
}
/*******************************************************************************
* Function Name : Virtual_Com_Port_NoData_Setup.
* Description : handle the no data class specific requests.
* Input : Request Nb.
* Output : None.
* Return : USB_UNSUPPORT or USB_SUCCESS.
*******************************************************************************/
static RESULT
Virtual_Com_Port_NoData_Setup (uint8_t RequestNo)
{
if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
{
if (RequestNo == SET_COMM_FEATURE)
return USB_SUCCESS;
else if (RequestNo == SET_CONTROL_LINE_STATE)
return USB_SUCCESS;
}
return USB_UNSUPPORT;
}
static uint8_t *
gnuk_device_GetDeviceDescriptor (uint16_t Length)
{
return Standard_GetDescriptorData (Length, &Device_Descriptor);
}
static uint8_t *
gnuk_device_GetConfigDescriptor (uint16_t Length)
{
return Standard_GetDescriptorData (Length, &Config_Descriptor);
}
static uint8_t *
gnuk_device_GetStringDescriptor (uint16_t Length)
{
uint8_t wValue0 = pInformation->USBwValue0;
if (wValue0 > (sizeof (String_Descriptor) / sizeof (ONE_DESCRIPTOR)))
return NULL;
else
return Standard_GetDescriptorData (Length, &String_Descriptor[wValue0]);
}
static RESULT
gnuk_device_Get_Interface_Setting (uint8_t Interface, uint8_t AlternateSetting)
{
if (AlternateSetting > 0)
return USB_UNSUPPORT;
else if (Interface > 1)
return USB_UNSUPPORT;
return USB_SUCCESS;
}
/*
* Interface to USB core
*/
DEVICE_PROP Device_Property = {
gnuk_device_init,
gnuk_device_reset,
gnuk_device_Status_In,
gnuk_device_Status_Out,
Virtual_Com_Port_Data_Setup,
Virtual_Com_Port_NoData_Setup,
gnuk_device_Get_Interface_Setting,
gnuk_device_GetDeviceDescriptor,
gnuk_device_GetConfigDescriptor,
gnuk_device_GetStringDescriptor,
0,
GNUK_MAX_PACKET_SIZE
};
DEVICE Device_Table = {
EP_NUM,
1
};
USER_STANDARD_REQUESTS User_Standard_Requests = {
NOP_Process, /* GetConfiguration */
gnuk_device_SetConfiguration,
NOP_Process, /* GetInterface */
NOP_Process, /* SetInterface */
NOP_Process, /* GetStatus */
NOP_Process, /* ClearFeature */
NOP_Process, /* SetEndPointFeature */
NOP_Process, /* SetDeviceFeature */
gnuk_device_SetDeviceAddress
};

26
src/usb_prop.h Normal file
View File

@@ -0,0 +1,26 @@
/*
(C) COPYRIGHT 2010 STMicroelectronics
usb_prop.h
MCD Application Team
V3.1.1
04/07/2010
All processing related to Virtual COM Port Demo (Endpoint 0)
*/
#ifndef __usb_prop_H
#define __usb_prop_H
#define SEND_ENCAPSULATED_COMMAND 0x00
#define GET_ENCAPSULATED_RESPONSE 0x01
#define SET_COMM_FEATURE 0x02
#define GET_COMM_FEATURE 0x03
#define CLEAR_COMM_FEATURE 0x04
#define SET_LINE_CODING 0x20
#define GET_LINE_CODING 0x21
#define SET_CONTROL_LINE_STATE 0x22
#define SEND_BREAK 0x23
extern ONE_DESCRIPTOR Device_Descriptor;
extern ONE_DESCRIPTOR Config_Descriptor;
extern ONE_DESCRIPTOR String_Descriptor[4];
#endif /* __usb_prop_H */

View File

@@ -1,4 +1,3 @@
USBCDCDIR = ../USBCDC
USBCDCSRC= $(USBCDCDIR)/usb_desc.c \
$(USBCDCDIR)/usb_endp.c $(USBCDCDIR)/usb_istr.c \
$(USBCDCDIR)/usb_prop.c $(USBCDCDIR)/usb_pwr.c
USBCDCSRC= $(USBCDCDIR)/usb_endp.c $(USBCDCDIR)/usb_istr.c \
$(USBCDCDIR)/usb_pwr.c