| 1 |
/* |
| 2 |
felicalib - FeliCa access wrapper library |
| 3 |
|
| 4 |
Copyright (c) 2007, Takuya Murakami, All rights reserved. |
| 5 |
|
| 6 |
Redistribution and use in source and binary forms, with or without |
| 7 |
modification, are permitted provided that the following conditions are |
| 8 |
met: |
| 9 |
|
| 10 |
1. Redistributions of source code must retain the above copyright notice, |
| 11 |
this list of conditions and the following disclaimer. |
| 12 |
|
| 13 |
2. Redistributions in binary form must reproduce the above copyright |
| 14 |
notice, this list of conditions and the following disclaimer in the |
| 15 |
documentation and/or other materials provided with the distribution. |
| 16 |
|
| 17 |
3. Neither the name of the project nor the names of its contributors |
| 18 |
may be used to endorse or promote products derived from this software |
| 19 |
without specific prior written permission. |
| 20 |
|
| 21 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 22 |
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 23 |
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 24 |
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| 25 |
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 26 |
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 27 |
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 28 |
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| 29 |
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| 30 |
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 31 |
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 32 |
*/ |
| 33 |
/** |
| 34 |
@file felicalib.c |
| 35 |
|
| 36 |
felicalib �{�� |
| 37 |
*/ |
| 38 |
|
| 39 |
#include "felicalib.h" |
| 40 |
#include "felicaint.h" |
| 41 |
|
| 42 |
#include <tchar.h> |
| 43 |
#include <shlobj.h> |
| 44 |
#include <stdio.h> |
| 45 |
|
| 46 |
/** |
| 47 |
@brief PaSoRi ���I�[�v������ |
| 48 |
@param[in] dummy �_�~�[ (libpasori ����������������) |
| 49 |
@retval pasori �n���h�� |
| 50 |
|
| 51 |
felica.dll �����[�h�A���������� |
| 52 |
*/ |
| 53 |
pasori *pasori_open(char *dummy) |
| 54 |
{ |
| 55 |
TCHAR cp[_MAX_PATH], dllpath[_MAX_PATH]; |
| 56 |
|
| 57 |
/* get felica.dll path */ |
| 58 |
SHGetSpecialFolderPath(NULL, cp, CSIDL_PROGRAM_FILES_COMMON, FALSE); |
| 59 |
_stprintf(dllpath, _T("%s\\Sony Shared\\FeliCaLibrary\\felica.dll"), cp); |
| 60 |
|
| 61 |
return pasori_open2(dllpath); |
| 62 |
} |
| 63 |
|
| 64 |
pasori *pasori_open2(TCHAR *dllpath) |
| 65 |
{ |
| 66 |
pasori *p; |
| 67 |
|
| 68 |
/* open felica.dll */ |
| 69 |
p = (pasori *)malloc(sizeof(pasori)); |
| 70 |
p->hInstDLL = LoadLibrary(dllpath); |
| 71 |
if (p->hInstDLL == NULL) { |
| 72 |
free(p); |
| 73 |
return NULL; |
| 74 |
} |
| 75 |
|
| 76 |
/* resolve function pointers */ |
| 77 |
#define resolve_entry(f) p->f = (f ## _t)GetProcAddress(p->hInstDLL, #f) |
| 78 |
resolve_entry(initialize_library); |
| 79 |
resolve_entry(dispose_library); |
| 80 |
resolve_entry(open_reader_writer_auto); |
| 81 |
resolve_entry(close_reader_writer); |
| 82 |
resolve_entry(polling_and_get_card_information); |
| 83 |
resolve_entry(polling_and_request_system_code); |
| 84 |
resolve_entry(polling_and_search_service_code); |
| 85 |
resolve_entry(read_block_without_encryption); |
| 86 |
resolve_entry(write_block_without_encryption); |
| 87 |
|
| 88 |
if (!p->initialize_library()) { |
| 89 |
free(p); |
| 90 |
return NULL; |
| 91 |
} |
| 92 |
return p; |
| 93 |
} |
| 94 |
|
| 95 |
/** |
| 96 |
@brief PaSoRi �n���h�����N���[�Y���� |
| 97 |
@param[in] p pasori�n���h�� |
| 98 |
|
| 99 |
felica.dll ���������� |
| 100 |
*/ |
| 101 |
void pasori_close(pasori *p) |
| 102 |
{ |
| 103 |
p->dispose_library(); |
| 104 |
FreeLibrary(p->hInstDLL); |
| 105 |
} |
| 106 |
|
| 107 |
/** |
| 108 |
@brief PaSoRi ������������ |
| 109 |
@param[in] p pasori�n���h�� |
| 110 |
@return �G���[�R�[�h |
| 111 |
*/ |
| 112 |
int pasori_init(pasori *p) |
| 113 |
{ |
| 114 |
if (!p->open_reader_writer_auto()) { |
| 115 |
return -1; |
| 116 |
} |
| 117 |
return 0; |
| 118 |
} |
| 119 |
|
| 120 |
static felica *alloc_felica(pasori *p, uint16 systemcode) |
| 121 |
{ |
| 122 |
felica *f = (felica *)malloc(sizeof(felica)); |
| 123 |
memset(f, 0, sizeof(felica)); |
| 124 |
f->p = p; |
| 125 |
f->systemcode = H2NS(systemcode); |
| 126 |
|
| 127 |
return f; |
| 128 |
} |
| 129 |
|
| 130 |
/** |
| 131 |
@brief FeliCa ���|�[�����O���� |
| 132 |
@param[in] p pasori�n���h�� |
| 133 |
@param[in] systemcode �V�X�e���R�[�h |
| 134 |
@param[in] RFU RFU (�g�p������) |
| 135 |
@param[in] timeslot �^�C���X���b�g |
| 136 |
@return felica�n���h�� |
| 137 |
*/ |
| 138 |
felica *felica_polling(pasori *p, uint16 systemcode, uint8 RFU, uint8 timeslot) |
| 139 |
{ |
| 140 |
felica *f; |
| 141 |
POLLING polling; |
| 142 |
uint16 sc; |
| 143 |
uint8 number_of_cards = 0; |
| 144 |
CARD_INFO card_info; |
| 145 |
|
| 146 |
f = alloc_felica(p, systemcode); |
| 147 |
|
| 148 |
sc = H2NS(systemcode); |
| 149 |
polling.system_code = (uint8 *)≻ |
| 150 |
polling.time_slot = timeslot; |
| 151 |
|
| 152 |
card_info.card_idm = f->IDm; |
| 153 |
card_info.card_pmm = f->PMm; |
| 154 |
|
| 155 |
if (!p->polling_and_get_card_information(&polling, &number_of_cards, &card_info) || |
| 156 |
number_of_cards == 0) { |
| 157 |
free(f); |
| 158 |
return NULL; |
| 159 |
} |
| 160 |
|
| 161 |
return f; |
| 162 |
} |
| 163 |
|
| 164 |
/** |
| 165 |
@brief �������������������u���b�N���������� |
| 166 |
@param[in] f felica�n���h�� |
| 167 |
@param[in] servicecode �T�[�r�X�R�[�h |
| 168 |
@param[in] mode ���[�h(�g�p������) |
| 169 |
@param[in] addr �u���b�N���� |
| 170 |
@param[out] data �f�[�^(16�o�C�g) |
| 171 |
@return �G���[�R�[�h |
| 172 |
|
| 173 |
�T�[�r�X�R�[�h�A�u���b�N�������w�������u���b�N�����������B |
| 174 |
�V�X�e���R�[�h�� felica_polling ���w�������������g�p�������B |
| 175 |
*/ |
| 176 |
int felica_read_without_encryption02(felica *f, int servicecode, int mode, uint8 addr, uint8 *data) |
| 177 |
{ |
| 178 |
INSTR_READ_BLOCK irb; |
| 179 |
OUTSTR_READ_BLOCK orb; |
| 180 |
|
| 181 |
uint8 service_code_list[2]; |
| 182 |
uint8 block_list[2]; |
| 183 |
uint8 status_flag1, status_flag2; |
| 184 |
uint8 result_number_of_blocks = 0; |
| 185 |
|
| 186 |
service_code_list[0] = servicecode & 0xff; |
| 187 |
service_code_list[1] = servicecode >> 8; |
| 188 |
block_list[0] = 0x80; |
| 189 |
block_list[1] = addr; |
| 190 |
|
| 191 |
irb.card_idm = f->IDm; |
| 192 |
irb.number_of_services = 1; |
| 193 |
irb.service_code_list = service_code_list; |
| 194 |
irb.number_of_blocks = 1; |
| 195 |
irb.block_list = block_list; |
| 196 |
|
| 197 |
orb.status_flag_1 = &status_flag1; |
| 198 |
orb.status_flag_2 = &status_flag2; |
| 199 |
orb.result_number_of_blocks = &result_number_of_blocks; |
| 200 |
orb.block_data = data; |
| 201 |
|
| 202 |
if (!f->p->read_block_without_encryption(&irb, &orb)) { |
| 203 |
return -1; |
| 204 |
} |
| 205 |
if (status_flag1 != 0) { |
| 206 |
return -1; |
| 207 |
} |
| 208 |
return 0; |
| 209 |
} |
| 210 |
|
| 211 |
/*------------- ���������� libpasori ���������� (����) ------------*/ |
| 212 |
|
| 213 |
/** |
| 214 |
@brief �������������������u���b�N���������� |
| 215 |
@param[in] f felica�n���h�� |
| 216 |
@param[in] servicecode �T�[�r�X�R�[�h |
| 217 |
@param[in] mode ���[�h(�g�p������) |
| 218 |
@param[in] addr �u���b�N���� |
| 219 |
@param[out] data �f�[�^(16�o�C�g) |
| 220 |
@return �G���[�R�[�h |
| 221 |
|
| 222 |
�T�[�r�X�R�[�h�A�u���b�N�������w�������u���b�N�����������B |
| 223 |
�V�X�e���R�[�h�� felica_polling ���w�������������g�p�������B |
| 224 |
����!!! �{���������e�X�g!!!!! |
| 225 |
*/ |
| 226 |
int felica_write_without_encryption(felica *f, int servicecode, uint8 addr, uint8 *data) |
| 227 |
{ |
| 228 |
INSTR_WRITE_BLOCK irb; |
| 229 |
OUTSTR_WRITE_BLOCK orb; |
| 230 |
|
| 231 |
uint8 service_code_list[2]; |
| 232 |
uint8 block_list[2]; |
| 233 |
uint8 status_flag1, status_flag2; |
| 234 |
|
| 235 |
service_code_list[0] = servicecode & 0xff; |
| 236 |
service_code_list[1] = servicecode >> 8; |
| 237 |
block_list[0] = 0x80; |
| 238 |
block_list[1] = addr; |
| 239 |
|
| 240 |
irb.card_idm = f->IDm; |
| 241 |
irb.number_of_services = 1; |
| 242 |
irb.service_code_list = service_code_list; |
| 243 |
irb.number_of_blocks = 1; |
| 244 |
irb.block_list = block_list; |
| 245 |
irb.block_data = data; |
| 246 |
|
| 247 |
orb.status_flag_1 = &status_flag1; |
| 248 |
orb.status_flag_2 = &status_flag2; |
| 249 |
|
| 250 |
if (!f->p->write_block_without_encryption(&irb, &orb)) { |
| 251 |
return -1; |
| 252 |
} |
| 253 |
if (status_flag1 != 0) { |
| 254 |
return -1; |
| 255 |
} |
| 256 |
return 0; |
| 257 |
} |
| 258 |
|
| 259 |
/** |
| 260 |
@brief felica �n���h������ |
| 261 |
@param[in] f felica �n���h�� |
| 262 |
*/ |
| 263 |
void felica_free(felica *f) |
| 264 |
{ |
| 265 |
free(f); |
| 266 |
} |
| 267 |
|
| 268 |
/** |
| 269 |
@brief IDm ���� |
| 270 |
@param[in] f felica �n���h�� |
| 271 |
@param[out] buf IDm ���i�[�����o�b�t�@(8�o�C�g) |
| 272 |
*/ |
| 273 |
void felica_getidm(felica *f, uint8 *buf) |
| 274 |
{ |
| 275 |
memcpy(buf, f->IDm, 8); |
| 276 |
} |
| 277 |
|
| 278 |
/** |
| 279 |
@brief PMm ���� |
| 280 |
@param[in] f felica �n���h�� |
| 281 |
@param[out] buf PMm ���i�[�����o�b�t�@(8�o�C�g) |
| 282 |
*/ |
| 283 |
void felica_getpmm(felica *f, uint8 *buf) |
| 284 |
{ |
| 285 |
memcpy(buf, f->PMm, 8); |
| 286 |
} |
| 287 |
|
| 288 |
/** |
| 289 |
@brief �V�X�e���R�[�h������ |
| 290 |
@param[in] p pasori�n���h�� |
| 291 |
@return felica�n���h�� |
| 292 |
|
| 293 |
�������Afelica�\������ num_system_code/system_code ���i�[�������B |
| 294 |
�����A�V�X�e���R�[�h���G���f�B�A�����t���i�[���������������������������B |
| 295 |
*/ |
| 296 |
felica * felica_enum_systemcode(pasori *p) |
| 297 |
{ |
| 298 |
felica *f; |
| 299 |
POLLING polling; |
| 300 |
CARD_INFO card_info; |
| 301 |
INSTR_REQ_SYSTEM_CODE irs; |
| 302 |
OUTSTR_REQ_SYSTEM_CODE ors; |
| 303 |
|
| 304 |
f = alloc_felica(p, POLLING_ANY); |
| 305 |
|
| 306 |
polling.system_code = (uint8 *)&f->systemcode; |
| 307 |
polling.time_slot = 0; |
| 308 |
|
| 309 |
card_info.card_idm = f->IDm; |
| 310 |
card_info.card_pmm = f->PMm; |
| 311 |
|
| 312 |
irs.card_idm = f->IDm; |
| 313 |
|
| 314 |
ors.system_code_list = (uint8 *)f->system_code; |
| 315 |
|
| 316 |
if (!f->p->polling_and_request_system_code(&polling, &irs, &card_info, &ors)) { |
| 317 |
free(f); |
| 318 |
return NULL; |
| 319 |
} |
| 320 |
|
| 321 |
f->num_system_code = ors.number_of_system_codes; |
| 322 |
return f; |
| 323 |
} |
| 324 |
|
| 325 |
/** |
| 326 |
@brief �T�[�r�X/�G���A�R�[�h������ |
| 327 |
@param[in] p pasori�n���h�� |
| 328 |
@param[in] systemcode �V�X�e���R�[�h |
| 329 |
@return felica�n���h�� |
| 330 |
|
| 331 |
�������Afelica�\������ num_area_code/area_code/end_service_code ������ |
| 332 |
num_service_code/service_code ���i�[�������B |
| 333 |
*/ |
| 334 |
felica * felica_enum_service(pasori *p, uint16 systemcode) |
| 335 |
{ |
| 336 |
felica *f; |
| 337 |
|
| 338 |
POLLING polling; |
| 339 |
CARD_INFO card_info; |
| 340 |
INSTR_SEARCH_SERVICE iss; |
| 341 |
OUTSTR_SEARCH_SERVICE oss; |
| 342 |
|
| 343 |
f = alloc_felica(p, systemcode); |
| 344 |
|
| 345 |
polling.system_code = (uint8 *)&f->systemcode; |
| 346 |
polling.time_slot = 0; |
| 347 |
|
| 348 |
card_info.card_idm = f->IDm; |
| 349 |
card_info.card_pmm = f->PMm; |
| 350 |
|
| 351 |
iss.buffer_size_of_area_codes = MAX_AREA_CODE; |
| 352 |
iss.buffer_size_of_service_codes = MAX_SERVICE_CODE; |
| 353 |
iss.offset_of_area_service_index = 0; |
| 354 |
|
| 355 |
oss.num_area_codes = 10; |
| 356 |
oss.num_service_codes = 10; |
| 357 |
oss.service_code_list = (uint8 *)f->service_code; |
| 358 |
oss.area_code_list = (uint8 *)f->area_code; |
| 359 |
oss.end_service_code_list = (uint8 *)f->end_service_code; |
| 360 |
|
| 361 |
if (!f->p->polling_and_search_service_code(&polling, &iss, &card_info, &oss)) { |
| 362 |
free(f); |
| 363 |
return NULL; |
| 364 |
} |
| 365 |
|
| 366 |
f->num_area_code = oss.num_area_codes; |
| 367 |
f->num_service_code = oss.num_service_codes; |
| 368 |
|
| 369 |
return f; |
| 370 |
} |