smartbook.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. // [START]{ SMARTBOOK CUSTOM CODE. TODO: move to standalone file
  2. // Original MHL driver use tabstop=4, this policy is followed here.
  3. #include <linux/delay.h>
  4. /*#include <mach/mt_gpio.h>*/
  5. #include <linux/interrupt.h>
  6. #include <linux/input.h>
  7. #include <linux/time.h>
  8. #include <linux/device.h>
  9. #include <linux/miscdevice.h>
  10. #include <asm/uaccess.h>
  11. #include <linux/power_supply.h>
  12. #include <linux/kthread.h>
  13. #include <linux/wakelock.h>
  14. #include <linux/timex.h>
  15. #include <linux/proc_fs.h>
  16. #include <linux/mutex.h>
  17. #include <linux/sched.h>
  18. #include <linux/module.h>
  19. #include <linux/cdev.h>
  20. /*#include "linux/aee.h"*/
  21. #include "si_fw_macros.h"
  22. #include "si_mhl_defs.h"
  23. #include "si_infoframe.h"
  24. #include "si_edid.h"
  25. #include "si_mhl2_edid_3d_api.h"
  26. #include "si_mhl_tx_hw_drv_api.h"
  27. #include "si_mdt_inputdev.h"
  28. #include "mhl_linux_tx.h"
  29. #include "mhl_supp.h"
  30. #include "smartbook.h"
  31. #include "mmprofile.h"
  32. struct SMB_MMP_Events_t
  33. {
  34. MMP_Event SmartBook;
  35. MMP_Event Keyboard_Ctrl;
  36. MMP_Event Keyboard_Normal;
  37. MMP_Event Mouse;
  38. }SMB_MMP_Events;
  39. #ifdef CONFIG_MTK_SMARTBOOK_SUPPORT
  40. extern int SiiHandshakeCommand(HandshakeType ComType);
  41. //extern bool_t PutPriorityCBusTransactionWrapper(cbus_req_t *preq);
  42. //extern bool_t PutPriorityCBusTransactionImpl(cbus_req_t *preq);
  43. extern struct mhl_dev_context *si_dev_context;
  44. #ifdef ENABLE_TX_DEBUG_PRINT
  45. #define PutPriorityCBusTransaction(req) PutPriorityCBusTransactionWrapper(req)
  46. #else
  47. #define PutPriorityCBusTransaction(req) PutPriorityCBusTransactionImpl(req)
  48. #endif
  49. static struct input_dev *smartbook_dev = NULL;
  50. // HID Buffer
  51. static uint8_t hidbi = 0; // HID buffer index
  52. static uint8_t hidbt = 0; // HID buffer tail
  53. static uint8_t hidbuf[HID_BUF * HID_SIZE]; // HID data ring buffer
  54. // Mouse
  55. static __u32 mouse_btns[] = { BTN_LEFT, BTN_MIDDLE, BTN_RIGHT }; // BTN_RIGHT
  56. int mouse_btn = 0;
  57. int HID_RES_X, HID_RES_Y = 0;
  58. /****************************Debug**********************************/
  59. const char print_mouse_btns[3][32] = {{"BTN_LEFT"}, {"BTN_MIDDLE"}, {"BTN_RIGHT"}};
  60. const char print_kb_modmap[8][32] = {{"KEY_LEFTCTRL"}, {"KEY_LEFTSHIFT"}, {"KEY_LEFTALT"}, {"KEY_HOMEPAGE"},
  61. {"KEY_RIGHTCTRL"}, {"KEY_RIGHTSHIFT"}, {"KEY_RIGHTALT"}, {"KEY_RIGHTMETA"}};
  62. const char print_kb_map[KB_LEN][32] = { // 10 keys per line. refer USB_HID_Usage_Table.pdf for this mapping
  63. {0},{0},{0},{0}, {"KEY_A"}, {"KEY_B"}, {"KEY_C"}, {"KEY_D"}, {"KEY_E"}, {"KEY_F"},
  64. {"KEY_G"}, {"KEY_H"}, {"KEY_I"}, {"KEY_J"}, {"KEY_K"}, {"KEY_L"}, {"KEY_M"}, {"KEY_N"}, {"KEY_O"}, {"KEY_P"},
  65. {"KEY_Q"}, {"KEY_R"}, {"KEY_S"}, {"KEY_T"}, {"KEY_U"}, {"KEY_V"}, {"KEY_W"}, {"KEY_X"}, {"KEY_Y"}, {"KEY_Z"},
  66. {"KEY_1"}, {"KEY_2"}, {"KEY_3"}, {"KEY_4"}, {"KEY_5"}, {"KEY_6"}, {"KEY_7"}, {"KEY_8"}, {"KEY_9"}, {"KEY_0"},
  67. {"KEY_ENTER"}, {"KEY_ESC"}, {"KEY_BACKSPACE"}, {"KEY_TAB"}, {"KEY_SPACE"}, {"EY_MINUS"}, {"KEY_EQUAL"}, {"KEY_LEFTBRACE"}, {"KEY_RIGHTBRACE"}, {"KEY_BACKSLASH"},
  68. {"KEY_GRAVE"}, {"KEY_SEMICOLON"}, {"KEY_APOSTROPHE"},{"KEY_GRAVE"}, {"KEY_COMMA"}, {"KEY_DOT"}, {"KEY_SLASH"}, {"KEY_CAPSLOCK"}, {"KEY_F1, KEY_F2"},
  69. {"KEY_F3"}, {"KEY_F4"}, {"KEY_F5"}, {"KEY_F6"}, {"KEY_F7"}, {"KEY_F8"}, {"KEY_F9"}, {"KEY_F10"}, {"KEY_F11"}, {"KEY_F12"},
  70. {"KEY_SYSRQ"}, {"KEY_SCROLLLOCK"},{"KEY_PAUSE"}, {"KEY_INSERT"}, {"KEY_HOME"}, {"KEY_PAGEUP"}, {"KEY_DELETE"}, {"KEY_END"}, {"KEY_PAGEDOWN"}, {"KEY_RIGHT"},
  71. {"KEY_LEFT"}, {"KEY_DOWN"}, {"KEY_UP"}, {"KEY_NUMLOCK"} ,{"KEY_KPSLASH"}, {"KEY_KPASTERISK"}, {"KEY_KPMINUS"}, {"KEY_KPPLUS"}, {"KEY_KPENTER"}, {"KEY_KP1"},
  72. {"KEY_KP2"}, {"KEY_KP3"}, {"KEY_KP4"}, {"KEY_KP5"}, {"KEY_KP6"}, {"KEY_KP7"}, {"KEY_KP8"}, {"KEY_KP9"}, {"KEY_KP0"}, {"KEY_KPDOT"},
  73. {"KEY_BACKSLASH"}, {"KEY_MENU"}, {"KEY_POWER"}, {"KEY_KPEQUAL"}, {"KEY_F13"}, {"KEY_F14"}, {"KEY_F15"}, {"KEY_F16"}, {"KEY_F17"}, {"KEY_F18"},
  74. {"KEY_F19"}, {"KEY_F20"}, {"KEY_F21"}, {"KEY_F22"}, {"KEY_F23"}, {"KEY_F24"}, {"KEY_PLAYPAUSE"}, {"KEY_HELP"}, {"KEY_MENU"}, {"KEY_SELECT"},
  75. {"KEY_STOP"}, {"KEY_AGAIN"}, {"KEY_UNDO"}, {"KEY_CUT"}, {"KEY_COPY"}, {"KEY_PASTE"}, {"KEY_FIND"}, {"KEY_MUTE"}, {"KEY_VOLUMEUP"}, {"KEY_VOLUMEDOWN"},
  76. {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
  77. {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
  78. {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
  79. {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
  80. {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
  81. {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
  82. {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, /*19x*/
  83. {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, /*20x*/
  84. {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, /*21x*/
  85. {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, /*22x*/
  86. {0}, {0}, {"KEY_BRIGHTNESSUP"}, {"KEY_BRIGHTNESSDOWN"}, {"KEY_FN_F1"}, {"KEY_FN_F2"}, {"KEY_FN_F3"}, {"KEY_FN_F4"}, {"KEY_FN_F5"}, {"KEY_FN_F6"},
  87. {"KEY_FN_F7"}, {"KEY_FN_F8"}, {"KEY_FN_F9"}, {"KEY_FN_F10"}, {"KEY_FN_F11"}, {"KEY_FN_F12"}, {0}, {0}, {0}, {0},
  88. };
  89. // Keyboard
  90. int kb_modifier = 0;
  91. int kb_codes[] = {0,0,0,0};
  92. const unsigned int kb_modmap[] = {
  93. KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_LEFTALT, KEY_HOMEPAGE,
  94. KEY_RIGHTCTRL, KEY_RIGHTSHIFT, KEY_RIGHTALT, KEY_RIGHTMETA
  95. };
  96. const unsigned int kb_map[KB_LEN] = { // 10 keys per line. refer USB_HID_Usage_Table.pdf for this mapping
  97. 0,0,0,0, KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F,
  98. KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, KEY_P,
  99. KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z,
  100. KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0,
  101. KEY_ENTER, KEY_ESC, KEY_BACKSPACE, KEY_TAB, KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE, KEY_RIGHTBRACE, KEY_BACKSLASH,
  102. KEY_GRAVE, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA, KEY_DOT, KEY_SLASH, KEY_CAPSLOCK, KEY_F1, KEY_F2,
  103. KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12,
  104. KEY_SYSRQ, KEY_SCROLLLOCK, KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGEUP, KEY_DELETE, KEY_END, KEY_PAGEDOWN, KEY_RIGHT,
  105. KEY_LEFT, KEY_DOWN, KEY_UP, KEY_NUMLOCK, KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS, KEY_KPPLUS, KEY_KPENTER, KEY_KP1,
  106. KEY_KP2, KEY_KP3, KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7, KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT,
  107. KEY_BACKSLASH, KEY_MENU, KEY_POWER, KEY_KPEQUAL, KEY_F13, KEY_F14, KEY_F15, KEY_F16, KEY_F17, KEY_F18,
  108. KEY_F19, KEY_F20, KEY_F21, KEY_F22, KEY_F23, KEY_F24, KEY_PLAYPAUSE/*can't find EXECUTE*/, KEY_HELP, KEY_MENU, KEY_SELECT,
  109. KEY_STOP, KEY_AGAIN, KEY_UNDO, KEY_CUT, KEY_COPY, KEY_PASTE, KEY_FIND, KEY_MUTE, KEY_VOLUMEUP, KEY_VOLUMEDOWN,
  110. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  111. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  112. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  113. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  114. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  115. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  116. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*19x*/
  117. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20x*/
  118. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*21x*/
  119. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*22x*/
  120. 0, 0, KEY_BRIGHTNESSUP, KEY_BRIGHTNESSDOWN, KEY_FN_F1, KEY_FN_F2, KEY_FN_F3, KEY_FN_F4, KEY_FN_F5, KEY_FN_F6,
  121. KEY_FN_F7, KEY_FN_F8, KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_FN_F12, 0, 0, 0, 0,
  122. };
  123. const unsigned char SourceID[ID_LEN] =
  124. {SMB_SOURCE_ID_0, SMB_SOURCE_ID_1, SMB_SOURCE_ID_2, SMB_SOURCE_ID_3, SMB_SOURCE_ID_4, SMB_SOURCE_ID_5};
  125. const unsigned char SinkID[ID_LEN] =
  126. {SMB_SINK_ID_0, SMB_SINK_ID_1, SMB_SINK_ID_2, SMB_SINK_ID_3, SMB_SINK_ID_4, SMB_SINK_ID_5};
  127. // Misc.
  128. wait_queue_head_t smartbook_wq;
  129. struct wake_lock smartbook_suspend_lock;
  130. int sbk_isSuspend = 0;
  131. //int deinit = 0;
  132. static DEFINE_MUTEX(smb_mutex);
  133. SinkType SinkStatus = NotConnect;
  134. #define PERF_MONITOR
  135. #ifdef PERF_MONITOR
  136. #define NUM_RECORD 5
  137. // Performance monitor facility
  138. int64_t GetTimeStamp(void){
  139. struct timeval tv;
  140. do_gettimeofday(&tv);
  141. return (tv.tv_sec & 0xff) * 1000000 + tv.tv_usec; /*convert to microsecond*/
  142. }
  143. void RecordStamp(bool dump, char tag){
  144. static int records = 0;
  145. int i;
  146. static int stamp[NUM_RECORD];
  147. static char name[NUM_RECORD];
  148. stamp[records] = (int)GetTimeStamp();
  149. name[records] = tag;
  150. records++;
  151. if(dump == true || records >= NUM_RECORD){
  152. for(i = 0; i < records; i++){
  153. smb_print("TimeStamp[%c]: %d\n", name[i], stamp[i]);
  154. stamp[i] = 0;
  155. name[i] = 0;
  156. }
  157. records = 0;
  158. }
  159. }
  160. #else
  161. void RecordStamp(bool dump, char tag){
  162. }
  163. #endif
  164. void Init_SMB_mmp_Events(void)
  165. {
  166. if (SMB_MMP_Events.SmartBook == 0)
  167. {
  168. smb_print("Init_SMB_mmp_Events\n");
  169. SMB_MMP_Events.SmartBook = MMProfileRegisterEvent(MMP_RootEvent, "SmartBook");
  170. SMB_MMP_Events.Keyboard_Ctrl = MMProfileRegisterEvent(SMB_MMP_Events.SmartBook, "Keyboard_Ctrl");
  171. SMB_MMP_Events.Keyboard_Normal = MMProfileRegisterEvent(SMB_MMP_Events.SmartBook, "Keyboard_Normal");
  172. SMB_MMP_Events.Mouse = MMProfileRegisterEvent(SMB_MMP_Events.SmartBook, "Mouse");
  173. MMProfileEnableEventRecursive(SMB_MMP_Events.SmartBook, 1);
  174. }
  175. }
  176. static int smartbook_init(int flag) {
  177. int err, i;
  178. if(smartbook_dev==NULL) {
  179. HID_RES_X = simple_strtoul(CONFIG_LCM_WIDTH, NULL, 0);///LCM_WIDTH
  180. HID_RES_Y = simple_strtoul(CONFIG_LCM_HEIGHT, NULL, 0);///LCM_HEIGHT
  181. smartbook_dev = input_allocate_device();
  182. if (!smartbook_dev) {
  183. smb_print("smartbook_dev: Not enough memory\n");
  184. return -ENOMEM;
  185. }
  186. smartbook_dev->name = "sbk-kpd";
  187. smartbook_dev->id.bustype = BUS_HOST;
  188. smartbook_dev->id.vendor = 0x2454;
  189. smartbook_dev->id.product = 0x6589;
  190. smartbook_dev->id.version = 0x0001;
  191. set_bit(EV_KEY, smartbook_dev->evbit); // for kpd and mouse
  192. //set_bit(EV_ABS, smartbook_dev->evbit);
  193. set_bit(EV_REL, smartbook_dev->evbit); // for mouse
  194. set_bit(REL_X, smartbook_dev->relbit);
  195. set_bit(REL_Y, smartbook_dev->relbit);
  196. set_bit(REL_WHEEL, smartbook_dev->relbit);
  197. set_bit(BTN_LEFT, smartbook_dev->keybit);
  198. set_bit(BTN_MIDDLE, smartbook_dev->keybit);
  199. set_bit(BTN_RIGHT, smartbook_dev->keybit);
  200. set_bit(KEY_BACK, smartbook_dev->keybit);
  201. set_bit(BTN_MOUSE, smartbook_dev->keybit);
  202. for(i=0;i<KB_LEN;i++) set_bit(kb_map[i], smartbook_dev->keybit);
  203. for(i=0;i<KB_MODLEN;i++) set_bit(kb_modmap[i], smartbook_dev->keybit);
  204. }
  205. if(flag!=0) {
  206. err = input_register_device(smartbook_dev);
  207. smb_print("plug-in into smartbook, register input_dev\n");
  208. SinkStatus = MonitorTV;
  209. if(err) {
  210. smb_print("smartbook_dev: Failed to register device\n");
  211. input_free_device(smartbook_dev);
  212. return err;
  213. }
  214. } else {
  215. //deinit = 1;
  216. hidbi = 0;
  217. hidbt = 0;
  218. input_unregister_device(smartbook_dev);
  219. smb_print("plug-out from smartbook, unregister input_dev\n");
  220. smartbook_dev = NULL;
  221. if(SinkStatus == SmartBook){
  222. smb_print("call smartbook disconnection\n");
  223. }
  224. SinkStatus = NotConnect;
  225. //deinit = 0;
  226. // remove battery status when MHL connection is break
  227. update_battery_2nd_info(POWER_SUPPLY_STATUS_NOT_CHARGING, 0, 0);
  228. smb_print("MHL connection break\n");
  229. }
  230. Init_SMB_mmp_Events();
  231. return 0;
  232. }
  233. SinkType SMBGetSinkStatus(){
  234. return SinkStatus;
  235. }
  236. /*#ifdef SMARTBOOK_CRYPTO
  237. static void smartbook_crypt(unsigned char mid, unsigned char cpc) {
  238. unsigned char cps[6], enc;
  239. unsigned int i;
  240. for(i=0;i<6;i++) {
  241. enc = cpc;
  242. enc = enc & methods[mid];
  243. enc = enc ^ (enc >> 4);
  244. enc = enc ^ (enc >> 2);
  245. enc = enc ^ (enc >> 1);
  246. cpc = ( cpc << 1 ) | (enc & 1);
  247. cps[i] = cpc;
  248. }
  249. for(i=hidbi+2;i<hidbi+8;i++) {
  250. hidbuf[i] = hidbuf[i] ^ cps[i-2];
  251. }
  252. return 0;
  253. }
  254. #endif*/
  255. /*void SiiSendCbusWriteBurst(unsigned char *bufp, int length){
  256. int i;
  257. cbus_req_t req;
  258. req.command = MHL_WRITE_BURST;
  259. req.length = length;
  260. req.offsetData = SCRATCHPAD_OFFSET; // scratchpad offset (Don't modify it)
  261. req.payload_u.pdatabytes = bufp;
  262. //mutex_lock(&smb_mutex);
  263. //SiiMhlTxDrvSendCbusCommand(&req);
  264. PutNextCBusTransaction(&req);
  265. //mutex_unlock(&smb_mutex);
  266. }*/
  267. int SiiHandshakeCommand(HandshakeType ComType){
  268. int i;
  269. bool error = false;
  270. HIDCommand comm;
  271. //req.command = MHL_WRITE_BURST;
  272. //req.length = WRITEBURST_MAX_LEN;
  273. //req.offsetData = SCRATCHPAD_OFFSET; // scratchpad offset (Don't modify it)
  274. comm.category = CA_MISC;
  275. comm.command = MISC_HANDSHAKE;
  276. switch(ComType){
  277. case Init:
  278. for(i = 0; i < ID_LEN; i++){
  279. comm.payload[i] = SourceID[i];
  280. }
  281. smb_print("handshake Init\n");
  282. break;
  283. case Ack:
  284. for(i = 0; i < ID_LEN; i++){
  285. comm.payload[i] = 0x0;
  286. }
  287. break;
  288. default:
  289. error = true;
  290. break;
  291. }
  292. if(error == false){
  293. //PutPriorityCBusTransaction(&req);
  294. //SiiMhlTxDrvSendCbusCommand(&req);
  295. si_mhl_tx_request_write_burst(si_dev_context, 0, WRITEBURST_MAX_LEN, (uint8_t *)&comm);
  296. }
  297. }
  298. int SiiSendScreenCommand(ScreenOffType ComType, unsigned int downCountSec){
  299. bool error = false;
  300. HIDCommand comm;
  301. //req.command = MHL_WRITE_BURST;
  302. //req.length = 4;
  303. //req.offsetData = SCRATCHPAD_OFFSET; // scratchpad offset (Don't modify it)
  304. comm.category = CA_PMU;
  305. comm.command = PMU_SCREEN;
  306. switch(ComType){
  307. case ImmediateOff:
  308. comm.payload[0] = 0xC0;
  309. comm.payload[1] = 0x0;
  310. break;
  311. case DownCount:
  312. comm.payload[0] = 0x80 + ((downCountSec & 0x3f00) >> 8);
  313. comm.payload[1] = (downCountSec & 0xff);
  314. break;
  315. case CancelDownCount:
  316. comm.payload[0] = 0x0;
  317. comm.payload[1] = 0x0;
  318. break;
  319. default:
  320. error = true;
  321. break;
  322. }
  323. if(error == false){
  324. si_mhl_tx_request_write_burst(si_dev_context, 0, 4, (uint8_t *)&comm);
  325. }
  326. }
  327. int SiiLatencyCommand(){
  328. bool error = false;
  329. struct timeval tv;
  330. int64_t count;
  331. HIDCommand comm;
  332. //req.command = MHL_WRITE_BURST;
  333. //req.length = 5;
  334. //req.offsetData = SCRATCHPAD_OFFSET; // scratchpad offset (Don't modify it)
  335. comm.category = CA_MISC;
  336. comm.command = MISC_LATENCY;
  337. do_gettimeofday(&tv);
  338. count = tv.tv_sec*1000 + tv.tv_usec/1000;
  339. comm.payload[0] = 0x1; // plug-in code ID, don't care on the sink side
  340. comm.payload[1] = (unsigned char)((count & 0xff00) >> 8);
  341. comm.payload[2] = (unsigned char)(count & 0xff);
  342. if(error == false){
  343. si_mhl_tx_request_write_burst(si_dev_context, 0, 5, (uint8_t *)&comm);
  344. }
  345. }
  346. static void smartbook_kb(void) {
  347. int i, j, kcode;
  348. uint8_t *chidbuf = &(hidbuf[hidbi]);
  349. int mod_update = kb_modifier ^ chidbuf[2];
  350. if(chidbuf[3]==0x1 && chidbuf[4]==0x1 && chidbuf[5]==0x1) return;
  351. for(i=0;i<8;i++) {
  352. if(mod_update&(1<<i)) {
  353. input_report_key(smartbook_dev, kb_modmap[i], ((chidbuf[2]&(1<<i))?1:0));
  354. smb_mmp_print(SMB_MMP_Events.Keyboard_Ctrl, MMProfileFlagPulse, ((chidbuf[2]&(1<<i))?1:0), kb_modmap[i], print_kb_modmap[i]);
  355. }
  356. }
  357. kb_modifier = chidbuf[2];
  358. for(i=3;i<7;i++) {
  359. if(chidbuf[i]==0) break;
  360. for(j=0;j<4;j++) if(kb_codes[j]==chidbuf[i]) break;
  361. if(j==4) {
  362. //smb_print("Press HID KeyCode: %d\n", (int)chidbuf[i]);
  363. kcode = kb_map[chidbuf[i]<KB_LEN?chidbuf[i]:0];
  364. input_report_key(smartbook_dev, kcode, 1);
  365. smb_print("Press ScanCode: %d\n", kcode);
  366. smb_mmp_print(SMB_MMP_Events.Keyboard_Normal, MMProfileFlagPulse, 1, kcode, print_kb_map[chidbuf[i]]);
  367. //for aee dump temp solution
  368. if(kcode == KEY_4 && ((chidbuf[2] & 0x5) == 0x5 || (chidbuf[2] & 0x50) == 0x50)) {
  369. /*aee_kernel_reminding("manual dump", "CTRL + ALT + 4 to trigger dump");*/
  370. }
  371. }
  372. else kb_codes[j] = 0;
  373. }
  374. for(i=0;i<4;i++) if(kb_codes[i]) {
  375. kcode = kb_map[kb_codes[i]];
  376. input_report_key(smartbook_dev, kcode, 0);
  377. smb_mmp_print(SMB_MMP_Events.Keyboard_Normal, MMProfileFlagPulse, 0, kcode, print_kb_map[kb_codes[i]]);
  378. }
  379. for(i=0;i<4;i++) kb_codes[i] = chidbuf[i+3];
  380. input_sync(smartbook_dev);
  381. }
  382. static void smartbook_mouse(void) {
  383. int x,y,z,i,tmp_btn;
  384. uint8_t *chidbuf = &(hidbuf[hidbi]);
  385. x = ((chidbuf[3]<<8)&0xff00) + (chidbuf[4]&0xff);
  386. y = ((chidbuf[5]<<8)&0xff00) + (chidbuf[6]&0xff);
  387. z = chidbuf[7];
  388. tmp_btn = mouse_btn ^ chidbuf[2];
  389. if(x>>15) x=-(((~x)&0xfff)+1);
  390. if(y>>15) y=-(((~y)&0xfff)+1);
  391. if(z>>7) z=-(((~z)&0x0ff)+1);
  392. if(x<-100 || x>100 || y<-100 || y>100) return;
  393. mouse_btn = chidbuf[2];
  394. x = x * 2; y = y * 2;
  395. for(i=0;i<3;i++)
  396. if(tmp_btn&(1<<i))
  397. {
  398. input_report_key(smartbook_dev, mouse_btns[i], chidbuf[2]&(1<<i));
  399. smb_mmp_print(SMB_MMP_Events.Mouse, MMProfileFlagPulse, chidbuf[2]&(1<<i), mouse_btns[i], print_mouse_btns[i]);
  400. }
  401. input_report_rel(smartbook_dev, REL_X, x);
  402. input_report_rel(smartbook_dev, REL_Y, y);
  403. input_report_rel(smartbook_dev, REL_WHEEL, z);
  404. smb_print("Update Mouse: %d %d %d %d\n", x, y, z, mouse_btn);
  405. input_sync(smartbook_dev);
  406. }
  407. static void smartbook_battery(void) {
  408. uint8_t *chidbuf = &(hidbuf[hidbi]);
  409. int charge_status = ((chidbuf[2] & 0x80)?1:0);
  410. int sbk_power_level = chidbuf[2] & 0x7f;
  411. smb_print("sbk_power_level: %d \n", sbk_power_level);
  412. update_battery_2nd_info(
  413. (sbk_power_level==100?
  414. POWER_SUPPLY_STATUS_FULL:
  415. (charge_status?
  416. POWER_SUPPLY_STATUS_CHARGING:
  417. POWER_SUPPLY_STATUS_NOT_CHARGING)),
  418. sbk_power_level,
  419. 1
  420. );
  421. //SendCommand = true;
  422. }
  423. static void smartbook_handshake(void) {
  424. uint8_t *chidbuf = &(hidbuf[hidbi]);
  425. //int i;
  426. // skip category & command , total 2 bytes
  427. chidbuf += 2;
  428. /*for(i = 2; i < ID_LEN; i++){
  429. if(chidbuf[i] != SinkID[i]){
  430. smb_print("Compare ID Fail, i: %d, content: %d\n", i, chidbuf[i]);
  431. //SinkStatus = Unknown;
  432. return ;
  433. }
  434. }*/
  435. if(SinkStatus != SmartBook) {
  436. smb_print("Identify Sink is Smartbook!\n");
  437. SinkStatus = SmartBook;
  438. SiiHandshakeCommand(Ack);
  439. }
  440. }
  441. static void smartbook_latency(void) {
  442. uint8_t *chidbuf = &(hidbuf[hidbi]);
  443. int timestamp = (chidbuf[3] << 8) + chidbuf[4];
  444. smb_print("Latency: %d\n", timestamp);
  445. //SiiLatencyCommand();
  446. }
  447. // Called in component/mhl_tx/si_mhl_tx.c, when plug / unplug MHL
  448. void SiiHidSuspend(int flag) {
  449. if(sbk_isSuspend == flag) return;
  450. mutex_lock(&smb_mutex);
  451. sbk_isSuspend = flag;
  452. smartbook_init(flag);
  453. mutex_unlock(&smb_mutex);
  454. wake_up_interruptible(&smartbook_wq);
  455. }
  456. // Read data from Registers, write them to HID Buffer
  457. int SiiHidWrite(uint8_t *scratchpad_data) {
  458. uint8_t *chidbuf = &(hidbuf[hidbt]);
  459. if(!smartbook_dev) return 0;
  460. if(unlikely(HID_RES_Y==0)) smartbook_init(1);
  461. //SiiRegReadBlock(REG_CBUS_SCRATCHPAD_0 + 8, chidbuf, HID_SIZE);
  462. memcpy(chidbuf, scratchpad_data, HID_SIZE);
  463. smb_print("Writeburst: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
  464. chidbuf[0], chidbuf[1], chidbuf[2], chidbuf[3], chidbuf[4], chidbuf[5], chidbuf[6], chidbuf[7]);
  465. hidbt = (hidbt + HID_SIZE)%(HID_SIZE * HID_BUF);
  466. if(unlikely(hidbi==hidbt)) {
  467. smb_print("MHL Hid Ring buf Overflow. ");
  468. hidbi = (hidbt + HID_SIZE)%(HID_SIZE * HID_BUF);
  469. }
  470. wake_up_interruptible(&smartbook_wq);
  471. return 0;
  472. }
  473. // Read data from HID Buffer
  474. int SiiHidRead(void) {
  475. uint8_t *chidbuf = &(hidbuf[hidbi]);
  476. if(chidbuf[0]==1 && chidbuf[1]==2) smartbook_mouse();
  477. else if (chidbuf[0]==1 && chidbuf[1]==3) smartbook_kb();
  478. else if (chidbuf[0]==0x80 && chidbuf[1]==3) smartbook_battery();
  479. else if (chidbuf[0]==0x2 && chidbuf[1]==0xaa) smartbook_latency();
  480. else if (chidbuf[0]==0x2) smartbook_handshake();
  481. hidbi = (hidbi + HID_SIZE)%(HID_SIZE * HID_BUF);
  482. return 0;
  483. }
  484. // HID kthread offload ISR's tasks. ISR --> Kthread by HID Buffer
  485. int smartbook_kthread(void *data) {
  486. struct sched_param param;
  487. int retval = 0;
  488. //adjust priority
  489. param.sched_priority = 94; /*RTPM_PRIO_SCRN_UPDATE*/
  490. sched_setscheduler(current, SCHED_RR, &param);
  491. while(1) {
  492. if(hidbt==hidbi) { // ring buffer empty
  493. set_current_state(TASK_INTERRUPTIBLE);
  494. retval = wait_event_interruptible_timeout(smartbook_wq, hidbt!=hidbi , 5*HZ);
  495. set_current_state(TASK_RUNNING);
  496. }
  497. mutex_lock(&smb_mutex);
  498. if(smartbook_dev && retval!=0 && hidbt!=hidbi) SiiHidRead(); // not timeout
  499. mutex_unlock(&smb_mutex);
  500. if (kthread_should_stop()) break;
  501. }
  502. return 0;
  503. }
  504. static int SMBSinkTypeRead(char *buf, char **start, off_t off, int count, int *eof, void *data)
  505. {
  506. int len = 0;
  507. char *p = buf;
  508. switch(SinkStatus){
  509. case NotConnect:
  510. p += sprintf(p, "N\n");
  511. break;
  512. case SmartBook:
  513. p += sprintf(p, "S\n");
  514. break;
  515. case MonitorTV:
  516. p += sprintf(p, "M\n");
  517. break;
  518. case Unknown:
  519. p += sprintf(p, "U\n");
  520. break;
  521. default:
  522. p += sprintf(p, "error\n");
  523. break;
  524. }
  525. len = p - buf;
  526. return len;
  527. }
  528. static int SMBScreenCommandRead(char *buf, char **start, off_t off, int count, int *eof, void *data)
  529. {
  530. /*int len = 0;
  531. char *p = buf;
  532. if (mt_gpufreq_debug)
  533. p += sprintf(p, "gpufreq debug enabled\n");
  534. else
  535. p += sprintf(p, "gpufreq debug disabled\n");
  536. len = p - buf;
  537. return len;*/
  538. return 0;
  539. }
  540. static ssize_t SMBScreenCommandWrite(struct file *file, const char *buffer, size_t count, loff_t * off)
  541. {
  542. int comType = 0, countTime = 0;
  543. if (sscanf(buffer, "%d %d", &comType, &countTime) == 2 && smartbook_dev != NULL)
  544. {
  545. if(comType >= ImmediateOff && comType <= CancelDownCount){
  546. SiiSendScreenCommand(comType, countTime);
  547. smb_print("SendScreenCommand: %d %d\n", comType, countTime);
  548. return count;
  549. }
  550. }
  551. else if (smartbook_dev == NULL){
  552. smb_print("Smartbook is not connected! \n");
  553. }
  554. else {
  555. smb_print("SendScreenCommand fail!\n");
  556. }
  557. return -EINVAL;
  558. }
  559. static const struct file_operations screen_fops = {
  560. .owner = THIS_MODULE,
  561. .read = NULL,
  562. .write = SMBScreenCommandWrite,
  563. };
  564. static int __init smb_init(void)
  565. {
  566. //struct proc_dir_entry *entry = NULL;
  567. struct proc_dir_entry *smb_dir = NULL;
  568. smb_dir = proc_mkdir("smb", NULL);
  569. if (!smb_dir)
  570. {
  571. smb_print("[%s]: mkdir /proc/smb failed\n", __FUNCTION__);
  572. }
  573. else
  574. {
  575. proc_create("ScreenComm", S_IRUGO | S_IWUSR | S_IWGRP, smb_dir, &screen_fops);
  576. }
  577. return 0;
  578. }
  579. late_initcall(smb_init);
  580. #endif