dualwave.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. /**
  2. * @file dualwave.c
  3. * $Author: sirius.park@samsung.com $
  4. * Communication Solution Lab. DM R&D Center,
  5. * SAMSUNG ELECTRONICS CO., LTD.
  6. * $URL: $
  7. * $Revision: $
  8. *
  9. * @brief if some file write operation is occured, the uevent will be delivered to user app which listen those information
  10. * Time Write Location : /sys/kerenl/DualWave/sound/PLAY_TIME, /sys/kerenl/DualWave/sound/CAPTURE_TIME
  11. * Time Format : %ld.%09ld (ex. 1.123123123, 1.100000000)
  12. * note> if 1.1 is inserted, that value is understood to 1.000000001. so keep the format
  13. * uevent Format : %ld.%09ld (ex. CAPTURE_TIME=2.000000001)
  14. *
  15. * @see
  16. * Copyright 2014 by Samsung Electronics, Inc.,
  17. *
  18. */
  19. #include <linux/module.h>
  20. #include <net/sock.h>
  21. #include <linux/netlink.h>
  22. #include <linux/skbuff.h>
  23. #include <linux/kobject.h>
  24. #include <linux/time.h>
  25. #include <linux/jiffies.h>
  26. #include <linux/timer.h>
  27. #define MAX_DUALWAVE_MESSAGE_SIZE 1024
  28. #define PRINT_TIMEFORMAT_STRING "%ld.%09ld"
  29. #define PRINT_CONFIG_FORMAT "%d"
  30. #define PRINT_CONFIG_FORMAT_STRING "DUALWAVE_ENABLED="PRINT_CONFIG_FORMAT
  31. #define PRINT_UEVNET_FORMAT_STRING "%s="PRINT_TIMEFORMAT_STRING
  32. #define SND_AVAIL_STRING "SND_AVAIL=%d"
  33. ///////////////////////////////////////////////////////////////////////////////////////////////////
  34. // Local Data Structures
  35. struct dualwave_attribute{
  36. struct attribute attr;
  37. // operations
  38. ssize_t (*show) (struct dualwave_attribute *attr, char *buf);
  39. ssize_t (*store)(struct dualwave_attribute *attr, const char *buf, size_t count);
  40. // value
  41. struct timespec tTime;
  42. int tConfig;
  43. };
  44. // End of local Data Structures
  45. ///////////////////////////////////////////////////////////////////////////////////////////////////
  46. ///////////////////////////////////////////////////////////////////////////////////////////////////
  47. // Local Functions
  48. // attributes related functions
  49. #ifdef _DULAWAVE_TIME_INFO
  50. static ssize_t show_my_attr_info (struct dualwave_attribute *attr, char *buf);
  51. static ssize_t store_info_to_attr(struct dualwave_attribute *attr, const char *buf, size_t count);
  52. #endif
  53. static ssize_t show_my_config (struct dualwave_attribute *attr, char *buf);
  54. static ssize_t store_my_config(struct dualwave_attribute *attr, const char *buf, size_t count);
  55. // dualwave kobj sysfs operations
  56. static ssize_t dualwave_attr_show(struct kobject *, struct attribute *,char *);
  57. static ssize_t dualwave_attr_store(struct kobject *,struct attribute *,const char *, size_t);
  58. // dualwave kobj release operations
  59. static void dualwave_release(struct kobject *kobj);
  60. // send time uevent to USER APP
  61. int send_uevent_wh_timeinfo(const char *szName, struct timespec *ptTime);
  62. static int err_status = 0;
  63. // End of local function definitions
  64. ///////////////////////////////////////////////////////////////////////////////////////////////////
  65. ///////////////////////////////////////////////////////////////////////////////////////////////////
  66. // glbal variables
  67. #define DUALWAVE_INACTIVE 0
  68. #define DUALWAVE_PLAYBACK 1
  69. #define DUALWAVE_CAPTURE 2
  70. //#define TIMER_VALUE (10*HZ)
  71. #define TIMER_VALUE msecs_to_jiffies(10000)
  72. struct timer_list expTimer;
  73. void expTimer_service(unsigned long arg);
  74. static struct kobject *g_ptDualWaveKobj = NULL;
  75. static struct kset *g_ptDualWaveKset=NULL;
  76. static int g_iEnableUpdateSoundTime = DUALWAVE_INACTIVE;
  77. //static struct kset *g_ptKset=NULL;
  78. // the operations for kobject
  79. static const struct sysfs_ops dualwave_sysfs_ops = {
  80. .show = dualwave_attr_show,
  81. .store = dualwave_attr_store,
  82. };
  83. // set private attribute information.
  84. #if 0
  85. static struct dualwave_attribute playtime_attribute =
  86. __ATTR(PLAY_TIME, 0664, show_my_attr_info, store_info_to_attr);
  87. static struct dualwave_attribute capture_attribute =
  88. __ATTR(CAPTURE_TIME, 0664, show_my_attr_info, store_info_to_attr);
  89. #endif
  90. static struct dualwave_attribute config_attribute =
  91. __ATTR(DUALWAVE_CONFIG, 0664, show_my_config, store_my_config);
  92. // the attr member of private attriubte structure is only registered to default_attrs
  93. static struct attribute *dualwave_attrs[] = {
  94. #if 0
  95. &playtime_attribute.attr,
  96. &capture_attribute.attr,
  97. #endif
  98. &config_attribute.attr,
  99. NULL, /* need to NULL terminate the list of attributes */
  100. };
  101. static struct kobj_type g_tKobjType = {
  102. .sysfs_ops = &dualwave_sysfs_ops,
  103. .release = dualwave_release,
  104. .default_attrs = dualwave_attrs,
  105. };
  106. void expTimer_service(unsigned long arg){
  107. g_iEnableUpdateSoundTime = DUALWAVE_INACTIVE;
  108. config_attribute.tConfig = 0;
  109. printk(KERN_INFO "khhan %s %d\n", __func__, __LINE__);
  110. }
  111. /**
  112. * @fn ssize_t dualwave_attr_show(struct kobject *ptKobj, struct attribute *ptAttr,char *pBuf)
  113. * @brief called whenever some file read operation in DualWave/sound is occured
  114. *
  115. * @param kobject *ptKobj
  116. * @param attribute *ptAttr
  117. * @param *pBuf
  118. * @return ssize_t
  119. * @warning
  120. */
  121. ssize_t dualwave_attr_show(struct kobject *ptKobj, struct attribute *ptAttr,char *pBuf)
  122. {
  123. struct dualwave_attribute *ptDualWaveAttr;
  124. //printk(KERN_INFO "khhan %s %d\n", __func__, __LINE__);
  125. // get dualwave structure pointer
  126. ptDualWaveAttr = container_of(ptAttr,struct dualwave_attribute , attr);
  127. if (!ptDualWaveAttr->show)
  128. return -EIO;
  129. // call the function of the operations linked to this attribute file
  130. return ptDualWaveAttr->show(ptDualWaveAttr, pBuf);
  131. }
  132. /**
  133. * @fn ssize_t dualwave_attr_store(struct kobject *ptKobj,struct attribute *ptAttr,const char *pBuf, size_t nLen)
  134. * @brief called whenever some file write operation in DualWave/sound is occured
  135. *
  136. * @param kobject *ptKobj
  137. * @param attribute *ptAttr
  138. * @param char *pBuf
  139. * @param nLen
  140. * @return ssize_t
  141. * @warning
  142. */
  143. ssize_t dualwave_attr_store(struct kobject *ptKobj,struct attribute *ptAttr,const char *pBuf, size_t nLen)
  144. {
  145. struct dualwave_attribute *ptDualWaveAttr;
  146. //printk(KERN_INFO "khhan %s %d\n", __func__, __LINE__);
  147. // get dualwave structure pointer
  148. ptDualWaveAttr = container_of(ptAttr,struct dualwave_attribute , attr);
  149. if (!ptDualWaveAttr->store)
  150. return -EIO;
  151. // call the function of the operations linked to this attribute file
  152. return ptDualWaveAttr->store(ptDualWaveAttr, pBuf, nLen);
  153. }
  154. /**
  155. * @fn static void dualwave_release(struct kobject *kobj)
  156. * @brief called whenever some release operation in DualWave/sound is occured
  157. *
  158. * @param kobject *kobj
  159. * @return static
  160. * @warning
  161. */
  162. static void dualwave_release(struct kobject *kobj)
  163. {
  164. printk(KERN_INFO "khhan %s %d\n", __func__, __LINE__);
  165. kfree(kobj);
  166. }
  167. #if 0
  168. /**
  169. * @fn static ssize_t show_my_attr_info (struct dualwave_attribute *attr, char *buf)
  170. * @brief just show current time information for debugging
  171. *
  172. * @param dualwave_attribute *attr
  173. * @param *buf
  174. * @return static
  175. * @warning
  176. */
  177. static ssize_t show_my_attr_info (struct dualwave_attribute *attr, char *buf)
  178. {
  179. printk(KERN_INFO "khhan %s %d\n", __func__, __LINE__);
  180. return sprintf(buf, PRINT_TIMEFORMAT_STRING "\n", attr->tTime.tv_sec,attr->tTime.tv_nsec);
  181. }
  182. #endif
  183. #if 0
  184. /**
  185. * @fn static ssize_t store_info_to_attr(struct dualwave_attribute *attr, const char *buf, size_t count)
  186. * @brief send uevent to user appp with time information. the time informatin will be saved in module
  187. *
  188. * @param dualwave_attribute *attr
  189. * @param char *buf
  190. * @param count
  191. * @return ssize_t
  192. * @warning
  193. */
  194. static ssize_t store_info_to_attr(struct dualwave_attribute *attr, const char *buf, size_t count)
  195. {
  196. printk(KERN_INFO "khhan %s %d\n", __func__, __LINE__);
  197. sscanf(buf, PRINT_TIMEFORMAT_STRING, &attr->tTime.tv_sec, &attr->tTime.tv_nsec);
  198. send_uevent_wh_timeinfo(attr->attr.name, &attr->tTime);
  199. return count;
  200. }
  201. #endif
  202. static ssize_t show_my_config (struct dualwave_attribute *attr, char *buf)
  203. {
  204. //printk(KERN_INFO "khhan %s %d\n", __func__, __LINE__);
  205. //return sprintf(buf, PRINT_CONFIG_FORMAT "\n",g_iEnableUpdateSoundTime );
  206. return sprintf(buf, PRINT_CONFIG_FORMAT_STRING "\n", attr->tConfig);
  207. }
  208. static ssize_t store_my_config(struct dualwave_attribute *attr, const char *buf, size_t count)
  209. {
  210. //printk(KERN_INFO "khhan %s %d\n", __func__, __LINE__);
  211. sscanf(buf, PRINT_CONFIG_FORMAT, &attr->tConfig);
  212. switch(attr->tConfig){
  213. case 0:
  214. attr->tConfig = 0;
  215. g_iEnableUpdateSoundTime = DUALWAVE_INACTIVE;
  216. //if(timer_pending(&expTimer)) {
  217. del_timer(&expTimer);
  218. printk(KERN_INFO "khhan del timer %s %d\n", __func__, __LINE__);
  219. break;
  220. case 1:
  221. attr->tConfig = 1;
  222. g_iEnableUpdateSoundTime = DUALWAVE_PLAYBACK;
  223. mod_timer(&expTimer, jiffies + TIMER_VALUE);
  224. printk(KERN_INFO "khhan modifying timer %s %d\n", __func__, __LINE__);
  225. break;
  226. case 2:
  227. attr->tConfig = 2;
  228. g_iEnableUpdateSoundTime = DUALWAVE_CAPTURE;
  229. mod_timer(&expTimer, jiffies + TIMER_VALUE);
  230. printk(KERN_INFO "khhan modifying timer %s %d\n", __func__, __LINE__);
  231. break;
  232. default:
  233. attr->tConfig = 0;
  234. g_iEnableUpdateSoundTime = DUALWAVE_INACTIVE;
  235. count = -1;
  236. printk(KERN_INFO "khhan ***** wrong status %s %d ***** \n", __func__, __LINE__);
  237. }
  238. return count;
  239. }
  240. int checkDualWaveStatus(void)
  241. {
  242. return g_iEnableUpdateSoundTime;
  243. }
  244. EXPORT_SYMBOL(checkDualWaveStatus);
  245. #if 0
  246. void setDualWaveFunction(int bEnable)
  247. {
  248. if (!bEnable)
  249. {
  250. g_iEnableUpdateSoundTime= DUALWAVE_FALSE;
  251. } else
  252. {
  253. g_iEnableUpdateSoundTime= DUALWAVE_TRUE;
  254. }
  255. }
  256. EXPORT_SYMBOL(setDualWaveFunction);
  257. #endif
  258. /**
  259. * @fn static int send_uevent_wh_timeinfo(const char *szName, struct timespec *ptTime)
  260. * @brief send the played or captured time info to user application via uevent \n
  261. * string format is like as follows \n
  262. * \n
  263. * change@/kernel/DualWave/sound \n
  264. * ACTION=change \n
  265. * DEVPATH=/kernel/DualWave/sound \n
  266. * SUBSYSTEM=DualWave \n
  267. * CAPTURE_TIME=2.000000001 \n
  268. * SEQNUM=3260 \n
  269. *
  270. * @param char *szName the type of time info (PLAY_TIME or CAPTURE_TIME)
  271. * @param timespec *ptTime the time information
  272. * @return static
  273. * @warning
  274. */
  275. int send_uevent_wh_timeinfo(const char *szName, struct timespec *ptTime)
  276. {
  277. char *pEnvp[2];
  278. char *prBuf;
  279. int retval;
  280. #if 0 // this flag will be checked the caller side
  281. if(likely(g_iEnableUpdateSoundTime == DUALWAVE_FALSE))
  282. {
  283. return 0;
  284. }
  285. #endif
  286. printk(KERN_INFO "khhan %s %d\n", __func__, __LINE__);
  287. prBuf = kzalloc(MAX_DUALWAVE_MESSAGE_SIZE, GFP_KERNEL);
  288. if(prBuf == NULL)
  289. {
  290. printk(KERN_INFO "khhan ***** failed to alloc memory for dualwave message buffer %s %d ***** \n", __func__, __LINE__);
  291. return -1;
  292. }
  293. pEnvp[0] = prBuf;
  294. pEnvp[1] = NULL;
  295. sprintf(prBuf, PRINT_UEVNET_FORMAT_STRING,szName, ptTime->tv_sec, ptTime->tv_nsec);
  296. retval = kobject_uevent_env(g_ptDualWaveKobj, KOBJ_CHANGE, pEnvp) ;
  297. if(retval)
  298. {
  299. printk(KERN_INFO "khhan ***** failed to call kobject_event (%d) %s %d ***** \n", retval, __func__, __LINE__);
  300. kfree(prBuf);
  301. return -1;
  302. }
  303. kfree(prBuf);
  304. return 0 ;
  305. }
  306. EXPORT_SYMBOL(send_uevent_wh_timeinfo);
  307. int send_uevent_wh_ble_info(char *prEnvInfoLists[3])
  308. {
  309. int retval;
  310. printk(KERN_INFO "khhan %s %d\n", __func__, __LINE__);
  311. // prBuf = kzalloc(MAX_DUALWAVE_MESSAGE_SIZE, GFP_KERNEL);
  312. // if(prBuf == NULL)
  313. // {
  314. // printk("[DualWave] failed to alloc memory for dualwave message buffer\n\n");
  315. // return -1;
  316. // }
  317. // pEnvp[0] = prBuf;
  318. // pEnvp[1] = NULL;
  319. // sprintf(prBuf, PRINT_UEVNET_FORMAT_STRING,szName, ptTime->tv_sec, ptTime->tv_nsec);
  320. retval = kobject_uevent_env(g_ptDualWaveKobj, KOBJ_CHANGE, prEnvInfoLists) ;
  321. if(retval)
  322. {
  323. printk(KERN_INFO "khhan ***** failed to call kobject_event (%d) %s %d ***** \n", retval, __func__, __LINE__);
  324. return -1;
  325. }
  326. // kfree(prBuf);
  327. return 0 ;
  328. }
  329. EXPORT_SYMBOL(send_uevent_wh_ble_info);
  330. int send_uevent_snd_avail(int state)
  331. {
  332. char *pEnvp[2];
  333. char *prBuf;
  334. int retval;
  335. printk(KERN_INFO "khhan %s %d\n", __func__, __LINE__);
  336. prBuf = kzalloc(MAX_DUALWAVE_MESSAGE_SIZE, GFP_KERNEL);
  337. if(prBuf == NULL)
  338. {
  339. printk(KERN_INFO "khhan ***** failed to alloc memory for dualwave message buffer %s %d ***** \n", __func__, __LINE__);
  340. return -1;
  341. }
  342. pEnvp[0] = prBuf;
  343. pEnvp[1] = NULL;
  344. sprintf(prBuf, SND_AVAIL_STRING, state);
  345. retval = kobject_uevent_env(g_ptDualWaveKobj, KOBJ_CHANGE, pEnvp) ;
  346. if(retval)
  347. {
  348. printk(KERN_INFO "khhan ***** failed to call kobject_event (%d) %s %d ***** \n", retval, __func__, __LINE__);
  349. kfree(prBuf);
  350. return -1;
  351. }
  352. kfree(prBuf);
  353. return 0 ;
  354. }
  355. EXPORT_SYMBOL(send_uevent_snd_avail);
  356. /**
  357. * @fn static int __init dualwave_init(void)
  358. * @brief register module,
  359. *
  360. * @param void
  361. * @return int
  362. * @warning the code for registering to udev is not implemented
  363. */
  364. static int __init dualwave_init(void)
  365. {
  366. // struct kobj_uevent_env *env;
  367. int retval;
  368. static const char *SOUND_DIR="sound";
  369. printk(KERN_INFO "khhan Entering %s %d\n", __func__, __LINE__);
  370. init_timer(&expTimer);
  371. expTimer.expires = jiffies + TIMER_VALUE;
  372. expTimer.data = (unsigned long) NULL;
  373. expTimer.function = expTimer_service;
  374. add_timer(&expTimer);
  375. // Create kset: this is located in /sys/kernel/DualWave
  376. // This is required to send uevent. if kset is not existed, kobecjt_uevent will be failed
  377. g_ptDualWaveKset = kset_create_and_add("DualWave", NULL, kernel_kobj);
  378. //g_ptDualWaveKset = kset_create_and_add("DualWave", NULL, mkobj);
  379. if (!g_ptDualWaveKset)
  380. {
  381. printk(KERN_INFO "khhan ***** failed to execute kobject_create_and_add %s %d ***** \n", __func__, __LINE__);
  382. err_status = -1;
  383. return -EEXIST;
  384. }
  385. g_ptDualWaveKobj = kzalloc(sizeof(*g_ptDualWaveKobj), GFP_KERNEL);
  386. if(g_ptDualWaveKobj == NULL)
  387. {
  388. printk(KERN_INFO "khhan ***** failed to kobj kzalloc %s %d ***** \n", __func__, __LINE__);
  389. err_status = -2;
  390. return -ENOMEM;
  391. }
  392. // set the parent
  393. g_ptDualWaveKobj->kset = g_ptDualWaveKset;
  394. // Create kobject: this is located in /sys/kernel/DualWave/sound
  395. retval = kobject_init_and_add(g_ptDualWaveKobj,&g_tKobjType,NULL,"%s",SOUND_DIR);
  396. if (retval)
  397. {
  398. kset_put(g_ptDualWaveKset);
  399. printk(KERN_INFO "khhan ***** failed to kobj init and add %s %d ***** \n", __func__, __LINE__);
  400. err_status = -3;
  401. kfree(g_ptDualWaveKobj);
  402. return -1;
  403. }
  404. // send uevent for testing
  405. retval = kobject_uevent(g_ptDualWaveKobj, KOBJ_ADD);
  406. if(retval)
  407. {
  408. printk(KERN_INFO "khhan ***** failed to call kobject_event (%d) %s %d ***** \n", retval, __func__, __LINE__);
  409. err_status = -4;
  410. kfree(g_ptDualWaveKobj);
  411. return -1;
  412. }
  413. err_status = 0;
  414. return 0;
  415. }
  416. /**
  417. * @fn static void __exit dualwave_exit(void){
  418. * @brief remove module
  419. *
  420. * @param void
  421. * @return static
  422. * @warning
  423. */
  424. static void __exit dualwave_exit(void){
  425. printk(KERN_INFO "khhan exiting module %s %d \n", __func__, __LINE__);
  426. del_timer_sync(&expTimer);
  427. kobject_put(g_ptDualWaveKobj);
  428. kset_put(g_ptDualWaveKset);
  429. kfree(g_ptDualWaveKobj);
  430. }
  431. module_init(dualwave_init);
  432. module_exit(dualwave_exit);
  433. MODULE_LICENSE("GPL");