i2c_tools.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Minimal i2c-tools implementation for busybox.
  4. * Parts of code ported from i2c-tools:
  5. * http://www.lm-sensors.org/wiki/I2CTools.
  6. *
  7. * Copyright (C) 2014 by Bartosz Golaszewski <bartekgola@gmail.com>
  8. *
  9. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  10. */
  11. //config:config I2CGET
  12. //config: bool "i2cget (5.5 kb)"
  13. //config: default y
  14. //config: help
  15. //config: Read from I2C/SMBus chip registers.
  16. //config:
  17. //config:config I2CSET
  18. //config: bool "i2cset (6.7 kb)"
  19. //config: default y
  20. //config: help
  21. //config: Set I2C registers.
  22. //config:
  23. //config:config I2CDUMP
  24. //config: bool "i2cdump (7.1 kb)"
  25. //config: default y
  26. //config: help
  27. //config: Examine I2C registers.
  28. //config:
  29. //config:config I2CDETECT
  30. //config: bool "i2cdetect (7.1 kb)"
  31. //config: default y
  32. //config: help
  33. //config: Detect I2C chips.
  34. //config:
  35. //config:config I2CTRANSFER
  36. //config: bool "i2ctransfer (4.0 kb)"
  37. //config: default y
  38. //config: help
  39. //config: Send user-defined I2C messages in one transfer.
  40. //config:
  41. //applet:IF_I2CGET(APPLET(i2cget, BB_DIR_USR_SBIN, BB_SUID_DROP))
  42. //applet:IF_I2CSET(APPLET(i2cset, BB_DIR_USR_SBIN, BB_SUID_DROP))
  43. //applet:IF_I2CDUMP(APPLET(i2cdump, BB_DIR_USR_SBIN, BB_SUID_DROP))
  44. //applet:IF_I2CDETECT(APPLET(i2cdetect, BB_DIR_USR_SBIN, BB_SUID_DROP))
  45. //applet:IF_I2CTRANSFER(APPLET(i2ctransfer, BB_DIR_USR_SBIN, BB_SUID_DROP))
  46. /* not NOEXEC: if hw operation stalls, use less memory in "hung" process */
  47. //kbuild:lib-$(CONFIG_I2CGET) += i2c_tools.o
  48. //kbuild:lib-$(CONFIG_I2CSET) += i2c_tools.o
  49. //kbuild:lib-$(CONFIG_I2CDUMP) += i2c_tools.o
  50. //kbuild:lib-$(CONFIG_I2CDETECT) += i2c_tools.o
  51. //kbuild:lib-$(CONFIG_I2CTRANSFER) += i2c_tools.o
  52. /*
  53. * Unsupported stuff:
  54. *
  55. * - upstream i2c-tools can also look-up i2c busses by name, we only accept
  56. * numbers,
  57. * - bank and bankreg parameters for i2cdump are not supported because of
  58. * their limited usefulness (see i2cdump manual entry for more info),
  59. * - i2cdetect doesn't look for bus info in /proc as it does in upstream, but
  60. * it shouldn't be a problem in modern kernels.
  61. */
  62. #include "libbb.h"
  63. #include <linux/i2c.h>
  64. #define I2CDUMP_NUM_REGS 256
  65. #define I2CDETECT_MODE_AUTO 0
  66. #define I2CDETECT_MODE_QUICK 1
  67. #define I2CDETECT_MODE_READ 2
  68. /* linux/i2c-dev.h from i2c-tools overwrites the one from linux uapi
  69. * and defines symbols already defined by linux/i2c.h.
  70. * Also, it defines a bunch of static inlines which we would rather NOT
  71. * inline. What a mess.
  72. * We need only these definitions from linux/i2c-dev.h:
  73. */
  74. #define I2C_SLAVE 0x0703
  75. #define I2C_SLAVE_FORCE 0x0706
  76. #define I2C_FUNCS 0x0705
  77. #define I2C_PEC 0x0708
  78. #define I2C_SMBUS 0x0720
  79. #define I2C_RDWR 0x0707
  80. #define I2C_RDWR_IOCTL_MAX_MSGS 42
  81. #define I2C_RDWR_IOCTL_MAX_MSGS_STR "42"
  82. struct i2c_smbus_ioctl_data {
  83. __u8 read_write;
  84. __u8 command;
  85. __u32 size;
  86. union i2c_smbus_data *data;
  87. };
  88. struct i2c_rdwr_ioctl_data {
  89. struct i2c_msg *msgs; /* pointers to i2c_msgs */
  90. __u32 nmsgs; /* number of i2c_msgs */
  91. };
  92. /* end linux/i2c-dev.h */
  93. /*
  94. * This is needed for ioctl_or_perror_and_die() since it only accepts pointers.
  95. */
  96. static ALWAYS_INLINE void *itoptr(int i)
  97. {
  98. return (void*)(intptr_t)i;
  99. }
  100. static int32_t i2c_smbus_access(int fd, char read_write, uint8_t cmd,
  101. int size, union i2c_smbus_data *data)
  102. {
  103. struct i2c_smbus_ioctl_data args;
  104. args.read_write = read_write;
  105. args.command = cmd;
  106. args.size = size;
  107. args.data = data;
  108. return ioctl(fd, I2C_SMBUS, &args);
  109. }
  110. static int32_t i2c_smbus_read_byte(int fd)
  111. {
  112. union i2c_smbus_data data;
  113. int err;
  114. err = i2c_smbus_access(fd, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data);
  115. if (err < 0)
  116. return err;
  117. return data.byte;
  118. }
  119. #if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP
  120. static int32_t i2c_smbus_write_byte(int fd, uint8_t val)
  121. {
  122. return i2c_smbus_access(fd, I2C_SMBUS_WRITE,
  123. val, I2C_SMBUS_BYTE, NULL);
  124. }
  125. static int32_t i2c_smbus_read_byte_data(int fd, uint8_t cmd)
  126. {
  127. union i2c_smbus_data data;
  128. int err;
  129. err = i2c_smbus_access(fd, I2C_SMBUS_READ, cmd,
  130. I2C_SMBUS_BYTE_DATA, &data);
  131. if (err < 0)
  132. return err;
  133. return data.byte;
  134. }
  135. static int32_t i2c_smbus_read_word_data(int fd, uint8_t cmd)
  136. {
  137. union i2c_smbus_data data;
  138. int err;
  139. err = i2c_smbus_access(fd, I2C_SMBUS_READ, cmd,
  140. I2C_SMBUS_WORD_DATA, &data);
  141. if (err < 0)
  142. return err;
  143. return data.word;
  144. }
  145. #endif /* ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP */
  146. #if ENABLE_I2CSET
  147. static int32_t i2c_smbus_write_byte_data(int file,
  148. uint8_t cmd, uint8_t value)
  149. {
  150. union i2c_smbus_data data;
  151. data.byte = value;
  152. return i2c_smbus_access(file, I2C_SMBUS_WRITE, cmd,
  153. I2C_SMBUS_BYTE_DATA, &data);
  154. }
  155. static int32_t i2c_smbus_write_word_data(int file, uint8_t cmd, uint16_t value)
  156. {
  157. union i2c_smbus_data data;
  158. data.word = value;
  159. return i2c_smbus_access(file, I2C_SMBUS_WRITE, cmd,
  160. I2C_SMBUS_WORD_DATA, &data);
  161. }
  162. static int32_t i2c_smbus_write_block_data(int file, uint8_t cmd,
  163. uint8_t length, const uint8_t *values)
  164. {
  165. union i2c_smbus_data data;
  166. if (length > I2C_SMBUS_BLOCK_MAX)
  167. length = I2C_SMBUS_BLOCK_MAX;
  168. memcpy(data.block+1, values, length);
  169. data.block[0] = length;
  170. return i2c_smbus_access(file, I2C_SMBUS_WRITE, cmd,
  171. I2C_SMBUS_BLOCK_DATA, &data);
  172. }
  173. static int32_t i2c_smbus_write_i2c_block_data(int file, uint8_t cmd,
  174. uint8_t length, const uint8_t *values)
  175. {
  176. union i2c_smbus_data data;
  177. if (length > I2C_SMBUS_BLOCK_MAX)
  178. length = I2C_SMBUS_BLOCK_MAX;
  179. memcpy(data.block+1, values, length);
  180. data.block[0] = length;
  181. return i2c_smbus_access(file, I2C_SMBUS_WRITE, cmd,
  182. I2C_SMBUS_I2C_BLOCK_BROKEN, &data);
  183. }
  184. #endif /* ENABLE_I2CSET */
  185. #if ENABLE_I2CDUMP
  186. /*
  187. * Returns the number of bytes read, vals must hold at
  188. * least I2C_SMBUS_BLOCK_MAX bytes.
  189. */
  190. static int32_t i2c_smbus_read_block_data(int fd, uint8_t cmd, uint8_t *vals)
  191. {
  192. union i2c_smbus_data data;
  193. int i, err;
  194. err = i2c_smbus_access(fd, I2C_SMBUS_READ, cmd,
  195. I2C_SMBUS_BLOCK_DATA, &data);
  196. if (err < 0)
  197. return err;
  198. for (i = 1; i <= data.block[0]; i++)
  199. *vals++ = data.block[i];
  200. return data.block[0];
  201. }
  202. static int32_t i2c_smbus_read_i2c_block_data(int fd, uint8_t cmd,
  203. uint8_t len, uint8_t *vals)
  204. {
  205. union i2c_smbus_data data;
  206. int i, err;
  207. if (len > I2C_SMBUS_BLOCK_MAX)
  208. len = I2C_SMBUS_BLOCK_MAX;
  209. data.block[0] = len;
  210. err = i2c_smbus_access(fd, I2C_SMBUS_READ, cmd,
  211. len == 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN :
  212. I2C_SMBUS_I2C_BLOCK_DATA, &data);
  213. if (err < 0)
  214. return err;
  215. for (i = 1; i <= data.block[0]; i++)
  216. *vals++ = data.block[i];
  217. return data.block[0];
  218. }
  219. #endif /* ENABLE_I2CDUMP */
  220. #if ENABLE_I2CDETECT
  221. static int32_t i2c_smbus_write_quick(int fd, uint8_t val)
  222. {
  223. return i2c_smbus_access(fd, val, 0, I2C_SMBUS_QUICK, NULL);
  224. }
  225. #endif /* ENABLE_I2CDETECT */
  226. static int i2c_bus_lookup(const char *bus_str)
  227. {
  228. return xstrtou_range(bus_str, 10, 0, 0xfffff);
  229. }
  230. #if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP
  231. static int i2c_parse_bus_addr(const char *addr_str)
  232. {
  233. /* Slave address must be in range 0x03 - 0x77. */
  234. return xstrtou_range(addr_str, 16, 0x03, 0x77);
  235. }
  236. static void i2c_set_pec(int fd, int pec)
  237. {
  238. ioctl_or_perror_and_die(fd, I2C_PEC,
  239. itoptr(pec ? 1 : 0),
  240. "can't set PEC");
  241. }
  242. #endif
  243. #if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP || ENABLE_I2CTRANSFER
  244. static void i2c_set_slave_addr(int fd, int addr, int force)
  245. {
  246. ioctl_or_perror_and_die(fd, force ? I2C_SLAVE_FORCE : I2C_SLAVE,
  247. itoptr(addr),
  248. "can't set address to 0x%02x", addr);
  249. }
  250. #endif
  251. #if ENABLE_I2CGET || ENABLE_I2CSET
  252. static int i2c_parse_data_addr(const char *data_addr)
  253. {
  254. /* Data address must be an 8 bit integer. */
  255. return xstrtou_range(data_addr, 16, 0, 0xff);
  256. }
  257. #endif /* ENABLE_I2CGET || ENABLE_I2CSET */
  258. /*
  259. * Opens the device file associated with given i2c bus.
  260. *
  261. * Upstream i2c-tools also support opening devices by i2c bus name
  262. * but we drop it here for size reduction.
  263. */
  264. static int i2c_dev_open(int i2cbus)
  265. {
  266. char filename[sizeof("/dev/i2c-%d") + sizeof(int)*3];
  267. int fd;
  268. sprintf(filename, "/dev/i2c-%d", i2cbus);
  269. fd = open(filename, O_RDWR);
  270. if (fd < 0) {
  271. if (errno == ENOENT) {
  272. filename[8] = '/'; /* change to "/dev/i2c/%d" */
  273. fd = xopen(filename, O_RDWR);
  274. } else {
  275. bb_perror_msg_and_die("can't open '%s'", filename);
  276. }
  277. }
  278. return fd;
  279. }
  280. /* Size reducing helpers for xxx_check_funcs(). */
  281. static void get_funcs_matrix(int fd, unsigned long *funcs)
  282. {
  283. ioctl_or_perror_and_die(fd, I2C_FUNCS, funcs,
  284. "can't get adapter functionality matrix");
  285. }
  286. #if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP
  287. static void check_funcs_test_end(int funcs, int pec, const char *err)
  288. {
  289. if (pec && !(funcs & (I2C_FUNC_SMBUS_PEC | I2C_FUNC_I2C)))
  290. bb_simple_error_msg("warning: adapter does not support PEC");
  291. if (err)
  292. bb_error_msg_and_die(
  293. "adapter has no %s capability", err);
  294. }
  295. #endif /* ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP */
  296. /*
  297. * The below functions emit an error message and exit if the adapter doesn't
  298. * support desired functionalities.
  299. */
  300. #if ENABLE_I2CGET || ENABLE_I2CDUMP
  301. static void check_read_funcs(int fd, int mode, int data_addr, int pec)
  302. {
  303. unsigned long funcs;
  304. const char *err = NULL;
  305. get_funcs_matrix(fd, &funcs);
  306. switch (mode) {
  307. case I2C_SMBUS_BYTE:
  308. if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE)) {
  309. err = "SMBus receive byte";
  310. break;
  311. }
  312. if (data_addr >= 0 && !(funcs & I2C_FUNC_SMBUS_WRITE_BYTE))
  313. err = "SMBus send byte";
  314. break;
  315. case I2C_SMBUS_BYTE_DATA:
  316. if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE_DATA))
  317. err = "SMBus read byte";
  318. break;
  319. case I2C_SMBUS_WORD_DATA:
  320. if (!(funcs & I2C_FUNC_SMBUS_READ_WORD_DATA))
  321. err = "SMBus read word";
  322. break;
  323. #if ENABLE_I2CDUMP
  324. case I2C_SMBUS_BLOCK_DATA:
  325. if (!(funcs & I2C_FUNC_SMBUS_READ_BLOCK_DATA))
  326. err = "SMBus block read";
  327. break;
  328. case I2C_SMBUS_I2C_BLOCK_DATA:
  329. if (!(funcs & I2C_FUNC_SMBUS_READ_I2C_BLOCK))
  330. err = "I2C block read";
  331. break;
  332. #endif /* ENABLE_I2CDUMP */
  333. default:
  334. bb_simple_error_msg_and_die("internal error");
  335. }
  336. check_funcs_test_end(funcs, pec, err);
  337. }
  338. #endif /* ENABLE_I2CGET || ENABLE_I2CDUMP */
  339. #if ENABLE_I2CSET
  340. static void check_write_funcs(int fd, int mode, int pec)
  341. {
  342. unsigned long funcs;
  343. const char *err = NULL;
  344. get_funcs_matrix(fd, &funcs);
  345. switch (mode) {
  346. case I2C_SMBUS_BYTE:
  347. if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE))
  348. err = "SMBus send byte";
  349. break;
  350. case I2C_SMBUS_BYTE_DATA:
  351. if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
  352. err = "SMBus write byte";
  353. break;
  354. case I2C_SMBUS_WORD_DATA:
  355. if (!(funcs & I2C_FUNC_SMBUS_WRITE_WORD_DATA))
  356. err = "SMBus write word";
  357. break;
  358. case I2C_SMBUS_BLOCK_DATA:
  359. if (!(funcs & I2C_FUNC_SMBUS_WRITE_BLOCK_DATA))
  360. err = "SMBus block write";
  361. break;
  362. case I2C_SMBUS_I2C_BLOCK_DATA:
  363. if (!(funcs & I2C_FUNC_SMBUS_WRITE_I2C_BLOCK))
  364. err = "I2C block write";
  365. break;
  366. }
  367. check_funcs_test_end(funcs, pec, err);
  368. }
  369. #endif /* ENABLE_I2CSET */
  370. static void confirm_or_abort(void)
  371. {
  372. fprintf(stderr, "Continue? [y/N] ");
  373. if (!bb_ask_y_confirmation())
  374. bb_simple_error_msg_and_die("aborting");
  375. }
  376. /*
  377. * Return only if user confirms the action, abort otherwise.
  378. *
  379. * The messages displayed here are much less elaborate than their i2c-tools
  380. * counterparts - this is done for size reduction.
  381. */
  382. static void confirm_action(int bus_addr, int mode, int data_addr, int pec)
  383. {
  384. bb_simple_error_msg("WARNING! This program can confuse your I2C bus");
  385. /* Don't let the user break his/her EEPROMs */
  386. if (bus_addr >= 0x50 && bus_addr <= 0x57 && pec) {
  387. bb_simple_error_msg_and_die("this is I2C not smbus - using PEC on I2C "
  388. "devices may result in data loss, aborting");
  389. }
  390. if (mode == I2C_SMBUS_BYTE && data_addr >= 0 && pec)
  391. bb_simple_error_msg("WARNING! May interpret a write byte command "
  392. "with PEC as a write byte data command");
  393. if (pec)
  394. bb_simple_error_msg("PEC checking enabled");
  395. confirm_or_abort();
  396. }
  397. #if ENABLE_I2CGET
  398. //usage:#define i2cget_trivial_usage
  399. //usage: "[-fy] BUS CHIP-ADDRESS [DATA-ADDRESS [MODE]]"
  400. //usage:#define i2cget_full_usage "\n\n"
  401. //usage: "Read from I2C/SMBus chip registers"
  402. //usage: "\n"
  403. //usage: "\n I2CBUS I2C bus number"
  404. //usage: "\n ADDRESS 0x03-0x77"
  405. //usage: "\nMODE is:"
  406. //usage: "\n b Read byte data (default)"
  407. //usage: "\n w Read word data"
  408. //usage: "\n c Write byte/read byte"
  409. //usage: "\n Append p for SMBus PEC"
  410. //usage: "\n"
  411. //usage: "\n -f Force access"
  412. //usage: "\n -y Disable interactive mode"
  413. int i2cget_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  414. int i2cget_main(int argc UNUSED_PARAM, char **argv)
  415. {
  416. const unsigned opt_f = (1 << 0), opt_y = (1 << 1);
  417. int bus_num, bus_addr, data_addr = -1, status;
  418. int mode = I2C_SMBUS_BYTE, pec = 0, fd;
  419. unsigned opts;
  420. opts = getopt32(argv, "^" "fy" "\0" "-2:?4"/*from 2 to 4 args*/);
  421. argv += optind;
  422. bus_num = i2c_bus_lookup(argv[0]);
  423. bus_addr = i2c_parse_bus_addr(argv[1]);
  424. if (argv[2]) {
  425. data_addr = i2c_parse_data_addr(argv[2]);
  426. mode = I2C_SMBUS_BYTE_DATA;
  427. if (argv[3]) {
  428. switch (argv[3][0]) {
  429. case 'b': /* Already set */ break;
  430. case 'w': mode = I2C_SMBUS_WORD_DATA; break;
  431. case 'c': mode = I2C_SMBUS_BYTE; break;
  432. default:
  433. bb_simple_error_msg("invalid mode");
  434. bb_show_usage();
  435. }
  436. pec = argv[3][1] == 'p';
  437. }
  438. }
  439. fd = i2c_dev_open(bus_num);
  440. check_read_funcs(fd, mode, data_addr, pec);
  441. i2c_set_slave_addr(fd, bus_addr, opts & opt_f);
  442. if (!(opts & opt_y))
  443. confirm_action(bus_addr, mode, data_addr, pec);
  444. if (pec)
  445. i2c_set_pec(fd, 1);
  446. switch (mode) {
  447. case I2C_SMBUS_BYTE:
  448. if (data_addr >= 0) {
  449. status = i2c_smbus_write_byte(fd, data_addr);
  450. if (status < 0)
  451. bb_simple_error_msg("warning - write failed");
  452. }
  453. status = i2c_smbus_read_byte(fd);
  454. break;
  455. case I2C_SMBUS_WORD_DATA:
  456. status = i2c_smbus_read_word_data(fd, data_addr);
  457. break;
  458. default: /* I2C_SMBUS_BYTE_DATA */
  459. status = i2c_smbus_read_byte_data(fd, data_addr);
  460. }
  461. close(fd);
  462. if (status < 0)
  463. bb_simple_perror_msg_and_die("read failed");
  464. printf("0x%0*x\n", mode == I2C_SMBUS_WORD_DATA ? 4 : 2, status);
  465. return 0;
  466. }
  467. #endif /* ENABLE_I2CGET */
  468. #if ENABLE_I2CSET
  469. //usage:#define i2cset_trivial_usage
  470. //usage: "[-fy] [-m MASK] BUS CHIP-ADDRESS DATA-ADDRESS [VALUE] ... [MODE]"
  471. //usage:#define i2cset_full_usage "\n\n"
  472. //usage: "Set I2C registers"
  473. //usage: "\n"
  474. //usage: "\n I2CBUS I2C bus number"
  475. //usage: "\n ADDRESS 0x03-0x77"
  476. //usage: "\nMODE is:"
  477. //usage: "\n c Byte, no value"
  478. //usage: "\n b Byte data (default)"
  479. //usage: "\n w Word data"
  480. //usage: "\n i I2C block data"
  481. //usage: "\n s SMBus block data"
  482. //usage: "\n Append p for SMBus PEC"
  483. //usage: "\n"
  484. //usage: "\n -f Force access"
  485. //usage: "\n -y Disable interactive mode"
  486. //usage: "\n -r Read back and compare the result"
  487. //usage: "\n -m MASK Mask specifying which bits to write"
  488. int i2cset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  489. int i2cset_main(int argc, char **argv)
  490. {
  491. const unsigned opt_f = (1 << 0), opt_y = (1 << 1),
  492. opt_m = (1 << 2), opt_r = (1 << 3);
  493. int bus_num, bus_addr, data_addr, mode = I2C_SMBUS_BYTE, pec = 0;
  494. int val, blen, mask, fd, status;
  495. unsigned char block[I2C_SMBUS_BLOCK_MAX];
  496. char *opt_m_arg = NULL;
  497. unsigned opts;
  498. opts = getopt32(argv, "^"
  499. "fym:r"
  500. "\0" "-3", /* minimum 3 args */
  501. &opt_m_arg
  502. );
  503. argv += optind;
  504. argc -= optind;
  505. argc--; /* now argv[argc] is last arg */
  506. bus_num = i2c_bus_lookup(argv[0]);
  507. bus_addr = i2c_parse_bus_addr(argv[1]);
  508. data_addr = i2c_parse_data_addr(argv[2]);
  509. if (argv[3]) {
  510. if (!argv[4] && argv[3][0] != 'c') {
  511. mode = I2C_SMBUS_BYTE_DATA; /* Implicit b */
  512. } else {
  513. switch (argv[argc][0]) {
  514. case 'c': /* Already set */
  515. break;
  516. case 'b': mode = I2C_SMBUS_BYTE_DATA;
  517. break;
  518. case 'w': mode = I2C_SMBUS_WORD_DATA;
  519. break;
  520. case 's': mode = I2C_SMBUS_BLOCK_DATA;
  521. break;
  522. case 'i': mode = I2C_SMBUS_I2C_BLOCK_DATA;
  523. break;
  524. default:
  525. bb_simple_error_msg("invalid mode");
  526. bb_show_usage();
  527. }
  528. pec = (argv[argc][1] == 'p');
  529. if (mode == I2C_SMBUS_BLOCK_DATA
  530. || mode == I2C_SMBUS_I2C_BLOCK_DATA
  531. ) {
  532. if (pec && mode == I2C_SMBUS_I2C_BLOCK_DATA)
  533. bb_simple_error_msg_and_die(
  534. "PEC not supported for I2C "
  535. "block writes");
  536. if (opts & opt_m)
  537. bb_simple_error_msg_and_die(
  538. "mask not supported for block "
  539. "writes");
  540. }
  541. }
  542. }
  543. /* Prepare the value(s) to be written according to current mode. */
  544. mask = 0;
  545. blen = 0;
  546. switch (mode) {
  547. case I2C_SMBUS_BYTE_DATA:
  548. val = xstrtou_range(argv[3], 0, 0, 0xff);
  549. break;
  550. case I2C_SMBUS_WORD_DATA:
  551. val = xstrtou_range(argv[3], 0, 0, 0xffff);
  552. break;
  553. case I2C_SMBUS_BLOCK_DATA:
  554. case I2C_SMBUS_I2C_BLOCK_DATA:
  555. for (blen = 3; blen < argc; blen++)
  556. block[blen - 3] = xstrtou_range(argv[blen], 0, 0, 0xff);
  557. blen -= 3;
  558. val = -1;
  559. break;
  560. default:
  561. val = -1;
  562. break;
  563. }
  564. if (opts & opt_m) {
  565. mask = xstrtou_range(opt_m_arg, 0, 0,
  566. (mode == I2C_SMBUS_BYTE ||
  567. mode == I2C_SMBUS_BYTE_DATA) ? 0xff : 0xffff);
  568. }
  569. fd = i2c_dev_open(bus_num);
  570. check_write_funcs(fd, mode, pec);
  571. i2c_set_slave_addr(fd, bus_addr, opts & opt_f);
  572. if (!(opts & opt_y))
  573. confirm_action(bus_addr, mode, data_addr, pec);
  574. /*
  575. * If we're using mask - read the current value here and adjust the
  576. * value to be written.
  577. */
  578. if (opts & opt_m) {
  579. int tmpval;
  580. switch (mode) {
  581. case I2C_SMBUS_BYTE:
  582. tmpval = i2c_smbus_read_byte(fd);
  583. break;
  584. case I2C_SMBUS_WORD_DATA:
  585. tmpval = i2c_smbus_read_word_data(fd, data_addr);
  586. break;
  587. default:
  588. tmpval = i2c_smbus_read_byte_data(fd, data_addr);
  589. }
  590. if (tmpval < 0)
  591. bb_simple_perror_msg_and_die("can't read old value");
  592. val = (val & mask) | (tmpval & ~mask);
  593. if (!(opts & opt_y)) {
  594. bb_error_msg("old value 0x%0*x, write mask "
  595. "0x%0*x, will write 0x%0*x to register "
  596. "0x%02x",
  597. mode == I2C_SMBUS_WORD_DATA ? 4 : 2, tmpval,
  598. mode == I2C_SMBUS_WORD_DATA ? 4 : 2, mask,
  599. mode == I2C_SMBUS_WORD_DATA ? 4 : 2, val,
  600. data_addr);
  601. confirm_or_abort();
  602. }
  603. }
  604. if (pec)
  605. i2c_set_pec(fd, 1);
  606. switch (mode) {
  607. case I2C_SMBUS_BYTE:
  608. status = i2c_smbus_write_byte(fd, data_addr);
  609. break;
  610. case I2C_SMBUS_WORD_DATA:
  611. status = i2c_smbus_write_word_data(fd, data_addr, val);
  612. break;
  613. case I2C_SMBUS_BLOCK_DATA:
  614. status = i2c_smbus_write_block_data(fd, data_addr,
  615. blen, block);
  616. break;
  617. case I2C_SMBUS_I2C_BLOCK_DATA:
  618. status = i2c_smbus_write_i2c_block_data(fd, data_addr,
  619. blen, block);
  620. break;
  621. default: /* I2C_SMBUS_BYTE_DATA */
  622. status = i2c_smbus_write_byte_data(fd, data_addr, val);
  623. break;
  624. }
  625. if (status < 0)
  626. bb_simple_perror_msg_and_die("write failed");
  627. if (pec)
  628. i2c_set_pec(fd, 0); /* Clear PEC. */
  629. /* No readback required - we're done. */
  630. if (!(opts & opt_r))
  631. return 0;
  632. switch (mode) {
  633. case I2C_SMBUS_BYTE:
  634. status = i2c_smbus_read_byte(fd);
  635. val = data_addr;
  636. break;
  637. case I2C_SMBUS_WORD_DATA:
  638. status = i2c_smbus_read_word_data(fd, data_addr);
  639. break;
  640. default: /* I2C_SMBUS_BYTE_DATA */
  641. status = i2c_smbus_read_byte_data(fd, data_addr);
  642. }
  643. if (status < 0) {
  644. puts("Warning - readback failed");
  645. } else
  646. if (status != val) {
  647. printf("Warning - data mismatch - wrote "
  648. "0x%0*x, read back 0x%0*x\n",
  649. mode == I2C_SMBUS_WORD_DATA ? 4 : 2, val,
  650. mode == I2C_SMBUS_WORD_DATA ? 4 : 2, status);
  651. } else {
  652. printf("Value 0x%0*x written, readback matched\n",
  653. mode == I2C_SMBUS_WORD_DATA ? 4 : 2, val);
  654. }
  655. return 0;
  656. }
  657. #endif /* ENABLE_I2CSET */
  658. #if ENABLE_I2CDUMP
  659. static int read_block_data(int buf_fd, int mode, int *block)
  660. {
  661. uint8_t cblock[I2C_SMBUS_BLOCK_MAX + I2CDUMP_NUM_REGS];
  662. int res, blen = 0, tmp, i;
  663. if (mode == I2C_SMBUS_BLOCK_DATA) {
  664. blen = i2c_smbus_read_block_data(buf_fd, 0, cblock);
  665. if (blen <= 0)
  666. goto fail;
  667. } else {
  668. for (res = 0; res < I2CDUMP_NUM_REGS; res += tmp) {
  669. tmp = i2c_smbus_read_i2c_block_data(
  670. buf_fd, res, I2C_SMBUS_BLOCK_MAX,
  671. cblock + res);
  672. if (tmp <= 0) {
  673. blen = tmp;
  674. goto fail;
  675. }
  676. }
  677. if (res >= I2CDUMP_NUM_REGS)
  678. res = I2CDUMP_NUM_REGS;
  679. for (i = 0; i < res; i++)
  680. block[i] = cblock[i];
  681. if (mode != I2C_SMBUS_BLOCK_DATA)
  682. for (i = res; i < I2CDUMP_NUM_REGS; i++)
  683. block[i] = -1;
  684. }
  685. return blen;
  686. fail:
  687. bb_error_msg_and_die("block read failed: %d", blen);
  688. }
  689. /* Dump all but word data. */
  690. static void dump_data(int bus_fd, int mode, unsigned first,
  691. unsigned last, int *block, int blen)
  692. {
  693. int i, j, res;
  694. puts(" 0 1 2 3 4 5 6 7 8 9 a b c d e f"
  695. " 0123456789abcdef");
  696. for (i = 0; i < I2CDUMP_NUM_REGS; i += 0x10) {
  697. if (mode == I2C_SMBUS_BLOCK_DATA && i >= blen)
  698. break;
  699. if (i/16 < first/16)
  700. continue;
  701. if (i/16 > last/16)
  702. break;
  703. printf("%02x: ", i);
  704. for (j = 0; j < 16; j++) {
  705. fflush_all();
  706. /* Skip unwanted registers */
  707. if (i+j < first || i+j > last) {
  708. printf(" ");
  709. if (mode == I2C_SMBUS_WORD_DATA) {
  710. printf(" ");
  711. j++;
  712. }
  713. continue;
  714. }
  715. switch (mode) {
  716. case I2C_SMBUS_BYTE_DATA:
  717. res = i2c_smbus_read_byte_data(bus_fd, i+j);
  718. block[i+j] = res;
  719. break;
  720. case I2C_SMBUS_WORD_DATA:
  721. res = i2c_smbus_read_word_data(bus_fd, i+j);
  722. if (res < 0) {
  723. block[i+j] = res;
  724. block[i+j+1] = res;
  725. } else {
  726. block[i+j] = res & 0xff;
  727. block[i+j+1] = res >> 8;
  728. }
  729. break;
  730. case I2C_SMBUS_BYTE:
  731. res = i2c_smbus_read_byte(bus_fd);
  732. block[i+j] = res;
  733. break;
  734. default:
  735. res = block[i+j];
  736. }
  737. if (mode == I2C_SMBUS_BLOCK_DATA &&
  738. i+j >= blen) {
  739. printf(" ");
  740. } else if (res < 0) {
  741. printf("XX ");
  742. if (mode == I2C_SMBUS_WORD_DATA)
  743. printf("XX ");
  744. } else {
  745. printf("%02x ", block[i+j]);
  746. if (mode == I2C_SMBUS_WORD_DATA)
  747. printf("%02x ", block[i+j+1]);
  748. }
  749. if (mode == I2C_SMBUS_WORD_DATA)
  750. j++;
  751. }
  752. printf(" ");
  753. for (j = 0; j < 16; j++) {
  754. if (mode == I2C_SMBUS_BLOCK_DATA && i+j >= blen)
  755. break;
  756. /* Skip unwanted registers */
  757. if (i+j < first || i+j > last) {
  758. bb_putchar(' ');
  759. continue;
  760. }
  761. res = block[i+j];
  762. if (res < 0) {
  763. bb_putchar('X');
  764. } else if (res == 0x00 || res == 0xff) {
  765. bb_putchar('.');
  766. } else if (res < 32 || res >= 127) {
  767. bb_putchar('?');
  768. } else {
  769. bb_putchar(res);
  770. }
  771. }
  772. bb_putchar('\n');
  773. }
  774. }
  775. static void dump_word_data(int bus_fd, unsigned first, unsigned last)
  776. {
  777. int i, j, rv;
  778. /* Word data. */
  779. puts(" 0,8 1,9 2,a 3,b 4,c 5,d 6,e 7,f");
  780. for (i = 0; i < 256; i += 8) {
  781. if (i/8 < first/8)
  782. continue;
  783. if (i/8 > last/8)
  784. break;
  785. printf("%02x: ", i);
  786. for (j = 0; j < 8; j++) {
  787. /* Skip unwanted registers. */
  788. if (i+j < first || i+j > last) {
  789. printf(" ");
  790. continue;
  791. }
  792. rv = i2c_smbus_read_word_data(bus_fd, i+j);
  793. if (rv < 0)
  794. printf("XXXX ");
  795. else
  796. printf("%04x ", rv & 0xffff);
  797. }
  798. bb_putchar('\n');
  799. }
  800. }
  801. //usage:#define i2cdump_trivial_usage
  802. //usage: "[-fy] [-r FIRST-LAST] BUS ADDR [MODE]"
  803. //usage:#define i2cdump_full_usage "\n\n"
  804. //usage: "Examine I2C registers"
  805. //usage: "\n"
  806. //usage: "\n I2CBUS I2C bus number"
  807. //usage: "\n ADDRESS 0x03-0x77"
  808. //usage: "\nMODE is:"
  809. //usage: "\n b Byte (default)"
  810. //usage: "\n w Word"
  811. //usage: "\n W Word on even register addresses"
  812. //usage: "\n i I2C block"
  813. //usage: "\n s SMBus block"
  814. //usage: "\n c Consecutive byte"
  815. //usage: "\n Append p for SMBus PEC"
  816. //usage: "\n"
  817. //usage: "\n -f Force access"
  818. //usage: "\n -y Disable interactive mode"
  819. //usage: "\n -r Limit the number of registers being accessed"
  820. int i2cdump_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  821. int i2cdump_main(int argc UNUSED_PARAM, char **argv)
  822. {
  823. const unsigned opt_f = (1 << 0), opt_y = (1 << 1),
  824. opt_r = (1 << 2);
  825. int bus_num, bus_addr, mode = I2C_SMBUS_BYTE_DATA, even = 0, pec = 0;
  826. unsigned first = 0x00, last = 0xff, opts;
  827. int block[I2CDUMP_NUM_REGS];
  828. char *opt_r_str, *dash;
  829. int fd, res;
  830. opts = getopt32(argv, "^"
  831. "fyr:"
  832. "\0" "-2:?3" /* from 2 to 3 args */,
  833. &opt_r_str
  834. );
  835. argv += optind;
  836. bus_num = i2c_bus_lookup(argv[0]);
  837. bus_addr = i2c_parse_bus_addr(argv[1]);
  838. if (argv[2]) {
  839. switch (argv[2][0]) {
  840. case 'b': /* Already set. */ break;
  841. case 'c': mode = I2C_SMBUS_BYTE; break;
  842. case 'w': mode = I2C_SMBUS_WORD_DATA; break;
  843. case 'W':
  844. mode = I2C_SMBUS_WORD_DATA;
  845. even = 1;
  846. break;
  847. case 's': mode = I2C_SMBUS_BLOCK_DATA; break;
  848. case 'i': mode = I2C_SMBUS_I2C_BLOCK_DATA; break;
  849. default:
  850. bb_simple_error_msg_and_die("invalid mode");
  851. }
  852. if (argv[2][1] == 'p') {
  853. if (argv[2][0] == 'W' || argv[2][0] == 'i') {
  854. bb_simple_error_msg_and_die(
  855. "pec not supported for -W and -i");
  856. } else {
  857. pec = 1;
  858. }
  859. }
  860. }
  861. if (opts & opt_r) {
  862. first = strtol(opt_r_str, &dash, 0);
  863. if (dash == opt_r_str || *dash != '-' || first > 0xff)
  864. bb_simple_error_msg_and_die("invalid range");
  865. last = xstrtou_range(++dash, 0, first, 0xff);
  866. /* Range is not available for every mode. */
  867. switch (mode) {
  868. case I2C_SMBUS_BYTE:
  869. case I2C_SMBUS_BYTE_DATA:
  870. break;
  871. case I2C_SMBUS_WORD_DATA:
  872. if (!even || (!(first % 2) && last % 2))
  873. break;
  874. /* Fall through */
  875. default:
  876. bb_simple_error_msg_and_die(
  877. "range not compatible with selected mode");
  878. }
  879. }
  880. fd = i2c_dev_open(bus_num);
  881. check_read_funcs(fd, mode, -1 /* data_addr */, pec);
  882. i2c_set_slave_addr(fd, bus_addr, opts & opt_f);
  883. if (pec)
  884. i2c_set_pec(fd, 1);
  885. if (!(opts & opt_y))
  886. confirm_action(bus_addr, mode, -1 /* data_addr */, pec);
  887. /* All but word data. */
  888. if (mode != I2C_SMBUS_WORD_DATA || even) {
  889. int blen = 0;
  890. if (mode == I2C_SMBUS_BLOCK_DATA || mode == I2C_SMBUS_I2C_BLOCK_DATA)
  891. blen = read_block_data(fd, mode, block);
  892. if (mode == I2C_SMBUS_BYTE) {
  893. res = i2c_smbus_write_byte(fd, first);
  894. if (res < 0)
  895. bb_simple_perror_msg_and_die("write start address");
  896. }
  897. dump_data(fd, mode, first, last, block, blen);
  898. } else {
  899. dump_word_data(fd, first, last);
  900. }
  901. return 0;
  902. }
  903. #endif /* ENABLE_I2CDUMP */
  904. #if ENABLE_I2CDETECT
  905. enum adapter_type {
  906. ADT_DUMMY = 0,
  907. ADT_ISA,
  908. ADT_I2C,
  909. ADT_SMBUS,
  910. };
  911. struct adap_desc {
  912. const char *funcs;
  913. const char *algo;
  914. };
  915. static const struct adap_desc adap_descs[] ALIGN_PTR = {
  916. { .funcs = "dummy", .algo = "Dummy bus", },
  917. { .funcs = "isa", .algo = "ISA bus", },
  918. { .funcs = "i2c", .algo = "I2C adapter", },
  919. { .funcs = "smbus", .algo = "SMBus adapter", },
  920. };
  921. struct i2c_func {
  922. long value;
  923. const char* name;
  924. };
  925. static const struct i2c_func i2c_funcs_tab[] ALIGN_PTR = {
  926. { .value = I2C_FUNC_I2C,
  927. .name = "I2C" },
  928. { .value = I2C_FUNC_SMBUS_QUICK,
  929. .name = "SMBus quick command" },
  930. { .value = I2C_FUNC_SMBUS_WRITE_BYTE,
  931. .name = "SMBus send byte" },
  932. { .value = I2C_FUNC_SMBUS_READ_BYTE,
  933. .name = "SMBus receive byte" },
  934. { .value = I2C_FUNC_SMBUS_WRITE_BYTE_DATA,
  935. .name = "SMBus write byte" },
  936. { .value = I2C_FUNC_SMBUS_READ_BYTE_DATA,
  937. .name = "SMBus read byte" },
  938. { .value = I2C_FUNC_SMBUS_WRITE_WORD_DATA,
  939. .name = "SMBus write word" },
  940. { .value = I2C_FUNC_SMBUS_READ_WORD_DATA,
  941. .name = "SMBus read word" },
  942. { .value = I2C_FUNC_SMBUS_PROC_CALL,
  943. .name = "SMBus process call" },
  944. { .value = I2C_FUNC_SMBUS_WRITE_BLOCK_DATA,
  945. .name = "SMBus block write" },
  946. { .value = I2C_FUNC_SMBUS_READ_BLOCK_DATA,
  947. .name = "SMBus block read" },
  948. { .value = I2C_FUNC_SMBUS_BLOCK_PROC_CALL,
  949. .name = "SMBus block process call" },
  950. { .value = I2C_FUNC_SMBUS_PEC,
  951. .name = "SMBus PEC" },
  952. { .value = I2C_FUNC_SMBUS_WRITE_I2C_BLOCK,
  953. .name = "I2C block write" },
  954. { .value = I2C_FUNC_SMBUS_READ_I2C_BLOCK,
  955. .name = "I2C block read" },
  956. { .value = 0, .name = NULL }
  957. };
  958. static enum adapter_type i2cdetect_get_funcs(int bus)
  959. {
  960. enum adapter_type ret;
  961. unsigned long funcs;
  962. int fd;
  963. fd = i2c_dev_open(bus);
  964. get_funcs_matrix(fd, &funcs);
  965. if (funcs & I2C_FUNC_I2C)
  966. ret = ADT_I2C;
  967. else if (funcs & (I2C_FUNC_SMBUS_BYTE |
  968. I2C_FUNC_SMBUS_BYTE_DATA |
  969. I2C_FUNC_SMBUS_WORD_DATA))
  970. ret = ADT_SMBUS;
  971. else
  972. ret = ADT_DUMMY;
  973. close(fd);
  974. return ret;
  975. }
  976. static void NORETURN list_i2c_busses_and_exit(void)
  977. {
  978. const char *const i2cdev_path = "/sys/class/i2c-dev";
  979. char path[NAME_MAX], name[128];
  980. struct dirent *de, *subde;
  981. enum adapter_type adt;
  982. DIR *dir, *subdir;
  983. int rv, bus;
  984. char *pos;
  985. FILE *fp;
  986. /*
  987. * XXX Upstream i2cdetect also looks for i2c bus info in /proc/bus/i2c,
  988. * but we won't bother since it's only useful on older kernels (before
  989. * 2.6.5). We expect sysfs to be present and mounted at /sys/.
  990. */
  991. dir = xopendir(i2cdev_path);
  992. while ((de = readdir(dir))) {
  993. if (de->d_name[0] == '.')
  994. continue;
  995. /* Simple version for ISA chips. */
  996. snprintf(path, NAME_MAX, "%s/%s/name",
  997. i2cdev_path, de->d_name);
  998. fp = fopen(path, "r");
  999. if (fp == NULL) {
  1000. snprintf(path, NAME_MAX,
  1001. "%s/%s/device/name",
  1002. i2cdev_path, de->d_name);
  1003. fp = fopen(path, "r");
  1004. }
  1005. /* Non-ISA chips require the hard-way. */
  1006. if (fp == NULL) {
  1007. snprintf(path, NAME_MAX,
  1008. "%s/%s/device/name",
  1009. i2cdev_path, de->d_name);
  1010. subdir = opendir(path);
  1011. if (subdir == NULL)
  1012. continue;
  1013. while ((subde = readdir(subdir))) {
  1014. if (subde->d_name[0] == '.')
  1015. continue;
  1016. if (is_prefixed_with(subde->d_name, "i2c-")) {
  1017. snprintf(path, NAME_MAX,
  1018. "%s/%s/device/%s/name",
  1019. i2cdev_path, de->d_name,
  1020. subde->d_name);
  1021. fp = fopen(path, "r");
  1022. break;
  1023. }
  1024. }
  1025. }
  1026. if (fp != NULL) {
  1027. /*
  1028. * Get the rest of the info and display a line
  1029. * for a single bus.
  1030. */
  1031. memset(name, 0, sizeof(name));
  1032. pos = fgets(name, sizeof(name), fp);
  1033. fclose(fp);
  1034. if (pos == NULL)
  1035. continue;
  1036. pos = strchr(name, '\n');
  1037. if (pos != NULL)
  1038. *pos = '\0';
  1039. rv = sscanf(de->d_name, "i2c-%d", &bus);
  1040. if (rv != 1)
  1041. continue;
  1042. if (is_prefixed_with(name, "ISA"))
  1043. adt = ADT_ISA;
  1044. else
  1045. adt = i2cdetect_get_funcs(bus);
  1046. printf(
  1047. "i2c-%d\t%-10s\t%-32s\t%s\n",
  1048. bus, adap_descs[adt].funcs,
  1049. name, adap_descs[adt].algo);
  1050. }
  1051. }
  1052. exit(EXIT_SUCCESS);
  1053. }
  1054. static void NORETURN no_support(const char *cmd)
  1055. {
  1056. bb_error_msg_and_die("bus doesn't support %s", cmd);
  1057. }
  1058. static void will_skip(const char *cmd)
  1059. {
  1060. bb_error_msg(
  1061. "warning: can't use %s command, "
  1062. "will skip some addresses", cmd);
  1063. }
  1064. //usage:#define i2cdetect_trivial_usage
  1065. //usage: "-l | -F I2CBUS | [-ya] [-q|-r] I2CBUS [FIRST LAST]"
  1066. //usage:#define i2cdetect_full_usage "\n\n"
  1067. //usage: "Detect I2C chips"
  1068. //usage: "\n"
  1069. //usage: "\n -l List installed buses"
  1070. //usage: "\n -F BUS# List functionalities on this bus"
  1071. //usage: "\n -y Disable interactive mode"
  1072. //usage: "\n -a Force scanning of non-regular addresses"
  1073. //usage: "\n -q Use smbus quick write commands for probing (default)"
  1074. //usage: "\n -r Use smbus read byte commands for probing"
  1075. //usage: "\n FIRST and LAST limit probing range"
  1076. int i2cdetect_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  1077. int i2cdetect_main(int argc UNUSED_PARAM, char **argv)
  1078. {
  1079. const unsigned opt_y = (1 << 0), opt_a = (1 << 1),
  1080. opt_q = (1 << 2), opt_r = (1 << 3),
  1081. opt_F = (1 << 4), opt_l = (1 << 5);
  1082. int fd, bus_num, i, j, mode = I2CDETECT_MODE_AUTO, status, cmd;
  1083. unsigned first = 0x03, last = 0x77, opts;
  1084. unsigned long funcs;
  1085. opts = getopt32(argv, "^"
  1086. "yaqrFl"
  1087. "\0"
  1088. "q--r:r--q:"/*mutually exclusive*/
  1089. "?3"/*up to 3 args*/
  1090. );
  1091. argv += optind;
  1092. if (opts & opt_l)
  1093. list_i2c_busses_and_exit();
  1094. if (!argv[0])
  1095. bb_show_usage();
  1096. bus_num = i2c_bus_lookup(argv[0]);
  1097. fd = i2c_dev_open(bus_num);
  1098. get_funcs_matrix(fd, &funcs);
  1099. if (opts & opt_F) {
  1100. /* Only list the functionalities. */
  1101. printf("Functionalities implemented by bus #%d\n", bus_num);
  1102. for (i = 0; i2c_funcs_tab[i].value; i++) {
  1103. printf("%-32s %s\n", i2c_funcs_tab[i].name,
  1104. funcs & i2c_funcs_tab[i].value ? "yes" : "no");
  1105. }
  1106. return EXIT_SUCCESS;
  1107. }
  1108. if (opts & opt_r)
  1109. mode = I2CDETECT_MODE_READ;
  1110. else if (opts & opt_q)
  1111. mode = I2CDETECT_MODE_QUICK;
  1112. if (opts & opt_a) {
  1113. first = 0x00;
  1114. last = 0x7f;
  1115. }
  1116. /* Read address range. */
  1117. if (argv[1]) {
  1118. first = xstrtou_range(argv[1], 16, first, last);
  1119. if (argv[2])
  1120. last = xstrtou_range(argv[2], 16, first, last);
  1121. }
  1122. if (!(funcs & (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_READ_BYTE))) {
  1123. no_support("detection commands");
  1124. } else
  1125. if (mode == I2CDETECT_MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_QUICK)) {
  1126. no_support("SMBus quick write");
  1127. } else
  1128. if (mode == I2CDETECT_MODE_READ && !(funcs & I2C_FUNC_SMBUS_READ_BYTE)) {
  1129. no_support("SMBus receive byte");
  1130. }
  1131. if (mode == I2CDETECT_MODE_AUTO) {
  1132. if (!(funcs & I2C_FUNC_SMBUS_QUICK))
  1133. will_skip("SMBus quick write");
  1134. if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE))
  1135. will_skip("SMBus receive byte");
  1136. }
  1137. if (!(opts & opt_y))
  1138. confirm_action(-1, -1, -1, 0);
  1139. puts(" 0 1 2 3 4 5 6 7 8 9 a b c d e f");
  1140. for (i = 0; i < 128; i += 16) {
  1141. printf("%02x: ", i);
  1142. for (j = 0; j < 16; j++) {
  1143. fflush_all();
  1144. cmd = mode;
  1145. if (mode == I2CDETECT_MODE_AUTO) {
  1146. if ((i+j >= 0x30 && i+j <= 0x37) ||
  1147. (i+j >= 0x50 && i+j <= 0x5F))
  1148. cmd = I2CDETECT_MODE_READ;
  1149. else
  1150. cmd = I2CDETECT_MODE_QUICK;
  1151. }
  1152. /* Skip unwanted addresses. */
  1153. if (i+j < first
  1154. || i+j > last
  1155. || (cmd == I2CDETECT_MODE_READ && !(funcs & I2C_FUNC_SMBUS_READ_BYTE))
  1156. || (cmd == I2CDETECT_MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_QUICK)))
  1157. {
  1158. printf(" ");
  1159. continue;
  1160. }
  1161. status = ioctl(fd, I2C_SLAVE, itoptr(i + j));
  1162. if (status < 0) {
  1163. if (errno == EBUSY) {
  1164. printf("UU ");
  1165. continue;
  1166. }
  1167. bb_perror_msg_and_die(
  1168. "can't set address to 0x%02x", i + j);
  1169. }
  1170. switch (cmd) {
  1171. case I2CDETECT_MODE_READ:
  1172. /*
  1173. * This is known to lock SMBus on various
  1174. * write-only chips (mainly clock chips).
  1175. */
  1176. status = i2c_smbus_read_byte(fd);
  1177. break;
  1178. default: /* I2CDETECT_MODE_QUICK: */
  1179. /*
  1180. * This is known to corrupt the Atmel
  1181. * AT24RF08 EEPROM.
  1182. */
  1183. status = i2c_smbus_write_quick(fd,
  1184. I2C_SMBUS_WRITE);
  1185. break;
  1186. }
  1187. if (status < 0)
  1188. printf("-- ");
  1189. else
  1190. printf("%02x ", i+j);
  1191. }
  1192. bb_putchar('\n');
  1193. }
  1194. return 0;
  1195. }
  1196. #endif /* ENABLE_I2CDETECT */
  1197. #if ENABLE_I2CTRANSFER
  1198. static void check_i2c_func(int fd)
  1199. {
  1200. unsigned long funcs;
  1201. get_funcs_matrix(fd, &funcs);
  1202. if (!(funcs & I2C_FUNC_I2C))
  1203. bb_simple_error_msg_and_die("adapter does not support I2C transfers");
  1204. }
  1205. //usage:#define i2ctransfer_trivial_usage
  1206. //usage: "[-fay] I2CBUS {rLENGTH[@ADDR] | wLENGTH[@ADDR] DATA...}..."
  1207. //usage:#define i2ctransfer_full_usage "\n\n"
  1208. //usage: "Read/write I2C data in one transfer"
  1209. //usage: "\n"
  1210. //usage: "\n -f Force access to busy addresses"
  1211. //usage: "\n -a Force access to non-regular addresses"
  1212. //usage: "\n -y Disable interactive mode"
  1213. int i2ctransfer_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  1214. int i2ctransfer_main(int argc UNUSED_PARAM, char **argv)
  1215. {
  1216. enum {
  1217. opt_f = (1 << 0),
  1218. opt_y = (1 << 1),
  1219. opt_a = (1 << 2),
  1220. };
  1221. int bus_num, bus_addr;
  1222. int fd;
  1223. unsigned opts, first, last;
  1224. int nmsgs, nmsgs_sent, i;
  1225. struct i2c_msg msgs[I2C_RDWR_IOCTL_MAX_MSGS];
  1226. struct i2c_rdwr_ioctl_data rdwr;
  1227. memset(msgs, 0, sizeof(msgs));
  1228. opts = getopt32(argv, "^"
  1229. "fya"
  1230. "\0" "-2" /* minimum 2 args */
  1231. );
  1232. first = 0x03;
  1233. last = 0x77;
  1234. if (opts & opt_a) {
  1235. first = 0x00;
  1236. last = 0x7f;
  1237. }
  1238. argv += optind;
  1239. bus_num = i2c_bus_lookup(argv[0]);
  1240. fd = i2c_dev_open(bus_num);
  1241. check_i2c_func(fd);
  1242. bus_addr = -1;
  1243. nmsgs = 0;
  1244. while (*++argv) {
  1245. char *arg_ptr;
  1246. unsigned len;
  1247. uint16_t flags;
  1248. char *end;
  1249. if (nmsgs >= I2C_RDWR_IOCTL_MAX_MSGS)
  1250. bb_simple_error_msg_and_die("too many messages, max: "I2C_RDWR_IOCTL_MAX_MSGS_STR);
  1251. flags = 0;
  1252. arg_ptr = *argv;
  1253. switch (*arg_ptr++) {
  1254. case 'r': flags |= I2C_M_RD; break;
  1255. case 'w': break;
  1256. default:
  1257. bb_show_usage();
  1258. }
  1259. end = strchr(arg_ptr, '@');
  1260. if (end) *end = '\0';
  1261. len = xstrtou_range(arg_ptr, 0, 0, 0xffff);
  1262. if (end) {
  1263. bus_addr = xstrtou_range(end + 1, 0, first, last);
  1264. i2c_set_slave_addr(fd, bus_addr, (opts & opt_f));
  1265. } else {
  1266. /* Reuse last address if possible */
  1267. if (bus_addr < 0)
  1268. bb_error_msg_and_die("no address given in '%s'", *argv);
  1269. }
  1270. msgs[nmsgs].addr = bus_addr;
  1271. msgs[nmsgs].flags = flags;
  1272. msgs[nmsgs].len = len;
  1273. if (len)
  1274. msgs[nmsgs].buf = xzalloc(len);
  1275. if (!(flags & I2C_M_RD)) {
  1276. /* Consume DATA arg(s) */
  1277. unsigned buf_idx = 0;
  1278. while (buf_idx < len) {
  1279. uint8_t data8;
  1280. unsigned long data;
  1281. arg_ptr = *++argv;
  1282. if (!arg_ptr)
  1283. bb_show_usage();
  1284. data = strtoul(arg_ptr, &end, 0);
  1285. if (data > 0xff || arg_ptr == end)
  1286. bb_error_msg_and_die("invalid data byte '%s'", *argv);
  1287. data8 = data;
  1288. while (buf_idx < len) {
  1289. msgs[nmsgs].buf[buf_idx++] = data8;
  1290. if (!*end)
  1291. break;
  1292. switch (*end) {
  1293. /* Pseudo randomness (8 bit AXR with a=13 and b=27) */
  1294. case 'p':
  1295. data8 = (data8 ^ 27) + 13;
  1296. data8 = (data8 << 1) | (data8 >> 7);
  1297. break;
  1298. case '+': data8++; break;
  1299. case '-': data8--; break;
  1300. case '=': break;
  1301. default:
  1302. bb_error_msg_and_die("invalid data byte suffix: '%s'",
  1303. *argv);
  1304. }
  1305. }
  1306. }
  1307. }
  1308. nmsgs++;
  1309. }
  1310. if (!(opts & opt_y))
  1311. confirm_action(bus_addr, 0, 0, 0);
  1312. rdwr.msgs = msgs;
  1313. rdwr.nmsgs = nmsgs;
  1314. nmsgs_sent = ioctl_or_perror_and_die(fd, I2C_RDWR, &rdwr, "I2C_RDWR");
  1315. if (nmsgs_sent < nmsgs)
  1316. bb_error_msg("warning: only %u/%u messages sent", nmsgs_sent, nmsgs);
  1317. for (i = 0; i < nmsgs_sent; i++) {
  1318. if (msgs[i].len != 0 && (msgs[i].flags & I2C_M_RD)) {
  1319. int j;
  1320. for (j = 0; j < msgs[i].len - 1; j++)
  1321. printf("0x%02x ", msgs[i].buf[j]);
  1322. /* Print final byte with newline */
  1323. printf("0x%02x\n", msgs[i].buf[j]);
  1324. }
  1325. }
  1326. # if ENABLE_FEATURE_CLEAN_UP
  1327. close(fd);
  1328. for (i = 0; i < nmsgs; i++)
  1329. free(msgs[i].buf);
  1330. # endif
  1331. return 0;
  1332. }
  1333. #endif /* ENABLE_I2CTRANSFER */