123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199 |
- /*
- * 1-Wire implementation for the ds23el15 chip
- *
- * Copyright (C) 2013 maximintergrated
- *
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/device.h>
- #include <linux/types.h>
- #include <linux/platform_device.h>
- #include <linux/mutex.h>
- #include <linux/of.h>
- #include <linux/idr.h>
- #include <linux/delay.h>
- #include <linux/random.h>
- #include <linux/err.h>
- #include <linux/of.h>
- #include <linux/input.h>
- #include "../w1.h"
- #include "../w1_int.h"
- #include "../w1_family.h"
- #include "w1_ds28el15_sha256.h"
- // 1-Wire commands
- #define CMD_WRITE_MEMORY 0x55
- #define CMD_READ_MEMORY 0xF0
- #define CMD_LOAD_LOCK_SECRET 0x33
- #define CMD_COMPUTE_LOCK_SECRET 0x3C
- #define CMD_SELECT_SECRET 0x0F
- #define CMD_COMPUTE_PAGEMAC 0xA5
- #define CMD_READ_STATUS 0xAA
- #define CMD_WRITE_BLOCK_PROTECT 0xC3
- #define CMD_WRITE_AUTH_MEMORY 0x5A
- #define CMD_WRITE_AUTH_PROTECT 0xCC
- #define CMD_PIO_READ 0xDD
- #define CMD_PIO_WRITE 0x96
- #define CMD_RELEASE 0xAA
- #define BLOCK_READ_PROTECT 0x80
- #define BLOCK_WRITE_PROTECT 0x40
- #define BLOCK_EPROM_PROTECT 0x20
- #define BLOCK_WRITE_AUTH_PROTECT 0x10
- #define ROM_CMD_SKIP 0x3C
- #define ROM_CMD_RESUME 0xA5
- #define SELECT_SKIP 0
- #define SELECT_RESUME 1
- #define SELECT_MATCH 2
- #define SELECT_ODMATCH 3
- #define SELECT_SEARCH 4
- #define SELECT_READROM 5
- #define SELECT_ODSKIP 6
- #define PROT_BIT_AUTHWRITE 0x10
- #define PROT_BIT_EPROM 0x20
- #define PROT_BIT_WRITE 0x40
- #define PROT_BIT_READ 0x80
- #define DS28E15_FAMILY 0x17
- #define DS28E15_PAGES 2 // 2 pages, 4 blocks, 7 segment in each page. total 64 bytes
- #define PAGE_TO_BYTE 32 // 1 page = 32 bytes
- #define BLOCK_TO_BYTE 16 // 1 block = 16 bytes
- #define SEGMENT_TO_BYTE 4 // 1 segment = 4 bytes
- //#define LOW_VOLTAGE
- #ifdef LOW_VOLTAGE
- #define SHA_COMPUTATION_DELAY 4
- #define EEPROM_WRITE_DELAY 15
- #define SECRET_EEPROM_DELAY 200
- #else
- #define SHA_COMPUTATION_DELAY 3
- #define EEPROM_WRITE_DELAY 10
- #define SECRET_EEPROM_DELAY 90
- #endif
- #define ID_MIN 0
- #define ID_MAX 3
- #define CO_MIN 0
- #ifdef CONFIG_SEC_MEGA2LTE_COMMON
- #define CO_MAX 15
- #else
- #define CO_MAX 10
- #endif
- #define ID_DEFAULT 1
- #define CO_DEFAULT 1
- #define RETRY_LIMIT 10
- #ifdef CONFIG_W1_CF
- #define RETRY_LIMIT_CF 5
- #endif
- // misc state
- static unsigned short slave_crc16;
- static int special_mode = 0;
- static char special_values[2];
- static char rom_no[8];
- int verification = -1, id = 2, color;
- #ifdef CONFIG_W1_SN
- char g_sn[14];
- #endif
- #ifdef CONFIG_W1_CF
- int cf_node = -1;
- #endif
- #ifdef CONFIG_SEC_H_PROJECT
- extern int verified;
- #endif
- #define READ_EOP_BYTE(seg) (32-seg*4)
- static char w1_array[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- static u8 skip_setup = 1; // for test if the chip did not have secret code, we would need to write temp secret value
- static u8 init_verify = 1; // for inital verifying
- //module_param_array(w1_array, char, NULL, 0);
- //-----------------------------------------------------------------------------
- // ------ DS28EL15 Functions
- //-----------------------------------------------------------------------------
- //----------------------------------------------------------------------
- // Set or clear special mode flag
- //
- // 'enable' - '1' to enable special mode or '0' to clear
- //
- void set_special_mode(int enable, uchar *values)
- {
- special_mode= enable;
- special_values[0] = values[0];
- special_values[1] = values[1];
- }
- //--------------------------------------------------------------------------
- // Calculate a new CRC16 from the input data shorteger. Return the current
- // CRC16 and also update the global variable CRC16.
- //
- static short oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
- static unsigned short docrc16(unsigned short data)
- {
- data = (data ^ (slave_crc16 & 0xff)) & 0xff;
- slave_crc16 >>= 8;
- if (oddparity[data & 0xf] ^ oddparity[data >> 4])
- slave_crc16 ^= 0xc001;
- data <<= 6;
- slave_crc16 ^= data;
- data <<= 1;
- slave_crc16 ^= data;
- return slave_crc16;
- }
- //--------------------------------------------------------------------------
- // Compute MAC to write a 4 byte memory block using an authenticated
- // write.
- //
- // Parameters
- // page - page number where the block to write is located (0 to 15)
- // segment - segment number in page (0 to 7)
- // new_data - 4 byte buffer containing the data to write
- // old_data - 4 byte buffer containing the data to write
- // manid - 2 byte buffer containing the manufacturer ID (general device: 00h,00h)
- // mac - buffer to put the calculated mac into
- //
- // Returns: TRUE - mac calculated
- // FALSE - Failed to calculate
- //
- int calculate_write_authMAC256(int page, int segment, char *new_data, char *old_data, char *manid, char *mac)
- {
- char mt[64];
- // calculate MAC
- // clear
- memset(mt,0,64);
- // insert ROM number
- memcpy(&mt[32],rom_no,8);
- mt[43] = segment;
- mt[42] = page;
- mt[41] = manid[0];
- mt[40] = manid[1];
- // insert old data
- memcpy(&mt[44],old_data,4);
- // insert new data
- memcpy(&mt[48],new_data,4);
- // compute the mac
- return compute_mac256(mt, 55, &mac[0]);
- }
- //-----------------------------------------------------------------------------
- // ------ DS28EL15 Functions - 1 wire command
- //-----------------------------------------------------------------------------
- //--------------------------------------------------------------------------
- // Write a 4 byte memory block. The block location is selected by the
- // page number and offset blcok within the page. Multiple blocks can
- // be programmed without re-selecting the device using the continue flag.
- // This function does not use the Authenticated Write operation.
- //
- // Parameters
- // page - page number where the block to write is located (0, 1)
- // segment - segment number in page (0 to 7)
- // data - 4 byte buffer containing the data to write
- // contflag - Flag to indicate the write is continued from the last (=1)
- //
- // Returns: 0 - block written
- // else - Failed to write block (no presence or invalid CRC16)
- //
- int w1_ds28el15_write_block(struct w1_slave *sl, int page, int seg, uchar *data, int contflag)
- {
- uchar buf[256],cs;
- int cnt, i, offset;
- int length =4;
- cnt = 0;
- offset = 0;
- if (!sl)
- return -ENODEV;
- if (!contflag)
- {
- if (w1_reset_select_slave(sl))
- return -1;
- buf[cnt++] = CMD_WRITE_MEMORY;
- buf[cnt++] = (seg << 5) | page; // address
- // Send command
- w1_write_block(sl->master, &buf[0], 2);
- // Read CRC
- w1_read_block(sl->master, &buf[cnt], 2);
- cnt += 2;
- offset = cnt;
- }
- // add the data
- for (i = 0; i < length; i++)
- buf[cnt++] = data[i];
- // Send data
- w1_write_block(sl->master, data, length);
- // Read CRC
- w1_read_block(sl->master, &buf[cnt], 2);
- cnt += 2;
- // check the first CRC16
- if (!contflag)
- {
- slave_crc16 = 0;
- for (i = 0; i < offset; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -1;
- }
- // check the second CRC16
- slave_crc16 = 0;
- for (i = offset; i < cnt; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -1;
- // send release and strong pull-up
- buf[0] = CMD_RELEASE;
- w1_write_block(sl->master, &buf[0], 1);
- // now wait for EEPROM writing.
- msleep(EEPROM_WRITE_DELAY);
- // disable strong pullup
- // read the CS byte
- cs = w1_read_8(sl->master);
- if (cs == 0xAA)
- return 0;
- else
- return cs;
- }
- //--------------------------------------------------------------------------
- // Write a memory segment. The segment location is selected by the
- // page number and offset segment within the page. Multiple segments can
- // be programmed without re-selecting the device.
- // This function does not use the Authenticated Write operation.
- //
- // Parameters
- // page - page number where the block to write is located (0, 1)
- // seg - segment number in page (0 to 7)
- // data - 4 byte multiple buffer containing the data to write
- // length - length to write (4 multiple number, 4, 8, ..., 32)
- //
- // Returns: 0 - block written
- // else - Failed to write block (no presence or invalid CRC16)
- //
- int w1_ds28el15_write_memory(struct w1_slave *sl, int seg, int page, uchar *data, int length)
- {
- uchar buf[256];
- uchar cs=0;
- int i;
- if (!sl)
- return -ENODEV;
- // program one or more contiguous 4 byte segments of a memory block.
- if (length%4)
- return -EINVAL;
- memcpy(buf,data,length);
- for (i=0;i<length/4;i++) {
- cs = w1_ds28el15_write_block(sl, page, i, &buf[i*4], (i==0)? 0 : 1);
- }
- return cs;
- }
- //--------------------------------------------------------------------------
- // Write a 4 byte memory block using an authenticated write (with MAC).
- // The block location is selected by the
- // page number and offset blcok within the page. Multiple blocks can
- // be programmed without re-selecting the device using the continue flag.
- // This function does not use the Authenticated Write operation.
- //
- // Parameters
- // page - page number where the block to write is located (0, 1)
- // segment - segment number in page (0 to 7)
- // data - SHA input data for the Authenticated Write Memory including new_data, old_data, and manid
- // new_data - 4 byte buffer containing the data to write
- // old_data - 4 byte buffer containing the data to write
- // manid - 2 byte buffer containing the manufacturer ID (general device: 00h,00h)
- //
- // Restrictions
- // The memory block containing the targeted 4-byte segment must not be write protected.
- // The Read/Write Scratchpad command(w1_ds28el15_write_scratchpad) must have been issued once
- // in write mode after power-on reset to ensure proper setup of the SHA-256 engine.
- //
- // Returns: 0 - block written
- // else - Failed to write block (no presence or invalid CRC16)
- //
- int w1_ds28el15_write_authblock(struct w1_slave *sl, int page, int segment, uchar *data, int contflag)
- {
- uchar buf[256],cs;
- uchar new_data[4], old_data[4], manid[2];
- int cnt, i, offset;
- cnt = 0;
- offset = 0;
- if (!sl)
- return -ENODEV;
- memcpy(new_data, &data[0], 4);
- memcpy(old_data, &data[4], 4);
- memcpy(manid, &data[8], 2);
- if (!contflag) {
- if (w1_reset_select_slave(sl))
- return -1;
- buf[cnt++] = CMD_WRITE_AUTH_MEMORY;
- buf[cnt++] = (segment << 5) | page; // address
- // Send command
- w1_write_block(sl->master, &buf[0], 2);
- // Read the first CRC
- w1_read_block(sl->master, &buf[cnt], 2);
- cnt += 2;
- offset = cnt;
- }
- // add the data
- for (i = 0; i < 4; i++)
- buf[cnt++] = new_data[i];
- // Send data - first 4bytes
- w1_write_block(sl->master, new_data, 4);
- // read the second CRC
- w1_read_block(sl->master, &buf[cnt], 2);
- cnt += 2;
- // now wait for the MAC computation.
- msleep(SHA_COMPUTATION_DELAY);
- if (!contflag) {
- // check the first CRC16
- slave_crc16 = 0;
- for (i = 0; i < offset; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -1;
- }
- // check the second CRC16
- slave_crc16 = 0;
- for (i = offset; i < cnt; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -1;
- // compute the mac
- if (special_mode)
- {
- if (!calculate_write_authMAC256(page, segment, new_data, old_data, special_values, &buf[0]))
- return -1;
- }
- else
- {
- if (!calculate_write_authMAC256(page, segment, new_data, old_data, manid, &buf[0]))
- return -1;
- }
- // transmit MAC as a block - send the second 32bytes
- cnt=0;
- w1_write_block(sl->master, buf, 32);
- // calculate CRC on MAC
- slave_crc16 = 0;
- for (i = 0; i < 32; i++)
- docrc16(buf[i]);
- // append read of CRC16 and CS byte
- w1_read_block(sl->master, &buf[0], 3);
- cnt = 3;
- // ckeck CRC16
- for (i = 0; i < (cnt-1); i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -1;
- // check CS
- if (buf[cnt-1] != 0xAA)
- return -1;
- // send release and strong pull-up
- buf[0] = CMD_RELEASE;
- w1_write_block(sl->master, &buf[0], 1);
- // now wait for the MAC computation.
- msleep(EEPROM_WRITE_DELAY);
- // disable strong pullup
- // read the CS byte
- cs = w1_read_8(sl->master);
- if (cs == 0xAA)
- return 0;
- else
- return cs;
- }
- //--------------------------------------------------------------------------
- // Write a 4 byte memory block using an authenticated write (with MAC).
- // The MAC must be pre-calculated.
- //
- // Parameters
- // page - page number where the block to write is located (0 to 15)
- // segment - segment number in page (0 to 7)
- // new_data - 4 byte buffer containing the data to write
- // mac - mac to use for the write
- //
- // Returns: 0 - block written
- // else - Failed to write block (no presence or invalid CRC16)
- //
- int w1_ds28el15_write_authblockMAC(struct w1_slave *sl, int page, int segment, uchar *new_data, uchar *mac)
- {
- uchar buf[256],cs;
- int cnt, i, offset;
- cnt = 0;
- offset = 0;
- if (!sl)
- return -ENODEV;
- // check if not continuing a previous block write
- if (w1_reset_select_slave(sl))
- return -1;
- buf[cnt++] = CMD_WRITE_AUTH_MEMORY;
- buf[cnt++] = (segment << 5) | page; // address
- // Send command
- w1_write_block(sl->master, &buf[0], 2);
- // Read CRC
- w1_read_block(sl->master, &buf[cnt], 2);
- cnt += 2;
- offset = cnt;
- // add the data
- for (i = 0; i < 4; i++)
- buf[cnt++] = new_data[i];
- // Send data
- w1_write_block(sl->master, new_data, 4);
- // read first CRC
- w1_read_block(sl->master, &buf[cnt], 2);
- cnt += 2;
- // now wait for the MAC computation.
- msleep(SHA_COMPUTATION_DELAY);
- // disable strong pullup
- // check the first CRC16
- slave_crc16 = 0;
- for (i = 0; i < offset; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -1;
- // check the second CRC16
- slave_crc16 = 0;
- for (i = offset; i < cnt; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -1;
- // transmit MAC as a block
- w1_write_block(sl->master, mac, 32);
- // calculate CRC on MAC
- slave_crc16 = 0;
- for (i = 0; i < 32; i++)
- docrc16(mac[i]);
- // append read of CRC16 and CS byte
- w1_read_block(sl->master, &buf[0], 3);
- cnt = 3;
- // ckeck CRC16
- for (i = 0; i < (cnt-1); i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -1;
- // check CS
- if (buf[cnt-1] != 0xAA)
- return -1;
- // send release and strong pull-up
- buf[0] = CMD_RELEASE;
- w1_write_block(sl->master, &buf[0], 1);
- // now wait for the MAC computation.
- msleep(EEPROM_WRITE_DELAY);
- // disable strong pullup
- // read the CS byte
- cs = w1_read_8(sl->master);
- if (cs == 0xAA)
- return 0;
- else
- return cs;
- }
- #ifdef CONFIG_W1_CF
- //--------------------------------------------------------------------------
- // Read memory. Multiple pages can
- // be read without re-selecting the device using the continue flag.
- //
- // Parameters
- // seg - segment number(0~7) in page
- // page - page number where the block to read is located (0 to 15)
- // rdbuf - 32 byte buffer to contain the data to read
- // length - length to read (allow jsut segment(4bytes) unit) (4, 8, 16, ... , 64)
- //
- // Returns: 0 - block read and verified CRC
- // else - Failed to write block (no presence or invalid CRC16)
- //
- int w1_ds28el15_read_memory_check(struct w1_slave *sl, int seg, int page, uchar *rdbuf, int length)
- {
- uchar buf[256];
- int cnt, i, offset;
- cnt = 0;
- offset = 0;
- if (!sl)
- return -ENODEV;
- // Check presence detect
- if (w1_reset_overdrive_select_slave(sl))
- return -1;
- buf[cnt++] = CMD_READ_MEMORY;
- buf[cnt++] = (seg<<5) | page; // address
- // Send command
- w1_write_block(sl->master, &buf[0], 2);
- // Read CRC
- w1_read_block(sl->master, &buf[cnt], 2);
- cnt += 2;
- offset = cnt;
- // read data and CRC16
- w1_read_block(sl->master, &buf[cnt], length+2);
- cnt+=length+2;
- // check the first CRC16
- slave_crc16 = 0;
- for (i = 0; i < offset; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -2;
- if (READ_EOP_BYTE(seg) == length) {
- // check the second CRC16
- slave_crc16 = 0;
- for (i = offset; i < cnt; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -2;
- }
- // copy the data to the read buffer
- memcpy(rdbuf,&buf[offset],length);
- return 0;
- }
- #endif
- //--------------------------------------------------------------------------
- // Read memory. Multiple pages can
- // be read without re-selecting the device using the continue flag.
- //
- // Parameters
- // seg - segment number(0~7) in page
- // page - page number where the block to read is located (0 to 15)
- // rdbuf - 32 byte buffer to contain the data to read
- // length - length to read (allow jsut segment(4bytes) unit) (4, 8, 16, ... , 64)
- //
- // Returns: 0 - block read and verified CRC
- // else - Failed to write block (no presence or invalid CRC16)
- //
- int w1_ds28el15_read_memory(struct w1_slave *sl, int seg, int page, uchar *rdbuf, int length)
- {
- uchar buf[256];
- int cnt, i, offset;
- cnt = 0;
- offset = 0;
- if (!sl)
- return -ENODEV;
- // Check presence detect
- if (w1_reset_select_slave(sl))
- return -1;
- buf[cnt++] = CMD_READ_MEMORY;
- buf[cnt++] = (seg<<5) | page; // address
- // Send command
- w1_write_block(sl->master, &buf[0], 2);
- // Read CRC
- w1_read_block(sl->master, &buf[cnt], 2);
- cnt += 2;
- offset = cnt;
- // read data and CRC16
- w1_read_block(sl->master, &buf[cnt], length+2);
- cnt+=length+2;
- // check the first CRC16
- slave_crc16 = 0;
- for (i = 0; i < offset; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -1;
- if (READ_EOP_BYTE(seg) == length) {
- // check the second CRC16
- slave_crc16 = 0;
- for (i = offset; i < cnt; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -1;
- }
- // copy the data to the read buffer
- memcpy(rdbuf,&buf[offset],length);
- return 0;
- }
- //--------------------------------------------------------------------------
- // Read page and verify CRC. Multiple pages can
- // be read without re-selecting the device using the continue flag.
- //
- // Parameters
- // page - page number where the block to write is located (0 to 15)
- // rdbuf - 32 byte buffer to contain the data to read
- //
- // Returns: 0 - block read and verified CRC
- // else - Failed to write block (no presence or invalid CRC16)
- //
- int w1_ds28el15_read_page(struct w1_slave *sl, int page, uchar *rdbuf)
- {
- return w1_ds28el15_read_memory(sl, 0, page, rdbuf, 32);
- }
- //----------------------------------------------------------------------
- // Read the scratchpad (challenge or secret)
- //
- // 'rbbuf' - 32 byte buffer to contain the data to read
- //
- // Return: 0 - select complete
- // else - error during select, device not present
- //
- int w1_ds28el15_read_scratchpad(struct w1_slave *sl, uchar *rdbuf)
- {
- uchar buf[256];
- int cnt=0, i, offset;
- if (!sl)
- return -ENODEV;
- // select device for write
- if (w1_reset_select_slave(sl))
- return -1;
- buf[cnt++] = CMD_SELECT_SECRET;
- buf[cnt++] = 0x0F;
- // Send command
- w1_write_block(sl->master, &buf[0], 2);
- // Read CRC
- w1_read_block(sl->master, &buf[cnt], 2);
- cnt += 2;
- offset = cnt;
- // read data and CRC16
- w1_read_block(sl->master, &buf[cnt], 34);
- cnt+=34;
- // check first CRC16
- slave_crc16 = 0;
- for (i = 0; i < offset; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -1;
- // check the second CRC16
- slave_crc16 = 0;
- for (i = offset; i < cnt; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -1;
- // copy the data to the read buffer
- memcpy(rdbuf,&buf[offset],32);
- return 0;
- }
- //----------------------------------------------------------------------
- // Write the scratchpad (challenge or secret)
- //
- // 'data' - data to write to the scratchpad (32 bytes)
- //
- // Return: 0 - select complete
- // else - error during select, device not present
- //
- int w1_ds28el15_write_scratchpad(struct w1_slave *sl, uchar *data)
- {
- uchar buf[256];
- int cnt=0, i, offset;
- if (!sl)
- return -ENODEV;
- // select device for write
- if (w1_reset_select_slave(sl))
- return -1;
- buf[cnt++] = CMD_SELECT_SECRET;
- buf[cnt++] = 0x00;
- // Send command
- w1_write_block(sl->master, &buf[0], 2);
- // Read CRC
- w1_read_block(sl->master, &buf[cnt], 2);
- cnt += 2;
- offset = cnt;
- // add the data
- memcpy(&buf[cnt], data, 32);
- cnt+=32;
- // Send the data
- w1_write_block(sl->master, data, 32);
- // Read CRC
- w1_read_block(sl->master, &buf[cnt], 2);
- cnt += 2;
- // check first CRC16
- slave_crc16 = 0;
- for (i = 0; i < offset; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -2;
- // check the second CRC16
- slave_crc16 = 0;
- for (i = offset; i < cnt; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -3;
- return 0;
- }
- //----------------------------------------------------------------------
- // Load first secret operation on the DS28E25/DS28E22/DS28E15.
- //
- // 'lock' - option to lock the secret after the load (lock = 1)
- //
- // Restrictions
- // The Read/Write Scratchpad command(w1_ds28el15_write_scratchpad) must have been issued
- // in write mode prior to Load and Lock Secret to define the secret's value.
- //
- // Return: 0 - load complete
- // else - error during load, device not present
- //
- int w1_ds28el15_load_secret(struct w1_slave *sl, int lock)
- {
- uchar buf[256],cs;
- int cnt=0, i;
- if (!sl)
- return -ENODEV;
- // select device for write
- if (w1_reset_select_slave(sl))
- return -1;
- buf[cnt++] = CMD_LOAD_LOCK_SECRET;
- buf[cnt++] = (lock) ? 0xE0 : 0x00; // lock flag
- // Send command
- w1_write_block(sl->master, &buf[0], 2);
- // Read CRC
- w1_read_block(sl->master, &buf[cnt], 2);
- cnt += 2;
- // check CRC16
- slave_crc16 = 0;
- for (i = 0; i < cnt; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -1;
- // send release and strong pull-up
- buf[0] = CMD_RELEASE;
- w1_write_block(sl->master, &buf[0], 1);
- // now wait for the MAC computation.
- msleep(SECRET_EEPROM_DELAY);
- // disable strong pullup
- // read the CS byte
- cs = w1_read_8(sl->master);
- if (cs == 0xAA)
- return 0;
- else
- return cs;
- }
- //----------------------------------------------------------------------
- // Compute secret operation on the DS28E25/DS28E22/DS28E15.
- //
- // 'partial' - partial secret to load (32 bytes)
- // 'pbyte' - parameter byte including page_num and lock
- // 'page_num' - page number to read 0 - 16
- // 'lock' - option to lock the secret after the load (lock = 1)
- //
- // Restrictions
- // The Read/Write Scratchpad command(w1_ds28el15_write_scratchpad) must have been issued
- // in write mode prior to Compute and Lock Secret to define the partial secret.
- //
- // Return: 0 - compute complete
- // else - error during compute, device not present
- //
- int w1_ds28el15_compute_secret(struct w1_slave *sl, int pbyte)
- {
- uchar buf[256],cs;
- int cnt=0, i;
- int page_num, lock;
- if (!sl)
- return -ENODEV;
- page_num = pbyte & 0x01;
- lock = (pbyte & 0xE0) ? 1 : 0;
- // select device for write
- if (w1_reset_select_slave(sl))
- return -1;
- buf[cnt++] = CMD_COMPUTE_LOCK_SECRET;
- buf[cnt++] = (lock) ? (0xE0 | page_num) : page_num; // lock flag
- // Send command
- w1_write_block(sl->master, &buf[0], 2);
- // Read CRC
- w1_read_block(sl->master, &buf[cnt], 2);
- cnt += 2;
- // check CRC16
- slave_crc16 = 0;
- for (i = 0; i < cnt; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -1;
- // send release and strong pull-up
- buf[0] = CMD_RELEASE;
- w1_write_block(sl->master, &buf[0], 1);
- // now wait for the MAC computation.
- msleep(SHA_COMPUTATION_DELAY * 2 + SECRET_EEPROM_DELAY);
- // disable strong pullup
- // read the CS byte
- cs = w1_read_8(sl->master);
- if (cs == 0xAA)
- return 0;
- else
- return cs;
- }
- //--------------------------------------------------------------------------
- // Do Compute Page MAC command and return MAC. Optionally do
- // annonymous mode (anon != 0).
- //
- // Parameters
- // pbyte - parameter byte including page_num and anon
- // page_num - page number to read 0, 1
- // anon - Flag to indicate Annonymous mode if (anon != 0)
- // mac - 32 byte buffer for page data read
- //
- // Restrictions
- // The Read/Write Scratchpad command(w1_ds28el15_write_scratchpad) must have been issued
- // in write mode prior to Compute and Read Page MAC to define the challenge.
- //
- // Returns: 0 - page read has correct MAC
- // else - Failed to read page or incorrect MAC
- //
- int w1_ds28el15_compute_read_pageMAC(struct w1_slave *sl, int pbyte, uchar *mac)
- {
- uchar buf[256],cs;
- int cnt=0, i;
- if (!sl)
- return -ENODEV;
- // select device for write
- if (w1_reset_select_slave(sl))
- return -1;
- buf[cnt++] = CMD_COMPUTE_PAGEMAC;
- buf[cnt++] = pbyte;
- // Send command
- w1_write_block(sl->master, &buf[0], 2);
- // Read CRC
- w1_read_block(sl->master, &buf[cnt], 2);
- cnt += 2;
- // check CRC16
- slave_crc16 = 0;
- for (i = 0; i < cnt; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -2;
- // now wait for the MAC computation.
- msleep(SHA_COMPUTATION_DELAY * 2);
- // disable strong pullup
- // read the CS byte
- cs = w1_read_8(sl->master);
- if (cs != 0xAA)
- return -3;
- // read the MAC and CRC
- w1_read_block(sl->master, &buf[0], 34);
- // check CRC16
- slave_crc16 = 0;
- for (i = 0; i < 34; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -4;
- // copy MAC to return buffer
- memcpy(mac, buf, 32);
- return 0;
- }
- //--------------------------------------------------------------------------
- // Do Read Athenticated Page command and verify MAC. Optionally do
- // annonymous mode (anon != 0).
- //
- // Parameters
- // page_num - page number to read 0, 1
- // challange - 32 byte buffer containing the challenge
- // mac - 32 byte buffer for mac read
- // page_data - 32 byte buffer to contain the data to read
- // manid - 2 byte buffer containing the manufacturer ID (general device: 00h,00h)
- // skipread - Skip the read page and use the provided data in the 'page_data' buffer
- // anon - Flag to indicate Annonymous mode if (anon != 0)
- //
- // Returns: 0 - page read has correct MAC
- // else - Failed to read page or incorrect MAC
- //
- int w1_ds28el15_read_authverify(struct w1_slave *sl, int page_num, uchar *challenge, uchar *page_data, uchar *manid, int skipread, int anon)
- {
- uchar mac[32];
- uchar mt[128];
- int pbyte;
- int i = 0, rslt;
- if (!sl)
- return -ENODEV;
- if(w1_array[0] == 0) return 0;
- // check to see if we skip the read (use page_data)
- if (!skipread)
- {
- // read the page to get data
- while (i < RETRY_LIMIT) {
- rslt = w1_ds28el15_read_page(sl, page_num, page_data);
- if (rslt == 0)
- break;
- mdelay(10); /* wait 10ms */
- i++;
- }
- if (i > RETRY_LIMIT) {
- printk(KERN_ERR "w1_ds28el15_read_authverify err : -1F\n");
- return -1;
- }
- i = 0;
- }
- // The Read/Write Scratch pad command must have been issued in write mode prior
- // to Compute and Read Page MAC to define the challenge
- while (i < RETRY_LIMIT) {
- rslt = w1_ds28el15_write_scratchpad(sl, challenge);
- if (rslt == 0)
- break;
- mdelay(10); /* wait 10ms */
- i++;
- }
- if (i > RETRY_LIMIT) {
- printk(KERN_ERR "w1_ds28el15_read_authverify err : -2F\n");
- return -2;
- }
- i = 0;
- // have device compute mac
- pbyte = anon ? 0xE0 : 0x00;
- pbyte = pbyte | page_num;
- while (i < RETRY_LIMIT) {
- rslt = w1_ds28el15_compute_read_pageMAC(sl, pbyte, mac);
- if (rslt == 0)
- break;
- mdelay(10); /* wait 10ms */
- i++;
- }
- if (i > RETRY_LIMIT) {
- printk(KERN_ERR "w1_ds28el15_read_authverify err : -3\n");
- return -3;
- }
- // create buffer to compute and verify mac
- // clear
- memset(mt,0,128);
- // insert page data
- memcpy(&mt[0],page_data,32);
- // insert challenge
- memcpy(&mt[32],challenge,32);
- // insert ROM number or FF
- if (anon)
- memset(&mt[96],0xFF,8);
- else
- memcpy(&mt[96],rom_no,8);
- mt[106] = page_num;
- if (special_mode)
- {
- mt[105] = special_values[0];
- mt[104] = special_values[1];
- }
- else
- {
- mt[105] = manid[0];
- mt[104] = manid[1];
- }
- if (verify_mac256(mt, 119, mac) ==0) {
- printk(KERN_ERR "w1_ds28el15_compute_read_pageMAC err : -4\n");
- return -4;
- } else
- return 0;
- }
- //--------------------------------------------------------------------------
- // Verify provided MAC and page data. Optionally do
- // annonymous mode (anon != 0).
- //
- // Parameters
- // page_num - page number to read 0 - 16
- // challange - 32 byte buffer containing the challenge
- // page_data - 32 byte buffer to contain the data read
- // manid - 2 byte buffer containing the manufacturer ID (general device: 00h,00h)
- // mac - 32 byte buffer of mac read
- // anon - Flag to indicate Annonymous mode if (anon != 0)
- //
- // Returns: 0 - page read has correct MAC
- // else - Failed to read page or incorrect MAC
- //
- int w1_ds28el15_authverify(struct w1_slave *sl, int page_num, uchar *challenge, uchar *page_data, uchar *manid, uchar *mac, int anon)
- {
- uchar mt[128];
- // create buffer to compute and verify mac
- // clear
- memset(mt,0,128);
- // insert page data
- memcpy(&mt[0],page_data,32);
- // insert challenge
- memcpy(&mt[32],challenge,32);
- // insert ROM number or FF
- if (anon)
- memset(&mt[96],0xFF,8);
- else
- memcpy(&mt[96],rom_no,8);
- mt[106] = page_num;
- if (special_mode)
- {
- mt[105] = special_values[0];
- mt[104] = special_values[1];
- }
- else
- {
- mt[105] = manid[0];
- mt[104] = manid[1];
- }
- if (verify_mac256(mt, 119, mac) == 0)
- return -1;
- else
- return 0;
- }
- //--------------------------------------------------------------------------
- // Read status bytes, either personality or page protection.
- //
- // Parameters
- // pbyte - include personality, allpages, and page_num
- // personality - flag to indicate the read is the 4 personality bytes (1)
- // or page page protection (0)
- // allpages - flag to indicate if just one page (0) or all (1) page protection
- // bytes.
- // block_num - block number if reading protection 0 to 3
- // rdbuf - 16 byte buffer personality bytes (length 4) or page protection
- // (length 1 or 16)
- //
- // Returns: 0 - status read
- // else - Failed to read status
- //
- int w1_ds28el15_read_status(struct w1_slave *sl, int pbyte, uchar *rdbuf)
- {
- uchar buf[256];
- int cnt, i, offset,rdnum;
- int personality, allpages, block_num;
- if (!sl)
- return -ENODEV;
- personality = (pbyte & 0xE0) ? 1 : 0;
- allpages = (pbyte == 0) ? 1 : 0;
- block_num = pbyte & 0x03;
- cnt = 0;
- offset = 0;
- if (w1_reset_select_slave(sl)){
- pr_info("%s reset_select_slave error", __func__);
- return -1;
- }
- buf[cnt++] = CMD_READ_STATUS;
- if (personality)
- buf[cnt++] = 0xE0;
- else if (!allpages)
- buf[cnt++] = block_num;
- else
- buf[cnt++] = 0;
- // send the command
- w1_write_block(sl->master, &buf[0], 2);
- offset = cnt + 2;
- // adjust data length
- if ((personality) || (allpages))
- rdnum = 8;
- else
- rdnum = 5;
- // Read the bytes
- w1_read_block(sl->master, &buf[cnt], rdnum);
- cnt += rdnum;
- // check the first CRC16
- slave_crc16 = 0;
- for (i = 0; i < offset; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001){
- pr_info("%s slave_crc16 is error 1.\n", __func__);
- return -1;
- }
- if ((personality || allpages || (block_num == 1)))
- {
- // check the second CRC16
- slave_crc16 = 0;
- for (i = offset; i < cnt; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001){
- pr_info("%s slave_crc16 is error 2.\n", __func__);
- return -1;
- }
- }
- // copy the data to the read buffer
- memcpy(rdbuf,&buf[offset],rdnum-4);
- return 0;
- }
- //--------------------------------------------------------------------------
- // Write page protection byte.
- //
- // Parameters
- // block - block number (0 to 3) which covers two pages each
- // prot - protection byte
- //
- // Returns: 0 - protection written
- // else - Failed to set protection
- //
- int w1_ds28el15_write_blockprotection(struct w1_slave *sl, uchar prot)
- {
- uchar buf[256],cs;
- int cnt=0, i;
- if (!sl)
- return -ENODEV;
- // select device for write
- if (w1_reset_select_slave(sl))
- return -1;
- buf[cnt++] = CMD_WRITE_BLOCK_PROTECT;
- // compute parameter byte
- buf[cnt++] = prot;
- w1_write_block(sl->master, &buf[0], cnt);
- // Read CRC
- w1_read_block(sl->master, &buf[cnt], 2);
- cnt += 2;
- // check CRC16
- slave_crc16 = 0;
- for (i = 0; i < cnt; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -1;
- // sent release
- // now wait for programming
- msleep(EEPROM_WRITE_DELAY);
- // disable strong pullup
- // read the CS byte
- cs = w1_read_8(sl->master);
- if (cs == 0xAA)
- return 0;
- else
- return cs;
- }
- //--------------------------------------------------------------------------
- // Write page protection byte.
- //
- // Parameters
- // data - input data for Authenticated Write Block Protection
- // new_value - new protection byte(parameter byte) including block num
- // old_value - old protection byte(parameter byte)
- // manid - manufacturer ID
- //
- // Returns: 0 - protection written
- // else - Failed to set protection
- //
- int w1_ds28el15_write_authblockprotection(struct w1_slave *sl, uchar *data)
- {
- uchar buf[256],cs,mt[64];
- int cnt=0, i;
- int new_value, old_value;
- uchar manid[2];
- if (!sl)
- return -ENODEV;
- new_value = data[0];
- old_value = data[1];
- manid[0] = data[2];
- manid[1] = data[3];
- // select device for write
- if (w1_reset_select_slave(sl))
- return -1;
- buf[cnt++] = CMD_WRITE_AUTH_PROTECT;
- buf[cnt++] = new_value;
- // Send command
- w1_write_block(sl->master, &buf[0], 2);
- // read first CRC
- w1_read_block(sl->master, &buf[cnt], 2);
- // now wait for the MAC computation.
- msleep(SHA_COMPUTATION_DELAY);
- // disable strong pullup
- // check CRC16
- slave_crc16 = 0;
- for (i = 0; i < cnt; i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -1;
- // calculate MAC
- // clear
- memset(mt,0,64);
- // insert ROM number
- memcpy(&mt[32],rom_no,8);
- // instert block and page
- mt[43] = 0;
- mt[42] = new_value & 0x0F;
- // check on special mode
- if (special_mode)
- {
- mt[41] = special_values[0];
- mt[40] = special_values[1];
- }
- else
- {
- mt[41] = manid[0];
- mt[40] = manid[1];
- }
- // old data
- mt[44] = (old_value & PROT_BIT_AUTHWRITE) ? 0x01 : 0x00;
- mt[45] = (old_value & PROT_BIT_EPROM) ? 0x01 : 0x00;
- mt[46] = (old_value & PROT_BIT_WRITE) ? 0x01 : 0x00;
- mt[47] = (old_value & PROT_BIT_READ) ? 0x01 : 0x00;
- // new data
- mt[48] = (new_value & PROT_BIT_AUTHWRITE) ? 0x01 : 0x00;
- mt[49] = (new_value & PROT_BIT_EPROM) ? 0x01 : 0x00;
- mt[50] = (new_value & PROT_BIT_WRITE) ? 0x01 : 0x00;
- mt[51] = (new_value & PROT_BIT_READ) ? 0x01 : 0x00;
- // compute the mac
- compute_mac256(mt, 55, &buf[0]);
- cnt = 32;
- // send the MAC
- w1_write_block(sl->master, &buf[0], 32);
- // Read CRC and CS byte
- w1_read_block(sl->master, &buf[cnt], 3);
- cnt += 3;
- // ckeck CRC16
- slave_crc16 = 0;
- for (i = 0; i < (cnt-1); i++)
- docrc16(buf[i]);
- if (slave_crc16 != 0xB001)
- return -1;
- // check CS
- if (buf[cnt-1] != 0xAA)
- return -1;
- // send release and strong pull-up
- // DATASHEET_CORRECTION - last bit in release is a read-zero so don't check echo of write byte
- w1_write_8(sl->master, 0xAA);
- // now wait for the MAC computation.
- msleep(EEPROM_WRITE_DELAY);
- // disable strong pullup
- // read the CS byte
- cs = w1_read_8(sl->master);
- if (cs == 0xAA)
- return 0;
- else
- return cs;
- }
- //-------------------------------------------------------------------------
- // get_array_value
- //
- #ifdef CONFIG_OF_SUBCMDLINE_PARSE
- static int get_array_value(void)
- {
- int i, ret;
- char str[20], *buf, data;
- pr_info("%s: W1 Read Array.\n", __func__);
- ret = of_parse_args_on_subcmdline("array=",(char *)str);
- if (ret) {
- pr_err("%s: W1 Read Array Error\n", __func__);
- return -1;
- }
- buf = str;
- for(i=0;i<5;i++){
- strncpy(&data,&buf[i*2],2);
- sscanf(&data, "%x", (unsigned int *)&ret);
- w1_array[i]=ret;
- }
- return 0;
- }
- #else
- static int __init get_array_value(char *str)
- {
- int i, get[6];
- pr_info("%s: W1 Read Array\n", __func__);
- for(i=0;i<5;i++){
- sscanf(str, "%x", &get[i]);
- w1_array[i]=get[i];
- str=str+3;
- }
- return 0;
- }
- __setup("array=", get_array_value);
- #endif
- //--------------------------------------------------------------------------
- // w1_ds28el15_verifymac
- //
- // compare two mac data, Device mac and calculated mac and
- // returned the result
- // Returns: 0 - Success, have the same mac data in both of Device and AP.
- // else - Failed, have the different mac data or verifying sequnce failed.
- //
- int w1_ds28el15_verifymac(struct w1_slave *sl)
- {
- int rslt,rt;
- uchar buf[256], challenge[32], manid[2];
- uchar memimage[512];
- uchar master_secret[32];
- #if 1
- int i = 0;
- #endif
- // copy the secret code
- memcpy(master_secret, w1_array, 32); // Set temp_secret to the master secret
- rt = 0;
- if(w1_array[0] == 0) {
- pr_info("%s: w1_array[0] == 0\n", __func__);
- goto success;
- }
- // Store the master secret and romid.
- set_secret(master_secret);
- set_romid(rom_no);
- // read personality bytes to get manufacturer ID
- #if 1
- while (i < RETRY_LIMIT) {
- rslt = w1_ds28el15_read_status(sl, 0xE0, buf);
- if (rslt == 0)
- break;
- mdelay(10); /* wait 10ms */
- i++;
- }
- i = 0;
- #else
- rslt = w1_ds28el15_read_status(sl, 0xE0, buf);
- #endif
- if (rslt == 0)
- {
- manid[0] = buf[3];
- manid[1] = buf[2];
- } else {
- pr_info("%s : read_status error\n", __func__);
- rt = -1;
- goto success;
- }
- // if you want to use random value, insert code here.
- get_random_bytes(challenge, 32); // random challenge
- // Enhance verification status
- while (i < RETRY_LIMIT) {
- rslt = w1_ds28el15_read_authverify(sl, 0, challenge,
- &memimage[0], manid, 0, 0);
- if (rslt == 0)
- break;
- mdelay(10); /* wait 10ms */
- i++;
- }
- printk(KERN_ERR "%s result : %d\n",__func__, rslt);
- if (rslt){
- pr_info("%s: read_authverify error\n", __func__);
- rt = -1;
- }
- success:
- return rt;
- }
- static int w1_ds28el15_setup_device(struct w1_slave *sl)
- {
- int rslt,rt;
- uchar buf[256], challenge[32], manid[2];
- uchar memimage[512];
- uchar master_secret[32];
- // hard code master secret
- memcpy(master_secret, w1_array, 32); // Set temp_secret to the master secret
- // ----- DS28EL25/DS28EL22/DS28EL15 Setup
- printk(KERN_ERR "-------- DS28EL15 Setup Example\n");
- rt = 0;
- printk(KERN_ERR "Write scratchpad - master secret\n");
- rslt = w1_ds28el15_write_scratchpad(sl, master_secret);
- printk(KERN_ERR "result : %d\n", rslt);
- if (rslt) rt = -1;
- printk(KERN_ERR "Load the master secret\n");
- rslt = w1_ds28el15_load_secret(sl, 0);
- printk(KERN_ERR "result : %d\n",rslt);
- if (rslt) rt = -1;
- printk(KERN_ERR "Set the master secret in the Software SHA-256\n");
- set_secret(master_secret);
- set_romid(rom_no);
- // fill image with random data to write
- // read personality bytes to get manufacturer ID
- printk(KERN_ERR " w1_ds28el15_read_status(\n");
- rslt = w1_ds28el15_read_status(sl, 0xE0, buf);
- if (rslt == 0) {
- manid[0] = buf[3];
- manid[1] = buf[2];
- }
- else{
- rt = -1;
- goto end;
- }
- printk(KERN_ERR "result : %d\n",rslt);
- printk(KERN_ERR "Read-Authenticate with unique secret\n");
- get_random_bytes(challenge, 32); // random challenge
- rslt = w1_ds28el15_read_authverify(sl, 0, challenge, &memimage[0], manid, 0, 0);
- printk(KERN_ERR "result : %d\n",rslt);
- if (rslt) rt = -1;
- printk(KERN_ERR "DS28EL15 Setup Example: %s\n",(rt) ? "FAIL" : "SUCCESS");
- printk(KERN_ERR "--------------------------------------------------\n");
- end:
- return rt;
- }
- #if 0
- static int w1_ds28el15_application(struct w1_slave *sl)
- {
- int i,rslt,rt;
- uchar buf[256], challenge[32], manid[2], new_page[32];
- uchar memimage[512];
- uchar master_secret[32];
- // ----- DS28EL25/DS28EL22/DS28EL15 Application Example
- printk(KERN_ERR "\n-------- DS28EL15 Application Example\n");
- // hard code master secret
- for (i = 0; i < 32; i++)
- master_secret[i] = w1_array[i]; // Set master secret to temp_secret
- rt = 0;
- printk(KERN_ERR "Set the master secret in the Software SHA-256\n");
- set_secret(master_secret);
- set_romid(rom_no);
- // read personality bytes to get manufacturer ID
- rslt = w1_ds28el15_read_status(sl, 0xE0, buf);
- if (rslt == 0)
- {
- manid[0] = buf[3];
- manid[1] = buf[2];
- }
- else
- rt = -1;
- printk(KERN_ERR "result : %d\n",rslt);
- printk(KERN_ERR "Read-Authenticated page 0\n");
- get_random_bytes(challenge, 32); // random challenge
- rslt = w1_ds28el15_read_authverify(sl, 0, challenge, &memimage[0], manid, 0, 0);
- printk(KERN_ERR "result : %d\n",rslt);
- if (rslt) rt = -1;
- // change data block 0 by inverting the current data
- printk(KERN_ERR "Old data: ");
- for (i = 0; i < 4; i++)
- printk(KERN_ERR "%02X ",memimage[i]);
- printk(KERN_ERR "\nNew data: ");
- for (i = 0; i < 4; i++)
- {
- new_page[i] = ~memimage[i];
- printk(KERN_ERR "%02X ",new_page[i]);
- }
- // Write new block
- printk(KERN_ERR "\nWrite block at address 0000h\n");
- memset(&buf[0], 0x00, 10); // use 10bytes(4+4+2) for data
- memcpy(&buf[0], &new_page[0], 4);
- memcpy(&buf[4], &memimage[0], 4);
- memcpy(&buf[8], manid, 2);
- rslt = w1_ds28el15_write_authblock(sl, 0, 0, buf, 0);
- printk(KERN_ERR "result : %d\n",rslt);
- if (rslt) rt = -1;
- memcpy(&memimage[0], &new_page[0], 4);
- // verify memory is correct by doing just a compute
- printk(KERN_ERR "Read-Authenticate page 0 after write\n");
- get_random_bytes(challenge, 32); // random challenge
- rslt = w1_ds28el15_read_authverify(sl, 0, challenge, &memimage[0], manid, 1, 0);
- printk(KERN_ERR "result : %d\n",rslt);
- if (rslt) rt = -1;
- printk(KERN_ERR "DS28EL15 Application Example: %s\n",(rt) ? "FAIL" : "SUCCESS");
- printk(KERN_ERR "--------------------------------------------------------\n");
- return rt;
- }
- #endif
- static ssize_t w1_ds28el15_read_user_eeprom(struct device *device,
- struct device_attribute *attr, char *buf);
- static struct device_attribute w1_read_user_eeprom_attr =
- __ATTR(read_eeprom, S_IRUGO, w1_ds28el15_read_user_eeprom, NULL);
- // read 64 bytes user eeprom data
- static ssize_t w1_ds28el15_read_user_eeprom(struct device *device,
- struct device_attribute *attr, char *buf)
- {
- struct w1_slave *sl = dev_to_w1_slave(device);
- u8 rdbuf[64];
- int result, i, page_num;
- ssize_t c = PAGE_SIZE;
- // read page 0
- page_num=0;
- c -= snprintf(buf + PAGE_SIZE - c, c, "page %d read\n", page_num);
- result = w1_ds28el15_read_page(sl, page_num, &rdbuf[0]);
- if (result != 0) {
- c -= snprintf(buf + PAGE_SIZE - c, c, "\npage %d read fail\n", page_num);
- return 0;
- }
- for (i = 0; i < 32; ++i)
- c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ", rdbuf[i]);
- c -= snprintf(buf + PAGE_SIZE - c, c, "\npage %d read done\n", page_num);
- // read page 1
- page_num=1;
- result = w1_ds28el15_read_page(sl, page_num, &rdbuf[32]);
- if (result != 0) {
- c -= snprintf(buf + PAGE_SIZE - c, c, "\npage %d read fail\n", page_num);
- return 0;
- }
- for (i = 32; i < 64; ++i)
- c -= snprintf(buf + PAGE_SIZE - c, c, "%02x ", rdbuf[i]);
- c -= snprintf(buf + PAGE_SIZE - c, c, "\npage %d read done\n", page_num);
- return PAGE_SIZE - c;
- }
- static ssize_t w1_ds28el15_check_color(struct device *device,
- struct device_attribute *attr, char *buf);
- static struct device_attribute w1_check_color_attr =
- __ATTR(check_color, S_IRUGO, w1_ds28el15_check_color, NULL);
- // check COLOR for cover
- static ssize_t w1_ds28el15_check_color(struct device *device,
- struct device_attribute *attr, char *buf)
- {
- // read cover color
- return sprintf(buf, "%d\n", color);
- }
- #ifdef CONFIG_W1_CF
- static ssize_t w1_ds28el15_cf(struct device *device,
- struct device_attribute *attr, char *buf);
- static struct device_attribute w1_cf_attr =
- __ATTR(cf, S_IRUGO, w1_ds28el15_cf, NULL);
- // check cf_node cover or not
- static ssize_t w1_ds28el15_cf(struct device *device,
- struct device_attribute *attr, char *buf)
- {
- // read mem
- return sprintf(buf, "%d\n", cf_node);
- }
- #endif
- static ssize_t w1_ds28el15_check_id(struct device *device,
- struct device_attribute *attr, char *buf);
- static struct device_attribute w1_check_id_attr =
- __ATTR(check_id, S_IRUGO, w1_ds28el15_check_id, NULL);
- // check ID for cover
- static ssize_t w1_ds28el15_check_id(struct device *device,
- struct device_attribute *attr, char *buf)
- {
- // read cover id
- return sprintf(buf, "%d\n", id);
- }
- static ssize_t w1_ds28el15_verify_mac(struct device *device,
- struct device_attribute *attr, char *buf);
- static struct device_attribute w1_verifymac_attr =
- __ATTR(verify_mac, S_IRUGO, w1_ds28el15_verify_mac, NULL);
- // verified mac value between the device and AP
- static ssize_t w1_ds28el15_verify_mac(struct device *device,
- struct device_attribute *attr, char *buf)
- {
- struct w1_slave *sl = dev_to_w1_slave(device);
- int result;
- // verify mac
- result = w1_ds28el15_verifymac(sl);
- return sprintf(buf, "%d\n", result);
- }
- static int w1_ds28el15_get_buffer(struct w1_slave *sl, uchar *rdbuf, int retry_limit)
- {
- int ret = -1, retry = 0;
- while((ret != 0) && (retry < retry_limit)) {
- ret = w1_ds28el15_read_page(sl, 0, &rdbuf[0]);
- if(ret != 0 )
- pr_info("%s : error %d\n", __func__, ret);
- retry++;
- }
- return ret;
- }
- #ifdef CONFIG_W1_SN
- static const int sn_cdigit[19] = {
- 0x0e, 0x0d, 0x1f, 0x0b, 0x1c,
- 0x12, 0x0f, 0x1e, 0x0a, 0x13,
- 0x14, 0x15, 0x19, 0x16, 0x17,
- 0x20, 0x1b, 0x1d, 0x11};
- static bool w1_ds28el15_check_digit(const uchar *sn)
- {
- int i, tmp1 = 0, tmp2 = 0;
- int cdigit = sn[3];
- if (cdigit == 0x1e)
- return true;
- for (i=4;i<10;i++)
- tmp1 += sn[i];
- tmp1 += sn[4]*5;
- tmp2 = (tmp1 * sn[9] * sn[13]) % 19;
- tmp1 = (sn[10] + sn[12]) * 3 + (sn[11] + sn[13]) * 6 + 14;
- if (cdigit == sn_cdigit[((tmp1 + tmp2) % 19)])
- return true;
- else
- return false;
- }
- static uchar w1_ds28el15_char_convert(uchar c)
- {
- char ctable[36] = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
- 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W',
- 'X', 'Y', 'Z', 'I', 'O', 'U'};
- return ctable[c];
- }
- static void w1_ds28el15_slave_sn(const uchar *rdbuf)
- {
- int i;
- u8 sn[15];
- sn[14] = 0;
- if (w1_ds28el15_check_digit(&rdbuf[4])) {
- for (i = 0 ; i < 14 ; i++)
- sn[i] = w1_ds28el15_char_convert(rdbuf[i+4]);
- pr_info("%s: %s\n", __func__, sn);
- for (i = 0 ; i < 14 ; i++)
- g_sn[i] = sn[13 - i];
- } else {
- for (i = 0 ; i < 14 ; i++)
- sn[i] = w1_ds28el15_char_convert(rdbuf[i+4]);
- pr_info("%s: sn is not good %s\n", __func__, sn);
- }
- }
- #endif
- static void w1_ds28el15_update_slave_info(struct w1_slave *sl) {
- u8 rdbuf[32];
- int ret, retry = 0;
- ret = w1_ds28el15_get_buffer(sl, &rdbuf[0], 10);
- if(ret != 0)
- pr_info("%s : fail to get buffer %d\n", __func__, ret);
- while((rdbuf[0] < sl->id_min) || (rdbuf[0] > sl->id_max) ||
- (rdbuf[1] < sl->color_min) || (rdbuf[1] > sl->color_max)) {
- printk(KERN_ERR "%s: out of range : %d %d \n", __func__, rdbuf[0], rdbuf[1]);
- if(retry > 10) {
- printk(KERN_ERR "%s: out of range over 10 times.\n", __func__);
- pr_info("%s: Change ID(%d) & Color(%d) to Default Value(%d, %d)",
- __func__, rdbuf[0], rdbuf[1], sl->id_default, sl->color_default);
- rdbuf[0] = sl->id_default;
- rdbuf[1] = sl->color_default;
- break;
- }
- ret = w1_ds28el15_get_buffer(sl, &rdbuf[0], 10);
- if(ret != 0)
- pr_info("%s : fail to get buffer %d\n", __func__, ret);
- retry++;
- }
- //read page 0, ID is 0 ~ 7 bit(rdbuf[0])
- id = rdbuf[0];
- // read page 0, COLOR is 8 ~ 15 bit(rdbuf[1])
- color = rdbuf[1];
- pr_info("%s Read ID(%d) & Color(%d) & Verification State(%d)\n",
- __func__, id, color, verification);
- #ifdef CONFIG_W1_SN
- w1_ds28el15_slave_sn(&rdbuf[0]);
- #endif
- }
- static int w1_parse_dt(struct w1_slave *sl)
- {
- struct device_node* np;
- np = of_find_node_by_path("/soc/ds28el15");
- if (!np) {
- pr_err("%s: get ds28el15 node failed\n", __func__);
- return -ENODEV;
- }
- of_property_read_u32(np, "ds28el15,id-min", &sl->id_min);
- of_property_read_u32(np, "ds28el15,id-max", &sl->id_max);
- of_property_read_u32(np, "ds28el15,id-default", &sl->id_default);
- of_property_read_u32(np, "ds28el15,color-min", &sl->color_min);
- of_property_read_u32(np, "ds28el15,color-max", &sl->color_max);
- of_property_read_u32(np, "ds28el15,color-default", &sl->color_default);
- pr_info("%s : id min[%d] max[%d] default[%d]\n", __func__,
- sl->id_min, sl->id_max, sl->id_default);
- pr_info("%s : color min[%d] max[%d] default[%d]\n", __func__,
- sl->color_min, sl->color_max, sl->color_default);
- return 0;
- }
- static void w1_set_default_range(struct w1_slave *sl)
- {
- pr_info("%s : get default range\n", __func__);
- sl->id_min = ID_MIN;
- sl->id_max = ID_MAX;
- sl->id_default = ID_DEFAULT;
- sl->color_min = CO_MIN;
- sl->color_max = CO_MAX;
- sl->color_default = CO_DEFAULT;
- pr_info("%s : id min[%d] max[%d] default[%d]\n", __func__,
- sl->id_min, sl->id_max, sl->id_default);
- pr_info("%s : color min[%d] max[%d] default[%d]\n", __func__,
- sl->color_min, sl->color_max, sl->color_default);
- }
- static int w1_ds28el15_add_slave(struct w1_slave *sl)
- {
- int err = 0;
- #ifdef CONFIG_W1_CF
- int count = 0, rst = 0;
- u8 rdbuf[32];
- #endif
- printk(KERN_ERR "\nw1_ds28el15_add_slave start\n");
- err = w1_parse_dt(sl);
- if (err) {
- printk(KERN_ERR "%s: w1_parse_dt error\n", __func__);
- w1_set_default_range(sl);
- }
- #ifdef CONFIG_OF_SUBCMDLINE_PARSE
- err = get_array_value();
- if (err) {
- printk(KERN_ERR "%s: w1_get_array_value error\n", __func__);
- }
- #endif
- err = device_create_file(&sl->dev, &w1_read_user_eeprom_attr);
- if (err) {
- device_remove_file(&sl->dev, &w1_read_user_eeprom_attr);
- printk(KERN_ERR "%s: w1_read_user_eeprom_attr error\n", __func__);
- return err;
- }
- err = device_create_file(&sl->dev, &w1_verifymac_attr);
- if (err) {
- device_remove_file(&sl->dev, &w1_verifymac_attr);
- printk(KERN_ERR "%s: w1_verifymac_attr error\n", __func__);
- return err;
- }
- #ifdef CONFIG_W1_CF
- err = device_create_file(&sl->dev, &w1_cf_attr);
- if (err) {
- device_remove_file(&sl->dev, &w1_cf_attr);
- printk(KERN_ERR "%s: w1_cf_attr error\n", __func__);
- return err;
- }
- #endif
- err = device_create_file(&sl->dev, &w1_check_id_attr);
- if (err) {
- device_remove_file(&sl->dev, &w1_check_id_attr);
- printk(KERN_ERR "%s: w1_check_id_attr error\n", __func__);
- return err;
- }
- err = device_create_file(&sl->dev, &w1_check_color_attr);
- if (err) {
- device_remove_file(&sl->dev, &w1_check_color_attr);
- printk(KERN_ERR "%s: w1_check_color_attr error\n", __func__);
- return err;
- }
- // copy rom id to use mac calculation
- memcpy(rom_no, (u8 *)&sl->reg_num, sizeof(sl->reg_num));
- if (init_verify) {
- if (skip_setup == 0) {
- err = w1_ds28el15_setup_device(sl);
- printk(KERN_ERR "w1_ds28el15_setup_device\n");
- skip_setup = 1;
- err = w1_ds28el15_verifymac(sl);
- verification = err;
- } else {
- err = w1_ds28el15_verifymac(sl);
- verification = err;
- printk(KERN_ERR "w1_ds28el15_verifymac\n");
- }
- }
- #ifdef CONFIG_SEC_H_PROJECT
- pr_info("%s:verified(%d)", __func__, verified);
- if(!verified)
- #else
- if(!verification)
- #endif
- {
- #ifdef CONFIG_W1_CF
- while (count < RETRY_LIMIT_CF) {
- rst = w1_ds28el15_read_memory_check(sl, 0, 0, rdbuf, 32);
- if (rst == 0)
- break;
- count++;
- }
- if (rst == -2)
- cf_node = 1;
- else
- cf_node = 0;
- pr_info("%s:COVER CLASS(%d)\n", __func__, cf_node);
- #endif
- #if defined(CONFIG_SEC_H_PROJECT)
- w1_ds28el15_update_slave_info(sl);
- #else
- w1_ds28el15_update_slave_info(sl);
- pr_info("%s:uevent send 1\n", __func__);
- input_report_switch(sl->master->bus_master->input, SW_W1, 1);
- input_sync(sl->master->bus_master->input);
- #endif
- }
- printk(KERN_ERR "w1_ds28el15_add_slave end, skip_setup=%d, err=%d\n", skip_setup, err);
- return err;
- }
- static void w1_ds28el15_remove_slave(struct w1_slave *sl)
- {
- device_remove_file(&sl->dev, &w1_read_user_eeprom_attr);
- device_remove_file(&sl->dev, &w1_verifymac_attr);
- #ifdef CONFIG_W1_CF
- device_remove_file(&sl->dev, &w1_cf_attr);
- #endif
- device_remove_file(&sl->dev, &w1_check_id_attr);
- device_remove_file(&sl->dev, &w1_check_color_attr);
- verification = -1;
- printk(KERN_ERR "\nw1_ds28el15_remove_slave\n");
- }
- static struct w1_family_ops w1_ds28el15_fops = {
- .add_slave = w1_ds28el15_add_slave,
- .remove_slave = w1_ds28el15_remove_slave,
- };
- static struct w1_family w1_ds28el15_family = {
- .fid = W1_FAMILY_DS28EL15,
- .fops = &w1_ds28el15_fops,
- };
- static int __init w1_ds28el15_init(void)
- {
- return w1_register_family(&w1_ds28el15_family);
- }
- static void __exit w1_ds28el15_exit(void)
- {
- w1_unregister_family(&w1_ds28el15_family);
- }
- late_initcall(w1_ds28el15_init);
- module_exit(w1_ds28el15_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("Clark Kim <clark.kim@maximintegrated.com>");
- MODULE_DESCRIPTION("1-wire Driver for Maxim/Dallas DS23EL15 DeepCover Secure Authenticator IC");
|